python-trio / trustme Goto Github PK
View Code? Open in Web Editor NEW#1 quality TLS certs while you wait, for the discerning tester
Home Page: https://trustme.rtfd.io
License: Other
#1 quality TLS certs while you wait, for the discerning tester
Home Page: https://trustme.rtfd.io
License: Other
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.
Seems someone forgot to git push --tags
. Pls fix :)
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?
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?
The CA's private key is required for tasks like creating a TLS secret in Kubernetes (if I understand correctly).
See https://github.com/jetstack/cert-manager/blob/master/docs/user-guides/ca-based-issuer.md for example.
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)
So we get earlier notifications about stuff like #47
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!!
Whenever I use trustme with pytest I end up making my own fixture, could we ship with our own pytest fixtures out of the box?
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.
Sigh. But between the weird tempfile issues and #10, it's clearly necessary.
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.
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.
@alex sez that the next release of cryptography is going to deprecate passing U-labels into the x509 construction functions, and that passing A-labels has always been supported. So we should be sure to pass A-labels.
$subj. It'd be great if https://trustme.rtfd.io could be copied there. That field is on top of the page in the sidebar which is better visible than the one in README.
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?
because hey why not
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.
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:
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.
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.
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.
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:
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 🎉
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:
path_length
keyUsage
7.1.4.3 CA certificates:
7.1.2.3 subscriber certificates:
We might have some RFC 5280 fails too, I haven't read it carefully.
See sethmlarson/trustme-cli#1, wanted to make sure this work wasn't lost as I've used trustme-cli
multiple times in the past few weeks.
Currently we have _KEY_SIZE
but really this should be _DEFAULT_KEY_SIZE
and allow for generating keys of different sizes as a public API.
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?
Dependabot couldn't authenticate with https://pypi.python.org/simple/.
You can provide authentication details in your Dependabot dashboard by clicking into the account menu (in the top right) and selecting 'Config variables'.
ECDSA keys can be generated much faster.
Benchmarks of the tests using hyperfine
:
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
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 --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.
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.
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.
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.
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.
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.
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?
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
?)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.