django_ca.extensions - X509 extensions

The extension classes provided by django-ca act as convenience classes for handling extensions. They abstract away the complex API of cryptography and have some advanced data handling functions. As a constructor, they always take either a dict or a cryptography extension:

>>> from django_ca.extensions import KeyUsage
>>> KeyUsage({'value': ['keyAgreement', 'keyEncipherment']})
<KeyUsage: ['keyAgreement', 'keyEncipherment'], critical=True>

… but you can also pass an equivalent cryptography extension:

>>> from cryptography import x509
>>> from cryptography.x509.oid import ExtensionOID
>>> KeyUsage(x509.Extension(
...     oid=ExtensionOID.KEY_USAGE, critical=True, value=x509.KeyUsage(
...         key_agreement=True, key_encipherment=True, digital_signature=False, crl_sign=False,
...         content_commitment=False, data_encipherment=False, key_cert_sign=False, encipher_only=False,
...         decipher_only=False)
... ))
<KeyUsage: ['keyAgreement', 'keyEncipherment'], critical=True>

… regardless of how you created the extension, you can modify it at will until you actually use it somewhere:

>>> from django_ca.extensions import KeyUsage
>>> ku = KeyUsage({'value': ['keyAgreement', 'keyEncipherment']})
>>> ku |= ['nonRepudiation']
>>> ku.add('cRLSign')
>>> ku
<KeyUsage: ['cRLSign', 'keyAgreement', 'keyEncipherment', 'nonRepudiation'], critical=True>

The type of operations available to an extension depend on the extension.

You can always serialize an extension to its dict representation and later restore it (e.g. after transfering it over the network):

>>> ku = KeyUsage({'value': ['keyAgreement', 'keyEncipherment']})
>>> ku == KeyUsage(ku.serialize())
True

Extension classes

Note that extensions are not marked as “critical” by default. Only those that are usually marked as critical override the default_critical attribute.

class django_ca.extensions.AuthorityInformationAccess(value=None)[source]

Bases: django_ca.extensions.Extension

Class representing a AuthorityInformationAccess extension.

The value passed to this extension should be a dict with an ocsp and issuers key, both are optional:

>>> AuthorityInformationAccess({'value': {
...     'ocsp': ['http://ocsp.example.com'],
...     'issuers': ['http://issuer.example.com'],
... }})  
<AuthorityInformationAccess: issuers=['URI:http://issuer.example.com'],
ocsp=['URI:http://ocsp.example.com'], critical=False>

You can set/get the OCSP/issuers at runtime and dynamically use either strings or GeneralName as values:

>>> aia = AuthorityInformationAccess()
>>> aia.issuers = ['http://issuer.example.com']
>>> aia.ocsp = [x509.UniformResourceIdentifier('http://ocsp.example.com/')]
>>> aia  
<AuthorityInformationAccess: issuers=['URI:http://issuer.example.com'],
ocsp=['URI:http://ocsp.example.com/'], critical=False>
property issuers

The issuers in this extension.

key = 'authority_information_access'

Key used in CA_PROFILES.

property ocsp

The OCSP responders in this extension.

class django_ca.extensions.AuthorityKeyIdentifier(value=None)[source]

Bases: django_ca.extensions.Extension

Class representing a AuthorityKeyIdentifier extension.

This extension identifies the signing CA, so it is not usually defined in a profile or instantiated by a user. This extension will automatically be added by django-ca. If it is, the value must be a str or bytes:

>>> AuthorityKeyIdentifier({'value': '33:33:33:33:33:33'})
<AuthorityKeyIdentifier: keyid: 33:33:33:33:33:33, critical=False>
>>> AuthorityKeyIdentifier({'value': b'333333'})
<AuthorityKeyIdentifier: keyid: 33:33:33:33:33:33, critical=False>

If you want to set an authorityCertIssuer and authorityCertIssuer, you can also pass a dict instead:

