mirror of
https://github.com/saymrwulf/cryptography.git
synced 2026-05-14 20:37:55 +00:00
document creating a CA hierarchy: root -> int -> ee (#11031)
* document creating a CA hierarchy: root -> int -> ee * fix things
This commit is contained in:
parent
a744422087
commit
5dc620daa4
1 changed files with 192 additions and 0 deletions
|
|
@ -150,6 +150,198 @@ Then we generate the certificate itself:
|
|||
And now we have a private key and certificate that can be used for local
|
||||
testing.
|
||||
|
||||
Creating a CA hierarchy
|
||||
-----------------------
|
||||
|
||||
When building your own root hierarchy you need to generate a CA and then
|
||||
issue certificates (typically intermediates) using it. This example shows
|
||||
how to generate a root CA, a signing intermediate, and issues a leaf
|
||||
certificate off that intermediate. X.509 is a complex specification so
|
||||
this example will require adaptation (typically different extensions)
|
||||
for specific operating environments.
|
||||
|
||||
Note that this example does not add CRL distribution point or OCSP AIA
|
||||
extensions, nor does it save the key/certs to persistent storage.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> import datetime
|
||||
>>> from cryptography.hazmat.primitives.asymmetric import ec
|
||||
>>> from cryptography.hazmat.primitives import hashes
|
||||
>>> from cryptography.x509.oid import NameOID
|
||||
>>> from cryptography import x509
|
||||
>>> # Generate our key
|
||||
>>> root_key = ec.generate_private_key(ec.SECP256R1())
|
||||
>>> subject = issuer = x509.Name([
|
||||
... x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
|
||||
... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"),
|
||||
... x509.NameAttribute(NameOID.LOCALITY_NAME, "San Francisco"),
|
||||
... x509.NameAttribute(NameOID.ORGANIZATION_NAME, "My Company"),
|
||||
... x509.NameAttribute(NameOID.COMMON_NAME, "PyCA Docs Root CA"),
|
||||
... ])
|
||||
>>> root_cert = x509.CertificateBuilder().subject_name(
|
||||
... subject
|
||||
... ).issuer_name(
|
||||
... issuer
|
||||
... ).public_key(
|
||||
... root_key.public_key()
|
||||
... ).serial_number(
|
||||
... x509.random_serial_number()
|
||||
... ).not_valid_before(
|
||||
... datetime.datetime.now(datetime.timezone.utc)
|
||||
... ).not_valid_after(
|
||||
... # Our certificate will be valid for ~10 years
|
||||
... datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365*10)
|
||||
... ).add_extension(
|
||||
... x509.BasicConstraints(ca=True, path_length=None),
|
||||
... critical=True,
|
||||
... ).add_extension(
|
||||
... x509.KeyUsage(
|
||||
... digital_signature=True,
|
||||
... content_commitment=False,
|
||||
... key_encipherment=False,
|
||||
... data_encipherment=False,
|
||||
... key_agreement=False,
|
||||
... key_cert_sign=True,
|
||||
... crl_sign=True,
|
||||
... encipher_only=False,
|
||||
... decipher_only=False,
|
||||
... ),
|
||||
... critical=True,
|
||||
... ).add_extension(
|
||||
... x509.SubjectKeyIdentifier.from_public_key(root_key.public_key()),
|
||||
... critical=False,
|
||||
... ).sign(root_key, hashes.SHA256())
|
||||
|
||||
With a root certificate created we now want to create our intermediate.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> # Generate our intermediate key
|
||||
>>> int_key = ec.generate_private_key(ec.SECP256R1())
|
||||
>>> subject = x509.Name([
|
||||
... x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
|
||||
... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"),
|
||||
... x509.NameAttribute(NameOID.LOCALITY_NAME, "San Francisco"),
|
||||
... x509.NameAttribute(NameOID.ORGANIZATION_NAME, "My Company"),
|
||||
... x509.NameAttribute(NameOID.COMMON_NAME, "PyCA Docs Intermediate CA"),
|
||||
... ])
|
||||
>>> int_cert = x509.CertificateBuilder().subject_name(
|
||||
... subject
|
||||
... ).issuer_name(
|
||||
... root_cert.subject
|
||||
... ).public_key(
|
||||
... int_key.public_key()
|
||||
... ).serial_number(
|
||||
... x509.random_serial_number()
|
||||
... ).not_valid_before(
|
||||
... datetime.datetime.now(datetime.timezone.utc)
|
||||
... ).not_valid_after(
|
||||
... # Our intermediate will be valid for ~3 years
|
||||
... datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365*3)
|
||||
... ).add_extension(
|
||||
... # Allow no further intermediates (path length 0)
|
||||
... x509.BasicConstraints(ca=True, path_length=0),
|
||||
... critical=True,
|
||||
... ).add_extension(
|
||||
... x509.KeyUsage(
|
||||
... digital_signature=True,
|
||||
... content_commitment=False,
|
||||
... key_encipherment=False,
|
||||
... data_encipherment=False,
|
||||
... key_agreement=False,
|
||||
... key_cert_sign=True,
|
||||
... crl_sign=True,
|
||||
... encipher_only=False,
|
||||
... decipher_only=False,
|
||||
... ),
|
||||
... critical=True,
|
||||
... ).add_extension(
|
||||
... x509.SubjectKeyIdentifier.from_public_key(int_key.public_key()),
|
||||
... critical=False,
|
||||
... ).add_extension(
|
||||
... x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||
... root_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||
... ),
|
||||
... critical=False,
|
||||
... ).sign(root_key, hashes.SHA256())
|
||||
|
||||
Now we can issue an end entity certificate off this chain.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> ee_key = ec.generate_private_key(ec.SECP256R1())
|
||||
>>> subject = x509.Name([
|
||||
... x509.NameAttribute(NameOID.COUNTRY_NAME, "US"),
|
||||
... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "California"),
|
||||
... x509.NameAttribute(NameOID.LOCALITY_NAME, "San Francisco"),
|
||||
... x509.NameAttribute(NameOID.ORGANIZATION_NAME, "My Company"),
|
||||
... ])
|
||||
>>> ee_cert = x509.CertificateBuilder().subject_name(
|
||||
... subject
|
||||
... ).issuer_name(
|
||||
... int_cert.subject
|
||||
... ).public_key(
|
||||
... ee_key.public_key()
|
||||
... ).serial_number(
|
||||
... x509.random_serial_number()
|
||||
... ).not_valid_before(
|
||||
... datetime.datetime.now(datetime.timezone.utc)
|
||||
... ).not_valid_after(
|
||||
... # Our cert will be valid for 10 days
|
||||
... datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=10)
|
||||
... ).add_extension(
|
||||
... x509.SubjectAlternativeName([
|
||||
... # Describe what sites we want this certificate for.
|
||||
... x509.DNSName("cryptography.io"),
|
||||
... x509.DNSName("www.cryptography.io"),
|
||||
... ]),
|
||||
... critical=False,
|
||||
... ).add_extension(
|
||||
... x509.BasicConstraints(ca=False, path_length=None),
|
||||
... critical=True,
|
||||
... ).add_extension(
|
||||
... x509.KeyUsage(
|
||||
... digital_signature=True,
|
||||
... content_commitment=False,
|
||||
... key_encipherment=True,
|
||||
... data_encipherment=False,
|
||||
... key_agreement=False,
|
||||
... key_cert_sign=False,
|
||||
... crl_sign=True,
|
||||
... encipher_only=False,
|
||||
... decipher_only=False,
|
||||
... ),
|
||||
... critical=True,
|
||||
... ).add_extension(
|
||||
... x509.ExtendedKeyUsage([
|
||||
... x509.ExtendedKeyUsageOID.CLIENT_AUTH,
|
||||
... x509.ExtendedKeyUsageOID.SERVER_AUTH,
|
||||
... ]),
|
||||
... critical=False,
|
||||
... ).add_extension(
|
||||
... x509.SubjectKeyIdentifier.from_public_key(ee_key.public_key()),
|
||||
... critical=False,
|
||||
... ).add_extension(
|
||||
... x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||
... int_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||
... ),
|
||||
... critical=False,
|
||||
... ).sign(int_key, hashes.SHA256())
|
||||
|
||||
And finally we use the verification APIs to validate the chain.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> from cryptography.x509 import DNSName
|
||||
>>> from cryptography.x509.verification import PolicyBuilder, Store
|
||||
>>> store = Store([root_cert])
|
||||
>>> builder = PolicyBuilder().store(store)
|
||||
>>> verifier = builder.build_server_verifier(DNSName("cryptography.io"))
|
||||
>>> chain = verifier.verify(ee_cert, [int_cert])
|
||||
>>> len(chain)
|
||||
3
|
||||
|
||||
Determining Certificate or Certificate Signing Request Key Type
|
||||
---------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue