Trustme: #1 quality TLS certs while you wait

Overview

trustme: #1 quality TLS certs while you wait

https://vignette2.wikia.nocookie.net/jadensadventures/images/1/1e/Kaa%27s_hypnotic_eyes.jpg/revision/latest?cb=20140310173415

You wrote a cool network client or server. It encrypts connections using TLS. Your test suite needs to make TLS connections to itself.

Uh oh. Your test suite probably doesn't have a valid TLS certificate. Now what?

trustme is a tiny Python package that does one thing: it gives you a fake certificate authority (CA) that you can use to generate fake TLS certs to use in your tests. Well, technically they're real certs, they're just signed by your CA, which nobody trusts. But you can trust it. Trust me.

Vital statistics

Install: pip install -U trustme

Documentation: https://trustme.readthedocs.io

Bug tracker and source code: https://github.com/python-trio/trustme

Tested on: Python 3.6+, CPython and PyPy

License: MIT or Apache 2, your choice.

Code of conduct: Contributors are requested to follow our code of conduct in all project spaces.

Cheat sheet

Programmatic usage:

import trustme

# ----- Creating certs -----

# Look, you just created your certificate authority!
ca = trustme.CA()

# And now you issued a cert signed by this fake CA
# https://en.wikipedia.org/wiki/Example.org
server_cert = ca.issue_cert(u"test-host.example.org")

# That's it!

# ----- Using your shiny new certs -----

# You can configure SSL context objects to trust this CA:
ca.configure_trust(ssl_context)
# Or configure them to present the server certificate
server_cert.configure_cert(ssl_context)
# You can use standard library or PyOpenSSL context objects here,
# trustme is happy either way.

# ----- or -----

# Save the PEM-encoded data to a file to use in non-Python test
# suites:
ca.cert_pem.write_to_path("ca.pem")
server_cert.private_key_and_cert_chain_pem.write_to_path("server.pem")

# ----- or -----

# Put the PEM-encoded data in a temporary file, for libraries that
# insist on that:
with ca.cert_pem.tempfile() as ca_temp_path:
    requests.get("https://...", verify=ca_temp_path)

Command line usage:

$ # Certs may be generated from anywhere. Here's where we are:
$ pwd
/tmp
$ # ----- Creating certs -----
$ python -m trustme
Generated a certificate for 'localhost', '127.0.0.1', '::1'
Configure your server to use the following files:
  cert=/tmp/server.pem
  key=/tmp/server.key
Configure your client to use the following files:
  cert=/tmp/client.pem
$ # ----- Using certs -----
$ gunicorn --keyfile server.key --certfile server.pem app:app
$ curl --cacert client.pem https://localhost:8000/
Hello, world!

FAQ

Should I use these certs for anything real? Certainly not.

Why not just use self-signed certificates? These are more realistic. You don't have to disable your certificate validation code in your test suite, which is good because you want to test what you run in production, and you would never disable your certificate validation code in production, right? Plus, they're just as easy to work with. Actually easier, in many cases.

What if I want to test how my code handles some bizarre TLS configuration? We think trustme hits a sweet spot of ease-of-use and generality as it is. The defaults are carefully chosen to work on all major operating systems and be as fast as possible. We don't want to turn trustme into a second-rate re-export of everything in cryptography. If you have more complex needs, consider using them directly, possibly starting from the trustme code.

Will you automate installing CA cert into system trust store? No. mkcert already does this well, and we would not have anything to add.

Comments
  • Issue client cert

    Issue client cert

    Hi,

    It'd be nice to have a public API for creating client certificates as well. Just like issue_server_cert() but issue_client_cert().

    It's useful when testing client cert TLS auth in frameworks.

    opened by webknjaz 20
  • Support intermediate CAs

    Support intermediate CAs

    I tried to address #3.

    It does not seem to work, though. Test with:

    import trustme
    
    ca = trustme.CA()
    ca = ca.create_child_ca()
    server_cert = ca.issue_server_cert(u"test-host.example.org")
    
    server_cert.private_key_and_cert_chain_pem.write_to_path("server.pem")
    

    When commenting the ca = ca.create_child_ca() line, openssl verify -untrusted server.pem server.pem says:

    server.pem: O = "trustme v0.4.0+dev", OU = Testing server cert #XukT8k24PBXQBSqv
    error 20 at 0 depth lookup:unable to get local issuer certificate
    

    But with the create_child_ca line, we get:

    server.pem: O = "trustme v0.4.0+dev", OU = Testing CA #D2vixR6eI2g5N2k5
    error 19 at 1 depth lookup:self signed certificate in certificate chain
    

    I have no idea what I'm doing: what's the problem? I did try to make sure to only self-sign the root CA and not including it in the server.pem file.

    opened by pquentin 12
  • Add expires option

    Add expires option

    This PR adds the option to specify when the issued client certificate should expire (Not After field). It's specified in the style of <number>t, where t can be H (hour), m (month), d (days), etc...

    While adding this feature, I also found that the client and server certs were being written to the wrong paths. An included commit resolves this.

    opened by herbygillot 11
  • Add trustme command line interface

    Add trustme command line interface

    Closes #257, Closes https://github.com/sethmlarson/trustme-cli/issues/1

    This pull request ports trustme-cli to trustme itself.

    Included

    • [x] Port of $ trustme-cli command line program, as $ python -m trustme
    • [x] Docs
    • [x] Tests

    Unit tests are lightweight and basically just verify that options are accepted, though they don't actually try to do anything with the generated certs. Let me know if we should be more precise there. :-)

    Sample usage

    $ python -m trustme
    Generated a certificate for 'localhost', '127.0.0.1', '::1'
    Configure your server to use the following files:
      cert=/Users/florimond/Developer/python-projects/trustme/server.pem
      key=/Users/florimond/Developer/python-projects/trustme/server.key
    Configure your client to use the following files:
      cert=/Users/florimond/Developer/python-projects/trustme/client.pem
    

    Docs preview

    Screenshot 2020-12-22 at 13 25 15

    FireShot Capture 021 - trustme_ #1 quality TLS certs while you wait — trustme 0 6 0+dev docu_ - localhost

    enhancement 
    opened by florimondmanca 10
  • EC keys in trustme.

    EC keys in trustme.

    Added support to specify in EllipticCurve as key_type for the CA or a issues certificate. Basic test case for round trip added.

    It would be useful to have that in trustme for my own testing of my TLS work in the Apache web server. Maybe it is not the most beautiful python, all faults are mine.

    opened by icing 9
  • CHANGE EVERYTHING

    CHANGE EVERYTHING

    Now instead of having methods to return a ssl.SSLContext object, we have methods that take an ssl.SSLContext object and reconfigure it in place. This is more flexible and probably fits better into existing codebases.

    Plus, it makes it easy to support PyOpenSSL without lots of awkward namespacing!

    I'm still not 100% happy with the phrasing of

    ca.trust(ctx)
    server_cert.use(ctx)
    

    because the subject/object seem backwards.

    Maybe they should be top-level functions? Or have better names? ca.trust_me(ctx), cert.use_me(ctx), ca.trusted_by(ctx), cert.used_by(ctx)?

    opened by njsmith 8
  • Failure on 32 bit Linux

    Failure on 32 bit Linux

    When building aiohttp binary wheels we run tests on built files. On 32 bit Linux it produces the following error:

    
        @pytest.fixture
        def tls_certificate_authority():
    >       return trustme.CA()
    
    io/tests/conftest.py:25: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    opt/_internal/cpython-3.5.6/lib/python3.5/site-packages/trustme/__init__.py:212: in __init__
        backend=default_backend(),
    opt/_internal/cpython-3.5.6/lib/python3.5/site-packages/cryptography/x509/base.py:595: in sign
        return backend.create_x509_certificate(self, private_key, algorithm)
    opt/_internal/cpython-3.5.6/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py:804: in create_x509_certificate
        self._lib.X509_get_notAfter(x509_cert), builder._not_valid_after
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    
    self = <cryptography.hazmat.backends.openssl.backend.Backend object at 0xf6e759ec>
    asn1_time = <cdata 'struct asn1_string_st *' 0x90f5ab0>
    time = datetime.datetime(3000, 1, 1, 0, 0)
    
        def _set_asn1_time(self, asn1_time, time):
            timestamp = calendar.timegm(time.timetuple())
    >       res = self._lib.ASN1_TIME_set(asn1_time, timestamp)
    E       OverflowError: integer 32503680000 does not fit '32-bit int'
    
    opt/_internal/cpython-3.5.6/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py:840: OverflowError
    

    @njsmith do you have an idea how to fix it?

    opened by asvetlov 7
  • Set correct KU and EKU extensions

    Set correct KU and EKU extensions

    A CA certificate must not have an EKU extension. KU key_cert_signing is required. crl_sign is recommended for CRLs and digital_signature is recommended for OCSP.

    An end-entity cert must have an EKU. TLS server and TLS client are recommended. KU digital_signature is required for modern perfect forward secrecy handshake. key_encipherment is optional for old non-PFS handshake.

    Signed-off-by: Christian Heimes [email protected]

    opened by tiran 6
  • Publish test results in the AppVeyor UI

    Publish test results in the AppVeyor UI

    This change includes #220 adding one commit on top (see the second commit).

    Here's how the tests show up in the AppVeyor UI: https://ci.appveyor.com/project/njsmith/trustme/builds/34322432/job/rygsb2do5tkmtmxc/tests.

    opened by webknjaz 6
  • Allow specifying organization and organization unit in CA and issuer certs

    Allow specifying organization and organization unit in CA and issuer certs

    Hi,

    First of all, I'd like to thank you for creating this project that'll prevent me from writing a lot of boilerplate code.

    The only feature I'm missing right now is the ability to customize the organization name and the organization unit name from the CA certificate and from issued certificates. Do you think this is acceptable?

    Thank you again!

    opened by gilbsgilbs 6
  • Add CA.from_pem

    Add CA.from_pem

    Part of my work on https://github.com/urllib3/urllib3/issues/1705. The goal is to start using trustme more in urllib3, but by doing it gradually, and only switch to a trustme-generated CA at the end of the process.

    opened by pquentin 6
  • Bump pytest from 7.1.2 to 7.2.0

    Bump pytest from 7.1.2 to 7.2.0

    Bumps pytest from 7.1.2 to 7.2.0.

    Release notes

    Sourced from pytest's releases.

    7.2.0

    pytest 7.2.0 (2022-10-23)

    Deprecations

    • #10012: Update pytest.PytestUnhandledCoroutineWarning{.interpreted-text role="class"} to a deprecation; it will raise an error in pytest 8.

    • #10396: pytest no longer depends on the py library. pytest provides a vendored copy of py.error and py.path modules but will use the py library if it is installed. If you need other py.* modules, continue to install the deprecated py library separately, otherwise it can usually be removed as a dependency.

    • #4562: Deprecate configuring hook specs/impls using attributes/marks.

      Instead use :pypytest.hookimpl{.interpreted-text role="func"} and :pypytest.hookspec{.interpreted-text role="func"}. For more details, see the docs <legacy-path-hooks-deprecated>{.interpreted-text role="ref"}.

    • #9886: The functionality for running tests written for nose has been officially deprecated.

      This includes:

      • Plain setup and teardown functions and methods: this might catch users by surprise, as setup() and teardown() are not pytest idioms, but part of the nose support.
      • Setup/teardown using the @​with_setup decorator.

      For more details, consult the deprecation docs <nose-deprecation>{.interpreted-text role="ref"}.

    Features

    • #9897: Added shell-style wildcard support to testpaths.

    Improvements

    • #10218: @pytest.mark.parametrize() (and similar functions) now accepts any Sequence[str] for the argument names, instead of just list[str] and tuple[str, ...].

      (Note that str, which is itself a Sequence[str], is still treated as a comma-delimited name list, as before).

    • #10381: The --no-showlocals flag has been added. This can be passed directly to tests to override --showlocals declared through addopts.

    • #3426: Assertion failures with strings in NFC and NFD forms that normalize to the same string now have a dedicated error message detailing the issue, and their utf-8 representation is expresed instead.

    • #7337: A warning is now emitted if a test function returns something other than [None]{.title-ref}. This prevents a common mistake among beginners that expect that returning a [bool]{.title-ref} (for example [return foo(a, b) == result]{.title-ref}) would cause a test to pass or fail, instead of using [assert]{.title-ref}.

    • #8508: Introduce multiline display for warning matching via :pypytest.warns{.interpreted-text role="func"} and enhance match comparison for :py_pytest._code.ExceptionInfo.match{.interpreted-text role="func"} as returned by :pypytest.raises{.interpreted-text role="func"}.

    • #8646: Improve :pypytest.raises{.interpreted-text role="func"}. Previously passing an empty tuple would give a confusing error. We now raise immediately with a more helpful message.

    • #9741: On Python 3.11, use the standard library's tomllib{.interpreted-text role="mod"} to parse TOML.

      tomli{.interpreted-text role="mod"}` is no longer a dependency on Python 3.11.

    • #9742: Display assertion message without escaped newline characters with -vv.

    • #9823: Improved error message that is shown when no collector is found for a given file.

    ... (truncated)

    Commits
    • 3af3f56 Prepare release version 7.2.0
    • bc2c3b6 Merge pull request #10408 from NateMeyvis/patch-2
    • d84ed48 Merge pull request #10409 from pytest-dev/asottile-patch-1
    • ffe49ac Merge pull request #10396 from pytest-dev/pylib-hax
    • d352098 allow jobs to pass if codecov.io fails
    • c5c562b Fix typos in CONTRIBUTING.rst
    • d543a45 add deprecation changelog for py library vendoring
    • f341a5c Merge pull request #10407 from NateMeyvis/patch-1
    • 1027dc8 [pre-commit.ci] auto fixes from pre-commit.com hooks
    • 6b905ee Add note on tags to CONTRIBUTING.rst
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 1
  • Public API to retrieve cert key and cert chain files written to the fs separately

    Public API to retrieve cert key and cert chain files written to the fs separately

    Usually at high-level web servers expose separate configuration options for a certificate file, a private key file, and a certificate chain file.

    Currently trustme forces users to use one file for both certificate file and its key file (as it https://github.com/aio-libs/aiohttp/commit/c180800a4c90dc123d05311edbec92a3a82d6317#diff-3ba621217225120eff2c061666b8043cR284) and use CA cert for chain option.

    From the API perspective, it looks confusing to any humble human being who isn't proficient in TLS.

    When one looks at such tests they're puzzled: why options named explicitly as key and cert receive the same var? maybe it's a bug? what's going on here? Same for cert chain: why does it look like instead of some mysterious chain file there's a certificate or the CA?

    Proofs:

    • https://github.com/cherrypy/cheroot/blob/d31adfe/cheroot/ssl/init.py#L24
    • https://github.com/cherrypy/cheroot/blob/d31adfe/cheroot/ssl/builtin.py#L91
    • https://github.com/cherrypy/cheroot/blob/d31adfe/cheroot/ssl/pyopenssl.py#L241
    • https://github.com/cherrypy/cherrypy/blob/e10b984/cherrypy/_cpserver.py#L104-L112
    • https://github.com/aio-libs/aiohttp/blob/master/aiohttp/worker.py#L188-L191
    • https://github.com/pallets/flask/blob/master/flask/cli.py#L733-L738

    I think this use case deserves corresponding public APIs in place. What do you think?

    opened by webknjaz 2
  • Add a public API to calculate fingerprints of LeafCert instances

    Add a public API to calculate fingerprints of LeafCert instances

    So I've been finally integrating trustme into aiohttp's test today. Turns out that certificate fingerprint calculation isn't well-documented on the Internet for Python stdlib's ssl module. All examples use pyOpenSSL instead. So after fighting it for a while, I've figured out that one should turn certificate into DER format as opposed to PEM (ssl.PEM_cert_to_DER_cert()), because it's what SSLSocket.getpeercert() returns and what client uses to calculate hash: https://github.com/aio-libs/aiohttp/commit/c180800a4c90dc123d05311edbec92a3a82d6317#diff-484462fced51d1a06b1d93b4a44dd535R69

    Ref: https://github.com/aio-libs/aiohttp/blob/c9dabcb/aiohttp/client_reqrep.py#L105-L136

    So I think it'd be nice to wrap it into a method bound to LeafCert (and maybe Blob?). The suggested API is:

    # fingerprint calc function wrapped with `lru_cache`
    LeafCert.make_fingerprint(hash_function='sha256')
    
    # @properties:
    LeafCert.sha256_fingerprint
    LeafCert.sha1_fingerprint
    LeafCert.md5_fingerprint
    

    Maybe fingerprint would need to be represented by its own Fingerprint class, not just some bytes.

    opened by webknjaz 4
  • Follow CAFB guidelines more closely?

    Follow CAFB guidelines more closely?

    There are a bunch of ways we aren't really following CAFB rules. Not sure how much it matters. But for example:

    7.1.2.1 rules for root certificates:

    • SHOULD NOT set path_length
    • MUST include keyUsage
      • MUST be marked critical
      • MUST have keyCertSign and cRLSign set

    7.1.4.3 CA certificates:

    • MUST have a common name, organization name, and country name

    7.1.2.3 subscriber certificates:

    • MUST have certificatePolicies
    • MUST have extKeyUsage

    We might have some RFC 5280 fails too, I haven't read it carefully.

    opened by njsmith 3
A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps

boring-flutter A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps. Currently only supporting

Hamza 64 Oct 18, 2022
SSL / TLS Checking Tool written in Python3

ssts-chk SSL / TLS Checking Tool written in Python3. This tool will perform the following functions: Connect the target given Analyze the secure conne

Douglas Berdeaux 2 Feb 12, 2022
A gui application used for network reconnaissance while pentesting

netrecon A gui application used for network reconnaissance while pentesting

Krisna Pranav 4 Sep 3, 2022
Vulnerability Scanner & Auto Exploiter You can use this tool to check the security by finding the vulnerability in your website or you can use this tool to Get Shells

About create a target list or select one target, scans then exploits, done! Vulnnr is a Vulnerability Scanner & Auto Exploiter You can use this tool t

Nano 108 Dec 4, 2021
A wordlist generator tool, that allows you to supply a set of words, giving you the possibility to craft multiple variations from the given words, creating a unique and ideal wordlist to use regarding a specific target.

A wordlist generator tool, that allows you to supply a set of words, giving you the possibility to craft multiple variations from the given words, creating a unique and ideal wordlist to use regarding a specific target.

Cycurity 39 Dec 10, 2022
Consolidating and extending hosts files from several well-curated sources. You can optionally pick extensions to block pornography, social media, and other categories.

Take Note! With the exception of issues and PRs regarding changes to hosts/data/StevenBlack/hosts, all other issues regarding the content of the produ

Steven Black 22.1k Jan 2, 2023
SpiderFoot automates OSINT collection so that you can focus on analysis.

SpiderFoot is an open source intelligence (OSINT) automation tool. It integrates with just about every data source available and utilises a range of m

Steve Micallef 9k Jan 8, 2023
Profil3r is an OSINT tool that allows you to find potential profiles of a person on social networks, as well as their email addresses 🕵️

Profil3r is an OSINT tool that allows you to find potential profiles of a person on social networks, as well as their email addresses. This program also alerts you to the presence of a data leak for the found emails.

null 1.1k Aug 24, 2021
Midas ELF64 Injector is a tool that will help you inject a C program from source code into an ELF64 binary.

Midas ELF64 Injector Description Midas ELF64 Injector is a tool that will help you inject a C program from source code into an ELF64 binary. All you n

midas 20 Dec 24, 2022
You can manage your password with this program.

You must have Python compilers in order to run this program. First of all, download the compiler in the link.

Mustafa Bahadır Doğrusöz 6 Aug 7, 2021
adb - A tool that allows you to search for vulnerable android devices across the world and exploit them.

adb - An exploitation tool for android devices. A tool that allows you to search for vulnerable android devices across the world and exploit them. Fea

null 136 Jan 2, 2023
The probability of having the password you want in the PassMaker is +90%!!

PasswordMaker Strong listing password Introduction The probability of having the password you want in the tool is +90%!! How to Install Open the termi

MasterBurnt 4 Sep 5, 2021
Discord exploit allowing you to be unbannable.

Discord-Ban-Immunity Discord exploit allowing you to be unbannable. 9/3/2021 Found in late August. Found by Passive and Me. Explanation If a user gets

orlando 9 Nov 23, 2022
Let's you scan the entire internet in a couple of hours and identify all Minecraft servers on IPV4

Minecraft-Server-Scanner Let's you scan the entire internet in a couple of hours and identify all Minecraft servers on IPV4 Installation and running i

null 116 Jan 8, 2023
PasswordManager is a command-line program that helps you manage your secret files like passwords

PasswordManager is a command-line program that helps you manage your secret files like passwords. It's very minimalistic and easy to use.

Michael 3 Dec 30, 2021
JS Deobfuscation is a Python script that deobfuscate JS code and it's time saver for you.

JS Deobfuscation is a Python script that deobfuscate JS code and it's time saver for you. Although it may not work with high degrees of obfuscation, it's a pretty nice tool to help you even if it's just a bit.

Quatrecentquatre 3 May 1, 2022
A python tool capable of creating HUGE wordlists. Has the ability to add custom words for concatenation in any way you see fit.

A python tool capable of creating HUGE wordlists. Has the ability to add custom words for concatenation in any way you see fit.

Codex 9 Oct 5, 2022
On the 11/11/21 the apache 2.4.49-2.4.50 remote command execution POC has been published online and this is a loader so that you can mass exploit servers using this.

ApacheRCE ApacheRCE is a small little python script that will allow you to input the apache version 2.4.49-2.4.50 and then input a list of ip addresse

null 3 Dec 4, 2022
NexScanner is a tool which allows you to scan a website and find the admin login panel and sub-domains

NexScanner NexScanner is a tool which helps you scan a website for sub-domains and also to find login pages in the website like the admin login panel

null 8 Sep 3, 2022