>>> AuthorityKeyIdentifier({'value': {
...     'key_identifier': b'0',
...     'authority_cert_issuer': ['example.com'],
...     'authority_cert_serial_number': 1,
... }})
<AuthorityKeyIdentifier: keyid: 30, issuer: ['DNS:example.com'], serial: 1, critical=False>
key = 'authority_key_identifier'

Key used in CA_PROFILES.

class django_ca.extensions.BasicConstraints(value=None)[source]

Bases: django_ca.extensions.Extension

Class representing a BasicConstraints extension.

This class has the boolean attributes ca and the attribute pathlen, which is either None or an int. Note that this extension is marked as critical by default if you pass a dict to the constructor:

>>> bc = BasicConstraints({'value': {'ca': True, 'pathlen': 4}})
>>> (bc.ca, bc.pathlen, bc.critical)
(True, 4, True)
property ca

The ca property of this extension.

default_critical = True

This extension is marked as critical by default.

key = 'basic_constraints'

Key used in CA_PROFILES.

parse_pathlen(value)[source]

Parse a pathlen from the given value (either an int, a str of an int or None).

property pathlen

The pathlen value of this instance.

class django_ca.extensions.CRLDistributionPoints(value=None)[source]

Bases: django_ca.extensions.CRLDistributionPointsBase

Class representing a CRLDistributionPoints extension.

This extension identifies where a client can retrieve a Certificate Revocation List (CRL).

The value passed to this extension should be a list of DistributionPoint instances. Naturally, you can also pass those in serialized form:

>>> CRLDistributionPoints({'value': [
...     {'full_name': ['http://crl.example.com']}
... ]})  
<CRLDistributionPoints: [<DistributionPoint: full_name=['URI:http://crl.example.com']>],
critical=False>
key = 'crl_distribution_points'

Key used in CA_PROFILES.

class django_ca.extensions.CertificatePolicies(value=None)[source]

Bases: django_ca.extensions.ListExtension

Class representing a Certificate Policies extension.

The value passed to this extension should be a list of PolicyInformation instances. Naturally, you can also pass those in serialized form:

>>> CertificatePolicies({'value': [{
...     'policy_identifier': '2.5.29.32.0',
...     'policy_qualifier': ['policy1'],
... }]})
<CertificatePolicies: 1 policy, critical=False>
key = 'certificate_policies'

Key used in CA_PROFILES.

class django_ca.extensions.ExtendedKeyUsage(value=None)[source]

Bases: django_ca.extensions.OrderedSetExtension

Class representing a ExtendedKeyUsage extension.

KNOWN_PARAMETERS = ['OCSPSigning', 'anyExtendedKeyUsage', 'clientAuth', 'codeSigning', 'emailProtection', 'ipsecEndSystem', 'ipsecTunnel', 'ipsecUser', 'msKDC', 'serverAuth', 'smartcardLogon', 'timeStamping']

Known values that can be passed to this extension.

key = 'extended_key_usage'

Key used in CA_PROFILES.

class django_ca.extensions.FreshestCRL(value=None)[source]

Bases: django_ca.extensions.CRLDistributionPointsBase

Class representing a FreshestCRL extension.

This extension handles identically to the CRLDistributionPoints extension:

>>> FreshestCRL({'value': [
...     {'full_name': ['http://crl.example.com']}
... ]})  
<FreshestCRL: [<DistributionPoint: full_name=['URI:http://crl.example.com']>],
critical=False>
key = 'freshest_crl'

Key used in CA_PROFILES.

class django_ca.extensions.InhibitAnyPolicy(value=None)[source]

Bases: django_ca.extensions.Extension

Class representing a InhibitAnyPolicy extension.

Example:

>>> InhibitAnyPolicy({'value': 1})  # normal value dict is supported
<InhibitAnyPolicy: 1, critical=True>
>>> ext = InhibitAnyPolicy(3)  # a simple int is also okay
>>> ext
<InhibitAnyPolicy: 3, critical=True>
>>> ext.skip_certs = 5
>>> ext.skip_certs
5
default_critical = True

This extension is marked as critical by default (RFC 5280 requires this extension to be marked as critical).

from_int(value)[source]

Parser allowing creation of an instance just from an int.

key = 'inhibit_any_policy'

Key used in CA_PROFILES.

property skip_certs

The skip_certs value of this instance.

class django_ca.extensions.IssuerAlternativeName(value=None)[source]

Bases: django_ca.extensions.AlternativeNameExtension

Class representing an Issuer Alternative Name extension.

This extension is usually marked as non-critical.

>>> IssuerAlternativeName({'value': ['https://example.com']})
<IssuerAlternativeName: ['URI:https://example.com'], critical=False>
key = 'issuer_alternative_name'

Key used in CA_PROFILES.

class django_ca.extensions.KeyUsage(*args, **kwargs)[source]

Bases: django_ca.extensions.OrderedSetExtension

Class representing a KeyUsage extension, which defines the purpose of a certificate.

This extension is usually marked as critical and RFC 5280 defines that conforming CAs SHOULD mark it as critical. The value keyAgreement is always added if encipherOnly or decipherOnly is present, since the value of this extension is not meaningful otherwise.

>>> KeyUsage({'value': ['encipherOnly'], 'critical': True})
<KeyUsage: ['encipherOnly', 'keyAgreement'], critical=True>
>>> KeyUsage({'value': ['decipherOnly'], 'critical': True})
<KeyUsage: ['decipherOnly', 'keyAgreement'], critical=True>
KNOWN_PARAMETERS = ['cRLSign', 'dataEncipherment', 'decipherOnly', 'digitalSignature', 'encipherOnly', 'keyAgreement', 'keyCertSign', 'keyEncipherment', 'nonRepudiation']

Known values that can be passed to this extension.

default_critical = True

This extension is marked as critical by default.

key = 'key_usage'

Key used in CA_PROFILES.

class django_ca.extensions.NameConstraints(value=None)[source]

Bases: django_ca.extensions.Extension

Class representing a NameConstraints extension.

Unlike most other extensions, this extension does not accept a string as value, but you can pass a list containing the permitted/excluded subtrees as lists. Similar to SubjectAlternativeName, you can pass both strings or instances of GeneralName:

>>> NameConstraints({'value': {
...     'permitted': ['DNS:.com', 'example.org'],
...     'excluded': [x509.DNSName('.net')]
... }})
<NameConstraints: permitted=['DNS:.com', 'DNS:example.org'], excluded=['DNS:.net'], critical=True>

We also have permitted/excluded getters/setters to easily configure this extension:

>>> nc = NameConstraints()
>>> nc.permitted = ['example.com']
>>> nc.excluded = ['example.net']
>>> nc
<NameConstraints: permitted=['DNS:example.com'], excluded=['DNS:example.net'], critical=True>
>>> nc.permitted, nc.excluded
(<GeneralNameList: ['DNS:example.com']>, <GeneralNameList: ['DNS:example.net']>)
default_critical = True

This extension is marked as critical by default.

property excluded

The excluded value of this instance.

key = 'name_constraints'

Key used in CA_PROFILES.

property permitted

The permitted value of this instance.

class django_ca.extensions.OCSPNoCheck(value=None)[source]

Bases: django_ca.extensions.NullExtension

Extension to indicate that an OCSP client should (blindly) trust the certificate for it’s lifetime.

Ass a NullExtension, any value is ignored and you can pass a simple empty dict (or nothing at all) to the extension:

>>> OCSPNoCheck()
<OCSPNoCheck: critical=False>
>>> OCSPNoCheck({'critical': True})  # unlike PrecertPoison, you can still mark it as critical
<OCSPNoCheck: critical=True>

This extension is only meaningful in an OCSP responder certificate.

key = 'ocsp_no_check'

Key used in CA_PROFILES.

class django_ca.extensions.PolicyConstraints(value=None)[source]

