Coder Social home page Coder Social logo

python-trio / trustme Goto Github PK

View Code? Open in Web Editor NEW
542.0 542.0 28.0 785 KB

#1 quality TLS certs while you wait, for the discerning tester

Home Page: https://trustme.rtfd.io

License: Other

Shell 2.43% Python 97.57%
python ssl ssl-certificate testing testing-tools tls tls-certificate

trustme's People

Contributors

basak avatar bluetech avatar bmwiedemann avatar dependabot-preview[bot] avatar dependabot[bot] avatar florimondmanca avatar gilbsgilbs avatar graingert avatar herbygillot avatar hramezani avatar illia-v avatar kianmeng avatar njsmith avatar oremanj avatar pquentin avatar rsommer avatar smurfix avatar tipabu avatar tiran avatar vincentvanlaer avatar vladdoster avatar webknjaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

trustme's Issues

Adapt to cryptography 2.7's deprecations

https://travis-ci.org/python-trio/trio/jobs/540515155:

../../../../virtualenv/python3.6.7/lib/python3.6/site-packages/trio/tests/test_ssl.py:52: in <module>
    TRIO_TEST_1_CERT = TRIO_TEST_CA.issue_server_cert("trio-test-1.example.org")
../../../../virtualenv/python3.6.7/lib/python3.6/site-packages/trustme/__init__.py:359: in issue_cert
    ski),
../../../../virtualenv/python3.6.7/lib/python3.6/site-packages/cryptography/x509/extensions.py:202: in from_issuer_subject_key_identifier
    stacklevel=2,
E   cryptography.utils.CryptographyDeprecationWarning: Extension objects are deprecated as arguments to from_issuer_subject_key_identifier and support will be removed soon. Please migrate to passing a SubjectKeyIdentifier directly.

Intermediate CA

These days most actual certs are signed by intermediate CA's, and certificate chain issues are common failures. Would you accept a pull request that adds intermediate CA functionality to trustme?

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?

feature request (with provided source code) - training wheels

I spent a couple hours try to figure out how to use your amazing library to do server certificates only.

Once I finally got it working, I decided to encapsulate the logic and I came up with the following.

Perhaps you would be interested in adding something like this to your library:

# trustme.training_wheels.py
import ssl
import trustme

class ServerOnly:
	def __init__ ( self, *,
		server_hostname: str, # ex: 'test-host.example.org'
	) -> None:
		self.server_hostname = server_hostname
		self.ca = trustme.CA()
		self.server_cert = self.ca.issue_cert ( self.server_hostname )
	
	def server_context ( self ) -> ssl.SSLContext:
		ctx = ssl.create_default_context()
		ctx.check_hostname = False
		self.server_cert.configure_cert ( ctx )
		self.ca.configure_trust ( ctx )
		ctx.verify_mode = ssl.CERT_NONE
		return ctx
	
	def client_context ( self ) -> ssl.SSLContext:
		ctx = ssl.create_default_context()
		self.ca.configure_trust ( ctx )
		return ctx

class ClientServer:
	def __init__ ( self, *,
		client_hostname: str, # ex: '[email protected]'
		server_hostname: str, # ex: 'test-host.example.org'
	) -> None:
		self.client_hostname = client_hostname
		self.server_hostname = server_hostname
		self.ca = trustme.CA()
		self.client_cert = self.ca.issue_cert ( self.client_hostname )
		self.server_cert = self.ca.issue_cert ( self.server_hostname )
	
	def server_context ( self ) -> ssl.SSLContext:
		ctx = ssl.create_default_context ( ssl.Purpose.CLIENT_AUTH )
		self.server_cert.configure_cert ( ctx )
		self.ca.configure_trust ( ctx )
		ctx.verify_mode = ssl.CERT_REQUIRED
		return ctx
	
	def client_context ( self ) -> ssl.SSLContext:
		ctx = ssl.create_default_context()
		self.ca.configure_trust ( ctx )
		self.client_cert.configure_cert ( ctx )
		return ctx

And then new users could use it like so:

# trustme-trio-example.py

import trustme.training_wheels
import trio
import ssl

# Create our fake certificates
trust = trustme.training_wheels.ClientServer (
	client_hostname = '[email protected]',
	server_hostname = 'test-host.example.org',
)

async def demo_server(server_raw_stream):
    server_ssl_context = trust.server_context()

    server_ssl_stream = trio.SSLStream(
        server_raw_stream,
        server_ssl_context,
        server_side=True,
    )

    # Send some data to check that the connection is really working
    await server_ssl_stream.send_all(b"x")
    print("Server successfully sent data over the encrypted channel!")
    print("Client cert looks like:", server_ssl_stream.getpeercert())


async def demo_client(client_raw_stream):
    client_ssl_context = trust.client_context()

    client_ssl_stream = trio.SSLStream(
        client_raw_stream,
        client_ssl_context,
        # Tell the client that it's looking for a trusted cert for this
        # particular hostname (must match what we passed to issue_cert)
        server_hostname="test-host.example.org",
    )

    assert await client_ssl_stream.receive_some(1) == b"x"
    print("Client successfully received data over the encrypted channel!")
    print("Server cert looks like:", client_ssl_stream.getpeercert())


async def main():
    from trio.testing import memory_stream_pair
    server_raw_stream, client_raw_stream = memory_stream_pair()

    async with trio.open_nursery() as nursery:
        nursery.start_soon(demo_server, server_raw_stream)
        nursery.start_soon(demo_client, client_raw_stream)


trio.run(main)

Automate installing CA cert into system trust store?

Based on the current "command line usage" section of the Cheat Sheet, it looks like trustme can do almost everything needed to be a full replacement for mkcert: The gunicorn demo is a great example of using the certs trustme generates with a web server, but the curl --cacert example of client-side usage stops short of showing how to use trustme for web development, where clients are browsers. (Compare to mkcert, whose README includes screenshots of browsers, indicating this is a key use case it addresses.) Is this because trustme deliberately wants to avoid making it easy for users to install the CA certs that it can generate into the system trust store? (Is trustme focusing more on programmatic usage to support integration tests?) Or is there interest in having trustme support this use case better?

Relatedly, would it be worth adding something to the docs explaining which use cases trustme is focusing on vs. other tools such as mkcert?

Thanks for the great work on trustme and Trio!!

v0.2.0 broken on Windows

Due to openssl limitations: pyca/cryptography#3194

Need to reduce our cert validity period. How much? Not clear. MSDN says that "_gmtime64, which uses the __time64_t structure, enables dates to be expressed up through 23:59:59, December 31, 3000, UTC, whereas _gmtime32 only represent dates through 23:59:59 January 18, 2038, UTC.", so probably one of those is the limit.

Dependabot can't resolve your Python dependency files

Dependabot can't resolve your Python dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Could not find a version that satisfies the requirement pyparsing==2.4.1 (from packaging==19.0->sphinx==2.1.2->sphinxcontrib-trio==1.1.0->-r ci/rtd-requirements.in (line 1)) (from versions: 1.4.6, 1.4.7, 1.4.8, 1.4.11, 1.5.0, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 2.0.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.0.7, 2.1.0, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.1.5, 2.1.6, 2.1.7, 2.1.8, 2.1.9, 2.1.10, 2.2.0, 2.2.1, 2.2.2, 2.3.0, 2.3.1, 2.4.0, 2.4.1.1, 2.4.2a1)
Traceback (most recent call last):
  File "/usr/local/.pyenv/versions/3.7.3/bin/pip-compile", line 10, in <module>
    sys.exit(cli())
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/scripts/compile.py", line 350, in cli
    results = resolver.resolve(max_rounds=max_rounds)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/resolver.py", line 164, in resolve
    has_changed, best_matches = self._resolve_one_round()
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/resolver.py", line 259, in _resolve_one_round
    their_constraints.extend(self._iter_dependencies(best_match))
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/resolver.py", line 354, in _iter_dependencies
    dependencies = self.repository.get_dependencies(ireq)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/repositories/local.py", line 66, in get_dependencies
    return self.repository.get_dependencies(ireq)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/repositories/pypi.py", line 270, in get_dependencies
    download_dir, ireq, wheel_cache
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/repositories/pypi.py", line 229, in resolve_reqs
    results = resolver._resolve_one(reqset, ireq)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 294, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 242, in _get_abstract_dist_for
    self.require_hashes
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/operations/prepare.py", line 282, in prepare_linked_requirement
    req.populate_link(finder, upgrade_allowed, require_hashes)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/req/req_install.py", line 198, in populate_link
    self.link = finder.find_requirement(self, upgrade)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/index.py", line 792, in find_requirement
    'No matching distribution found for %s' % req
