Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API sketch for X509 cert chain verification #102

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/truststore/hazmat/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's lift this prose into it's own documentation page as a warning?

This is the "Hazardous Materials" part of the truststore API. It
contains advanced cryptographic primitives that are often dangerous
and can be used incorrectly. They require an in-depth knowledge of the
cryptographic concepts at work. Using this part of the API without a
thorough understanding of the details involved will put your
application and its users at severe risk.
"""

from ._api import verify_cert_chain
17 changes: 17 additions & 0 deletions src/truststore/hazmat/_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import platform
import ssl

if platform.system() == "Windows":
from .._windows import _verify_peercerts_impl as _verify_cert_chain_impl
elif platform.system() == "Darwin":
from .._macos import _verify_peercerts_impl as _verify_cert_chain_impl
else:
from ._openssl import _verify_cert_chain_impl


def verify_cert_chain(cert_chain):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

_verify_cert_chain_impl(
ssl_context=context, cert_chain=cert_chain, server_hostname=None
)
28 changes: 28 additions & 0 deletions src/truststore/hazmat/_openssl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from .._openssl import _configure_context

try:
import OpenSSL.crypto
import OpenSSL.SSL
except ImportError:
raise Exception("Certificate chain verification on OpenSSL requires pyOpenSSL")


def _verify_intermediate_cert_and_add_to_store(store, cert):
store_ctx = OpenSSL.crypto.X509StoreContext(store, cert)
store_ctx.verify_certificate()
store.add_cert(cert)


def _verify_cert_chain_impl(ssl_context, cert_chain, server_hostname=None):
# We use the pyOpenSSL SSL context, not the stdlib ssl one.
# Discard the one that was passed in to avoid confusion.
ssl_context = None

pyopenssl_context = OpenSSL.SSL.Context(OpenSSL.SSL.TLS_CLIENT_METHOD)
with _configure_context(pyopenssl_context):
store = pyopenssl_context.get_cert_store()
for cert in reversed(cert_chain):
pyopenssl_cert = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_ASN1, cert
)
_verify_intermediate_cert_and_add_to_store(store, pyopenssl_cert)