Bases: django_ca.extensions.Extension

Class representing a PolicyConstraints extension.

Example:

>>> ext = PolicyConstraints({'value': {'require_explicit_policy': 1, 'inhibit_policy_mapping': 2}})
>>> ext
<PolicyConstraints: inhibit_policy_mapping=2, require_explicit_policy=1, critical=True>
>>> ext.require_explicit_policy
1
>>> ext.inhibit_policy_mapping = 5
>>> ext.inhibit_policy_mapping
5
default_critical = True

This extension is marked as critical by default (RFC 5280 requires this extension to be marked as critical).

property inhibit_policy_mapping

The inhibit_policy_mapping value of this instance.

key = 'policy_constraints'

Key used in CA_PROFILES.

property require_explicit_policy

The require_explicit_policy value of this instance.

class django_ca.extensions.PrecertPoison(value=None)[source]

Bases: django_ca.extensions.NullExtension

Extension to indicate that the certificate is a submission to a certificate transparency log.

Note that creating this extension will raise ValueError if it is not marked as critical:

>>> PrecertPoison()
<PrecertPoison: critical=True>
>>> PrecertPoison({'critical': False})
Traceback (most recent call last):
    ...
ValueError: PrecertPoison must always be marked as critical
default_critical = True

This extension is marked as critical by default.

key = 'precert_poison'

Key used in CA_PROFILES.

class django_ca.extensions.PrecertificateSignedCertificateTimestamps(value=None)[source]

Bases: django_ca.extensions.ListExtension

Class representing signed certificate timestamps.

This extension can be used to verify that a certificate is included in a Certificate Transparency log.

Note

Cryptography currently does not provide a way to create instances of this extension without already having a certificate that provides this extension.

https://github.com/pyca/cryptography/issues/4820

See also

RFC 6962

human_readable_timestamps()[source]

Convert SCTs into a generator of serializable dicts.

key = 'precertificate_signed_certificate_timestamps'

Key used in CA_PROFILES.

class django_ca.extensions.SubjectAlternativeName(value=None)[source]

Bases: django_ca.extensions.AlternativeNameExtension

Class representing an Subject Alternative Name extension.

This extension is usually marked as non-critical.

>>> SubjectAlternativeName({'value': ['example.com']})
<SubjectAlternativeName: ['DNS:example.com'], critical=False>
get_common_name()[source]

Get a value suitable for use as CommonName in a subject, or None if no such value is found.

This function returns a string representation of the first value that is not a DirectoryName, RegisteredID or OtherName.

key = 'subject_alternative_name'

Key used in CA_PROFILES.

class django_ca.extensions.SubjectKeyIdentifier(value=None)[source]

Bases: django_ca.extensions.KeyIdExtension

Class representing a SubjectKeyIdentifier extension.

This extension identifies the certificate, so it is not usually defined in a profile or instantiated by a user. This extension will automatically be added by django-ca. If you ever handle this extension directly, the value must be a str or bytes:

>>> SubjectKeyIdentifier({'value': '33:33:33:33:33:33'})
<SubjectKeyIdentifier: b'333333', critical=False>
>>> SubjectKeyIdentifier({'value': b'333333'})
<SubjectKeyIdentifier: b'333333', critical=False>
key = 'subject_key_identifier'

Key used in CA_PROFILES.

class django_ca.extensions.TLSFeature(value=None)[source]

Bases: django_ca.extensions.OrderedSetExtension

Class representing a TLSFeature extension.

As a OrderedSetExtension, this extension handles much like it’s other sister extensions::

>>> TLSFeature({'value': ['OCSPMustStaple']})
<TLSFeature: ['OCSPMustStaple'], critical=False>
>>> tf = TLSFeature({'value': ['OCSPMustStaple']})
>>> tf.add('MultipleCertStatusRequest')
>>> tf
<TLSFeature: ['MultipleCertStatusRequest', 'OCSPMustStaple'], critical=False>
KNOWN_PARAMETERS = ['MultipleCertStatusRequest', 'OCSPMustStaple']