pip._internal.exceptions.DistributionNotFound: No matching distribution found for pyparsing==2.4.1 (from packaging==19.0->sphinx==2.1.2->sphinxcontrib-trio==1.1.0->-r ci/rtd-requirements.in (line 1))

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

You can mention @dependabot in the comments below to contact the Dependabot team.

Allow setting the CN field

Traditionally, there are two fields inside a cert that computers look at when checking its identity: subjectAlternativeName (SAN) and commonName (CN). CN is a single bare string, and its deprecated because the interpretation is ambiguous. SAN is a list of typed objects ("hostname", "ip", "email address", etc.), and what you're supposed to use these days.

Currently trustme only fills in the SAN field, and leaves CN blank. Which is a pretty good default for generic testing. But what if the thing you want to test is how the CN field is handled?

Idea: add a kwarg-only CN= argument to issue_server_cert (i.e., the signature becomes issue_server_cert(*hostnames, CN=None) – though of course we have to use **kwargs to fake this b/c python 2, sigh). Require that either at least one hostname or CN has to be set.

The other way would be to automatically set CN to match the first hostname, but this way is much more flexible (e.g., you can test that if CN doesn't match any of the hostnames, then your validation code ignores it, or generate a cert that only has a CN and no SAN).

urllib3 is an example of a library whose test suite uses a cert with CN-but-no-SAN.

Support on winhttp

Hello I am trying to incorporate trustme in the CA SSL verification testing in a opensourced project. Experience on Linux is good but run into error with winhttp:
Send request failed: The certificate authority is invalid or incorrect
I googled but could not find any evidence explicitly suggesting the trustm support on winhttp. So I wonder how is it?

Stop generating CN fields

Right now we throw some nonsense in the CN field and put the good stuff in the SAN, on the theory that this will help catch any old software that's incorrectly relying on the CN field instead of SAN. But this violates the CABF baseline requirements. We should leave the CN out entirely, which will let us catch broken software while also meeting the requirements.

Add typing

urllib3 is using trustme in its tests, and is in the process of being type annotated, so it would be nice if trustme is also typed.

First, would you like trustme to be typed at all?

If so, since the library still supports Python 2, it can be done with one of these approaches:

  1. Add type stubs (pyi files) to typeshed. This is a pretty streamlined process nowadays, the typing could by used by installing an extra types-trustme package.

  2. Add external type stubs to the package itself. This way users don't need to install the extra dependency, but trustme becomes responsible for keeping the stubs up-to-date/synced with the public API in the code.

  3. Add inline type annotations with Python 2-compatible comment syntax. Similar to 2, but doesn't get of sync, but is more invasive. In this case CI would also run mypy which can be nice as a linter.

I'm willing to do the work using whichever approach you prefer.

trustme complies with the macOS 10.15 TLS rules

macOS 10.15 was released three weeks ago and has stricter rules about TLS certificates, see https://support.apple.com/en-us/HT210176, quoted below.

All TLS server certificates must comply with these new security requirements in iOS 13 and macOS 10.15:

  • TLS server certificates and issuing CAs using RSA keys must use key sizes greater than or equal to 2048 bits. Certificates using RSA key sizes smaller than 2048 bits are no longer trusted for TLS.
  • TLS server certificates and issuing CAs must use a hash algorithm from the SHA-2 family in the signature algorithm. SHA-1 signed certificates are no longer trusted for TLS.
  • TLS server certificates must present the DNS name of the server in the Subject Alternative Name extension of the certificate. DNS names in the CommonName of a certificate are no longer trusted.

Additionally, all TLS server certificates issued after July 1, 2019 (as indicated in the NotBefore field of the certificate) must follow these guidelines:

  • TLS server certificates must contain an ExtendedKeyUsage (EKU) extension containing the id-kp-serverAuth OID.
  • TLS server certificates must have a validity period of 825 days or fewer (as expressed in the NotBefore and NotAfter fields of the certificate).

trustme:

  • uses 2048 bits since #45,
  • does not use SHA-1 but SHA-256,
  • sets the Subject Alternative Name in addition to the CommonName,
  • and sets the server auth extension

The validity period is larger than 825 days, but since our NotBefore is 2000-01-01, the rule does not apply to us.

So trustme 0.5.1+ complies with those rules 🎉

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.

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 aio-libs/aiohttp@c180800#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:

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

Consider adding an option for ECDSA keys

ECDSA keys can be generated much faster.

Benchmarks

Benchmarks of the tests using hyperfine:

RSA

  Time (mean ± σ):     14.322 s ±  0.495 s    [User: 14.252 s, System: 0.079 s]
  Range (min … max):   13.412 s … 14.958 s    10 runs

ECDSA (using secp521r1)

  Time (mean ± σ):     776.9 ms ±  21.7 ms    [User: 738.8 ms, System: 68.0 ms]
  Range (min … max):   753.7 ms … 823.5 ms    10 runs

For these last results, startup time becomes relevant, as pytest reports ~0.55s

Diff for the ECDSA benchmarks

diff --git a/tests/test_trustme.py b/tests/test_trustme.py
index c9de4f8..324d8f9 100644
--- a/tests/test_trustme.py
+++ b/tests/test_trustme.py
@@ -69,7 +69,7 @@ def test_basics() -> None:
 
     today = datetime.datetime.today()
 
-    assert b"BEGIN RSA PRIVATE KEY" in ca.private_key_pem.bytes()
+    assert b"BEGIN EC PRIVATE KEY" in ca.private_key_pem.bytes()
     assert b"BEGIN CERTIFICATE" in ca.cert_pem.bytes()
 
     private_key = load_pem_private_key(
@@ -80,9 +80,9 @@ def test_basics() -> None:
     assert ca_cert.not_valid_before <= today <= ca_cert.not_valid_after
 
     public_key1 = private_key.public_key().public_bytes(
-        Encoding.PEM, PublicFormat.PKCS1)
+        Encoding.PEM, PublicFormat.SubjectPublicKeyInfo)
     public_key2 = ca_cert.public_key().public_bytes(
-        Encoding.PEM, PublicFormat.PKCS1)
+        Encoding.PEM, PublicFormat.SubjectPublicKeyInfo)
     assert public_key1 == public_key2
 
     assert ca_cert.issuer == ca_cert.subject