Known values that can be passed to this extension.

key = 'tls_feature'

Key used in CA_PROFILES.

django_ca.extensions.get_extension_name(ext)[source]

Function to get the name of an extension.

Attribute classes

class django_ca.extensions.DistributionPoint(data=None)[source]

Class representing a Distribution Point.

This class is used internally by extensions that have a list of Distribution Points, e.g. the : CRLDistributionPoints extension. The class accepts either a cryptography.x509.DistributionPoint or a dict. Note that in the latter case, you can also pass a str as full_name or crl_issuer if there is only one value:

>>> DistributionPoint(x509.DistributionPoint(
...     full_name=[x509.UniformResourceIdentifier('http://ca.example.com/crl')],
...     relative_name=None, crl_issuer=None, reasons=None
... ))
<DistributionPoint: full_name=['URI:http://ca.example.com/crl']>
>>> DistributionPoint({'full_name': ['http://example.com']})
<DistributionPoint: full_name=['URI:http://example.com']>
>>> DistributionPoint({'full_name': 'http://example.com'})
<DistributionPoint: full_name=['URI:http://example.com']>
>>> DistributionPoint({
...     'relative_name': '/CN=example.com',
...     'crl_issuer': 'http://example.com',
...     'reasons': ['key_compromise', 'ca_compromise'],
... })  
<DistributionPoint: relative_name='/CN=example.com', crl_issuer=['URI:http://example.com'],
                    reasons=['ca_compromise', 'key_compromise']>
class django_ca.extensions.PolicyInformation(data=None)[source]

Class representing a PolicyInformation object.

This class is internally used by the CertificatePolicies extension.

You can pass a PolicyInformation instance or a dictionary representing that instance:

>>> PolicyInformation({'policy_identifier': '2.5.29.32.0', 'policy_qualifiers': ['text1']})
<PolicyInformation(oid=2.5.29.32.0, qualifiers=['text1'])>
>>> PolicyInformation({
...     'policy_identifier': '2.5.29.32.0',
...     'policy_qualifiers': [{'explicit_text': 'text2', }],
... })
<PolicyInformation(oid=2.5.29.32.0, qualifiers=[{'explicit_text': 'text2'}])>
>>> PolicyInformation({
...     'policy_identifier': '2.5',
...     'policy_qualifiers': [{
...         'notice_reference': {
...             'organization': 't3',
...             'notice_numbers': [1, ],
...         }
...     }],
... })  
<PolicyInformation(oid=2.5, qualifiers=[{'notice_reference': {...}}])>

Base classes

class django_ca.extensions.Extension(value=None)[source]

Convenience class to handle X509 Extensions.

The value is a dict as used by the CA_PROFILES setting:

>>> KeyUsage({'value': ['keyAgreement', 'keyEncipherment']})
<KeyUsage: ['keyAgreement', 'keyEncipherment'], critical=True>
>>> KeyUsage({'critical': False, 'value': ['key_agreement', 'key_encipherment']})
<KeyUsage: ['keyAgreement', 'keyEncipherment'], critical=False>

… but can also use a subclass of ExtensionType from cryptography:

>>> from cryptography import x509
>>> cg_ext = x509.extensions.Extension(
...    oid=ExtensionOID.EXTENDED_KEY_USAGE,
...    critical=False,
...    value=x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH])
... )
>>> ExtendedKeyUsage(cg_ext)
<ExtendedKeyUsage: ['serverAuth'], critical=False>
>>> ExtendedKeyUsage({'value': ['serverAuth']})
<ExtendedKeyUsage: ['serverAuth'], critical=False>
Parameters
valuelist or tuple or dict or str or ExtensionType

The value of the extension, the description provides further details.

Attributes
namestr

A human readable name of this extension

value

Raw value for this extension. The type various from subclass to subclass.

criticalbool

If this extension is marked as critical

oidExtensionOID

The OID for this extension.

keystr

The key is a reusable ID used in various parts of the application.

default_criticalbool

The default critical value if you pass a dict without the "critical" key.

as_extension()[source]

This extension as ExtensionType.

as_text()[source]

Human-readable version of the value, not including the “critical” flag.

property extension_type

The extension_type for this value.

for_builder()[source]

Return kwargs suitable for a CertificateBuilder.

Example:

>>> kwargs = KeyUsage({'value': ['keyAgreement', 'keyEncipherment']}).for_builder()
>>> builder.add_extension(**kwargs)  
key = None

Key used in CA_PROFILES.

serialize()[source]

Serialize this extension to a string in a way that it can be passed to a constructor again.

For example, this should always be True:

>>> ku = KeyUsage({'value': ['keyAgreement', 'keyEncipherment']})
>>> ku == KeyUsage(ku.serialize())
True
class django_ca.extensions.IterableExtension(value=None)[source]

Bases: django_ca.extensions.Extension

Base class for iterable extensions.

Extensions of this class can be used just like any other iterable, e.g.:

>>> e = IterableExtension({'value': ['foo', 'bar']})
>>> 'foo' in e
True
>>> len(e)
2
>>> for val in e:
...     print(val)
foo
bar
serialize_iterable()[source]

Serialize the whole iterable contained in this extension.

serialize_value(value)[source]

Serialize a single value from the iterable contained in this extension.

class django_ca.extensions.ListExtension(value=None)[source]

Bases: django_ca.extensions.IterableExtension

Base class for extensions with multiple ordered values.

class django_ca.extensions.OrderedSetExtension(value=None)[source]

Bases: django_ca.extensions.IterableExtension

Base class for extensions that contain a set of values.

For reproducibility, any serialization will always sort the values contained in this extension.

Extensions derived from this class can be used like a normal set, for example:

>>> e = OrderedSetExtension({'value': {'foo', }})
>>> e.add('bar')
>>> e
<OrderedSetExtension: ['bar', 'foo'], critical=False>
>>> e -= {'foo', }
>>> e
<OrderedSetExtension: ['bar'], critical=False>
class django_ca.extensions.KeyIdExtension(value=None)[source]

Bases: django_ca.extensions.Extension

Base class for extensions that contain a KeyID as value.

The value can be a hex str or bytes:

>>> KeyIdExtension({'value': '33:33'})
<KeyIdExtension: b'33', critical=False>
>>> KeyIdExtension({'value': b'33'})
<KeyIdExtension: b'33', critical=False>
class django_ca.extensions.CRLDistributionPointsBase(value=None)[source]

Bases: django_ca.extensions.ListExtension

Base class for CRLDistributionPoints and FreshestCRL.

class django_ca.extensions.AlternativeNameExtension(value=None)[source]

Bases: django_ca.extensions.ListExtension

Base class for extensions that contain a list of general names.

This class also allows you to pass GeneralName instances:

>>> san = SubjectAlternativeName({'value': [x509.DNSName('example.com'), 'example.net']})
>>> san
<SubjectAlternativeName: ['DNS:example.com', 'DNS:example.net'], critical=False>
>>> 'example.com' in san, 'DNS:example.com' in san, x509.DNSName('example.com') in san
(True, True, True)
class django_ca.extensions.NullExtension(value=None)[source]

Bases: django_ca.extensions.Extension

Base class for extensions that have a NULL value.

Extensions using this base class will ignore any "value" key in their dict, only the "critical" key is relevant:

>>> OCSPNoCheck()
<OCSPNoCheck: critical=False>
>>> OCSPNoCheck({'critical': True})
<OCSPNoCheck: critical=True>
>>> OCSPNoCheck({'critical': True})
<OCSPNoCheck: critical=True>
>>> OCSPNoCheck(x509.extensions.Extension(oid=ExtensionOID.OCSP_NO_CHECK, critical=True, value=None))
<OCSPNoCheck: critical=True>