diff --git a/trustme/__init__.py b/trustme/__init__.py
index a00c960..3b416cb 100644
--- a/trustme/__init__.py
+++ b/trustme/__init__.py
@@ -12,7 +12,7 @@ import idna
 from cryptography import x509
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives import hashes
-from cryptography.hazmat.primitives.asymmetric import rsa
+from cryptography.hazmat.primitives.asymmetric import rsa, ec
 from cryptography.hazmat.primitives.serialization import (
     PrivateFormat, NoEncryption
 )
@@ -219,11 +219,7 @@ class CA:
         organization_unit_name: Optional[str] = None,
     ) -> None:
         self.parent_cert = parent_cert
-        self._private_key = rsa.generate_private_key(
-            public_exponent=65537,
-            key_size=_KEY_SIZE,
-            backend=default_backend()
-        )
+        self._private_key = ec.generate_private_key(ec.SECP521R1)
         self._path_length = path_length
 
         name = _name(
@@ -353,11 +349,7 @@ class CA:
                 "Must specify at least one identity or common name"
             )
 
-        key = rsa.generate_private_key(
-            public_exponent=65537,
-            key_size=_KEY_SIZE,
-            backend=default_backend()
-        )
+        key = ec.generate_private_key(ec.SECP521R1)
 
         ski_ext = self._certificate.extensions.get_extension_for_class(
             x509.SubjectKeyIdentifier)

Dependabot can't resolve your Python dependency files

Dependabot can't resolve your Python dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Could not find a version that satisfies the requirement pyparsing==2.4.1 (from packaging==19.0->sphinx==2.1.2->sphinxcontrib-trio==1.1.0->-r ci/rtd-requirements.in (line 1)) (from versions: 1.4.6, 1.4.7, 1.4.8, 1.4.11, 1.5.0, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 2.0.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.0.7, 2.1.0, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.1.5, 2.1.6, 2.1.7, 2.1.8, 2.1.9, 2.1.10, 2.2.0, 2.2.1, 2.2.2, 2.3.0, 2.3.1, 2.4.0)
Traceback (most recent call last):
  File "/usr/local/.pyenv/versions/3.7.3/bin/pip-compile", line 10, in <module>
    sys.exit(cli())
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/scripts/compile.py", line 350, in cli
    results = resolver.resolve(max_rounds=max_rounds)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/resolver.py", line 164, in resolve
    has_changed, best_matches = self._resolve_one_round()
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/resolver.py", line 259, in _resolve_one_round
    their_constraints.extend(self._iter_dependencies(best_match))
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/resolver.py", line 354, in _iter_dependencies
    dependencies = self.repository.get_dependencies(ireq)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/repositories/local.py", line 66, in get_dependencies
    return self.repository.get_dependencies(ireq)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/repositories/pypi.py", line 270, in get_dependencies
    download_dir, ireq, wheel_cache
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/piptools/repositories/pypi.py", line 229, in resolve_reqs
    results = resolver._resolve_one(reqset, ireq)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 294, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 242, in _get_abstract_dist_for
    self.require_hashes
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/operations/prepare.py", line 282, in prepare_linked_requirement
    req.populate_link(finder, upgrade_allowed, require_hashes)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/req/req_install.py", line 198, in populate_link
    self.link = finder.find_requirement(self, upgrade)
  File "/usr/local/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip/_internal/index.py", line 792, in find_requirement
    'No matching distribution found for %s' % req
pip._internal.exceptions.DistributionNotFound: No matching distribution found for pyparsing==2.4.1 (from packaging==19.0->sphinx==2.1.2->sphinxcontrib-trio==1.1.0->-r ci/rtd-requirements.in (line 1))

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

You can mention @dependabot in the comments below to contact the Dependabot team.

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: aio-libs/aiohttp@c180800#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.

0.9.0: sphinx warnings

Looks like latest sphins show some warnings

+ /usr/bin/python3 setup.py build_sphinx -b man --build-dir build/sphinx
running build_sphinx
Running Sphinx v4.3.2
making output directory... done
loading intersphinx inventory from https://docs.python.org/3/objects.inv...
loading intersphinx inventory from https://www.pyopenssl.org/en/stable/objects.inv...
loading intersphinx inventory from https://trio.readthedocs.io/en/latest/objects.inv...
building [mo]: targets for 0 po files that are out of date
building [man]: all manpages
updating environment: [new config] 1 added, 0 changed, 0 removed
reading sources... [100%] index
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
writing... python-trustme.3 { } /home/tkloczko/rpmbuild/BUILD/trustme-0.9.0/trustme/__init__.py:docstring of trustme.CA.configure_trust:: WARNING: py:class reference target not found: OpenSSL.SSL.Context
/home/tkloczko/rpmbuild/BUILD/trustme-0.9.0/trustme/__init__.py:docstring of trustme.CA.configure_trust:: WARNING: py:class reference target not found: OpenSSL.SSL.Context
/home/tkloczko/rpmbuild/BUILD/trustme-0.9.0/trustme/__init__.py:docstring of trustme.LeafCert.configure_cert:: WARNING: py:class reference target not found: OpenSSL.SSL.Context
/home/tkloczko/rpmbuild/BUILD/trustme-0.9.0/trustme/__init__.py:docstring of trustme.LeafCert.configure_cert:: WARNING: py:class reference target not found: OpenSSL.SSL.Context
done
build succeeded, 4 warnings.

Use towncrier for release notes

I'd like to move the trio projects to this in general (esp. since trio 0.2.0 is shaping up to be a disaster, release-notes-wise), and trustme seems like a good little project to use to figure things out.

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.

Import a CA from cert and private key PEMs

To fix urllib3/urllib3#1419 while keeping the existing test root CA, I'd like to be able to do this:

import trustme

root_ca = trustme.CA.from_pem(
    cert='urllib3/dummyserver/certs/cacert.pem',
    private_key='urllib3/dummyserver/certs/cacert.key')

What do you think about the names? Should we also accept file-like parameters? Bytes?

Support email addresses in subjectAlternativeName

I think we could just use a silly rule like "if a 'hostname' has an @ in it, that's an email address".

urllib3 is an example of a project that uses test certs with email addresses in them.

(This might be the only difference between client certs and server certs in practice? Maybe issue_server_cert is a misnomer and it should be renamed to issue_cert?)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.