update windows build to Python 3.7
This commit is contained in:
parent
73105fa71e
commit
ddc59ab92d
5761 changed files with 750298 additions and 213405 deletions
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from cryptography.x509 import certificate_transparency
|
||||
from cryptography.x509.base import (
|
||||
Certificate, CertificateBuilder, CertificateRevocationList,
|
||||
CertificateRevocationListBuilder,
|
||||
|
|
@ -11,26 +12,31 @@ from cryptography.x509.base import (
|
|||
InvalidVersion, RevokedCertificate, RevokedCertificateBuilder,
|
||||
Version, load_der_x509_certificate, load_der_x509_crl, load_der_x509_csr,
|
||||
load_pem_x509_certificate, load_pem_x509_crl, load_pem_x509_csr,
|
||||
random_serial_number,
|
||||
)
|
||||
from cryptography.x509.extensions import (
|
||||
AccessDescription, AuthorityInformationAccess,
|
||||
AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints,
|
||||
CRLNumber, CRLReason, CertificateIssuer, CertificatePolicies,
|
||||
DistributionPoint, DuplicateExtension, ExtendedKeyUsage, Extension,
|
||||
ExtensionNotFound, ExtensionType, Extensions, GeneralNames,
|
||||
InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName, KeyUsage,
|
||||
NameConstraints, NoticeReference, OCSPNoCheck, PolicyInformation,
|
||||
ReasonFlags, SubjectAlternativeName, SubjectKeyIdentifier,
|
||||
UnrecognizedExtension, UnsupportedExtension, UserNotice
|
||||
DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage,
|
||||
Extension, ExtensionNotFound, ExtensionType, Extensions, FreshestCRL,
|
||||
GeneralNames, InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName,
|
||||
KeyUsage, NameConstraints, NoticeReference, OCSPNoCheck, OCSPNonce,
|
||||
PolicyConstraints, PolicyInformation, PrecertPoison,
|
||||
PrecertificateSignedCertificateTimestamps, ReasonFlags,
|
||||
SubjectAlternativeName, SubjectKeyIdentifier, TLSFeature, TLSFeatureType,
|
||||
UnrecognizedExtension, UserNotice
|
||||
)
|
||||
from cryptography.x509.general_name import (
|
||||
DNSName, DirectoryName, GeneralName, IPAddress, OtherName, RFC822Name,
|
||||
RegisteredID, UniformResourceIdentifier, UnsupportedGeneralNameType,
|
||||
_GENERAL_NAMES
|
||||
)
|
||||
from cryptography.x509.name import Name, NameAttribute
|
||||
from cryptography.x509.name import (
|
||||
Name, NameAttribute, RelativeDistinguishedName
|
||||
)
|
||||
from cryptography.x509.oid import (
|
||||
AuthorityInformationAccessOID, CRLEntryExtensionOID, CRLExtensionOID,
|
||||
AuthorityInformationAccessOID, CRLEntryExtensionOID,
|
||||
CertificatePoliciesOID, ExtendedKeyUsageOID, ExtensionOID, NameOID,
|
||||
ObjectIdentifier, SignatureAlgorithmOID, _SIG_OIDS_TO_HASH
|
||||
)
|
||||
|
|
@ -69,6 +75,7 @@ OID_RSA_WITH_SHA224 = SignatureAlgorithmOID.RSA_WITH_SHA224
|
|||
OID_RSA_WITH_SHA256 = SignatureAlgorithmOID.RSA_WITH_SHA256
|
||||
OID_RSA_WITH_SHA384 = SignatureAlgorithmOID.RSA_WITH_SHA384
|
||||
OID_RSA_WITH_SHA512 = SignatureAlgorithmOID.RSA_WITH_SHA512
|
||||
OID_RSASSA_PSS = SignatureAlgorithmOID.RSASSA_PSS
|
||||
|
||||
OID_COMMON_NAME = NameOID.COMMON_NAME
|
||||
OID_COUNTRY_NAME = NameOID.COUNTRY_NAME
|
||||
|
|
@ -104,26 +111,31 @@ OID_INVALIDITY_DATE = CRLEntryExtensionOID.INVALIDITY_DATE
|
|||
OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS
|
||||
OID_OCSP = AuthorityInformationAccessOID.OCSP
|
||||
|
||||
|
||||
__all__ = [
|
||||
"certificate_transparency",
|
||||
"load_pem_x509_certificate",
|
||||
"load_der_x509_certificate",
|
||||
"load_pem_x509_csr",
|
||||
"load_der_x509_csr",
|
||||
"load_pem_x509_crl",
|
||||
"load_der_x509_crl",
|
||||
"random_serial_number",
|
||||
"InvalidVersion",
|
||||
"DeltaCRLIndicator",
|
||||
"DuplicateExtension",
|
||||
"UnsupportedExtension",
|
||||
"ExtensionNotFound",
|
||||
"UnsupportedGeneralNameType",
|
||||
"NameAttribute",
|
||||
"Name",
|
||||
"RelativeDistinguishedName",
|
||||
"ObjectIdentifier",
|
||||
"ExtensionType",
|
||||
"Extensions",
|
||||
"Extension",
|
||||
"ExtendedKeyUsage",
|
||||
"FreshestCRL",
|
||||
"TLSFeature",
|
||||
"TLSFeatureType",
|
||||
"OCSPNoCheck",
|
||||
"BasicConstraints",
|
||||
"CRLNumber",
|
||||
|
|
@ -165,9 +177,12 @@ __all__ = [
|
|||
"OID_CA_ISSUERS",
|
||||
"OID_OCSP",
|
||||
"_GENERAL_NAMES",
|
||||
"CRLExtensionOID",
|
||||
"CertificateIssuer",
|
||||
"CRLReason",
|
||||
"InvalidityDate",
|
||||
"UnrecognizedExtension",
|
||||
"PolicyConstraints",
|
||||
"PrecertificateSignedCertificateTimestamps",
|
||||
"PrecertPoison",
|
||||
"OCSPNonce",
|
||||
]
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -6,6 +6,7 @@ from __future__ import absolute_import, division, print_function
|
|||
|
||||
import abc
|
||||
import datetime
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
import six
|
||||
|
|
@ -19,6 +20,27 @@ from cryptography.x509.name import Name
|
|||
_UNIX_EPOCH = datetime.datetime(1970, 1, 1)
|
||||
|
||||
|
||||
def _reject_duplicate_extension(extension, extensions):
|
||||
# This is quadratic in the number of extensions
|
||||
for e in extensions:
|
||||
if e.oid == extension.oid:
|
||||
raise ValueError('This extension has already been set.')
|
||||
|
||||
|
||||
def _convert_to_naive_utc_time(time):
|
||||
"""Normalizes a datetime to a naive datetime in UTC.
|
||||
|
||||
time -- datetime to normalize. Assumed to be in UTC if not timezone
|
||||
aware.
|
||||
"""
|
||||
if time.tzinfo is not None:
|
||||
offset = time.utcoffset()
|
||||
offset = offset if offset else datetime.timedelta()
|
||||
return time.replace(tzinfo=None) - offset
|
||||
else:
|
||||
return time
|
||||
|
||||
|
||||
class Version(Enum):
|
||||
v1 = 0
|
||||
v3 = 2
|
||||
|
|
@ -63,7 +85,7 @@ class Certificate(object):
|
|||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def serial(self):
|
||||
def serial_number(self):
|
||||
"""
|
||||
Returns certificate serial number
|
||||
"""
|
||||
|
|
@ -111,6 +133,12 @@ class Certificate(object):
|
|||
in the certificate.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def signature_algorithm_oid(self):
|
||||
"""
|
||||
Returns the ObjectIdentifier of the signature algorithm.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def extensions(self):
|
||||
"""
|
||||
|
|
@ -168,6 +196,13 @@ class CertificateRevocationList(object):
|
|||
Returns bytes using digest passed.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_revoked_certificate_by_serial_number(self, serial_number):
|
||||
"""
|
||||
Returns an instance of RevokedCertificate or None if the serial_number
|
||||
is not in the CRL.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def signature_hash_algorithm(self):
|
||||
"""
|
||||
|
|
@ -175,6 +210,12 @@ class CertificateRevocationList(object):
|
|||
in the certificate.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def signature_algorithm_oid(self):
|
||||
"""
|
||||
Returns the ObjectIdentifier of the signature algorithm.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def issuer(self):
|
||||
"""
|
||||
|
|
@ -223,6 +264,30 @@ class CertificateRevocationList(object):
|
|||
Checks not equal.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __len__(self):
|
||||
"""
|
||||
Number of revoked certificates in the CRL.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __getitem__(self, idx):
|
||||
"""
|
||||
Returns a revoked certificate (or slice of revoked certificates).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __iter__(self):
|
||||
"""
|
||||
Iterator over the revoked certificates
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_signature_valid(self, public_key):
|
||||
"""
|
||||
Verifies signature of revocation list against given public key.
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class CertificateSigningRequest(object):
|
||||
|
|
@ -263,6 +328,12 @@ class CertificateSigningRequest(object):
|
|||
in the certificate.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def signature_algorithm_oid(self):
|
||||
"""
|
||||
Returns the ObjectIdentifier of the signature algorithm.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def extensions(self):
|
||||
"""
|
||||
|
|
@ -288,6 +359,12 @@ class CertificateSigningRequest(object):
|
|||
2986.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def is_signature_valid(self):
|
||||
"""
|
||||
Verifies signature of signing request.
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RevokedCertificate(object):
|
||||
|
|
@ -336,11 +413,8 @@ class CertificateSigningRequestBuilder(object):
|
|||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = Extension(extension.oid, critical, extension)
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
|
||||
# TODO: This is quadratic in the number of extensions
|
||||
for e in self._extensions:
|
||||
if e.oid == extension.oid:
|
||||
raise ValueError('This extension has already been set.')
|
||||
return CertificateSigningRequestBuilder(
|
||||
self._subject_name, self._extensions + [extension]
|
||||
)
|
||||
|
|
@ -419,10 +493,13 @@ class CertificateBuilder(object):
|
|||
raise TypeError('Serial number must be of integral type.')
|
||||
if self._serial_number is not None:
|
||||
raise ValueError('The serial number may only be set once.')
|
||||
if number < 0:
|
||||
raise ValueError('The serial number should be non-negative.')
|
||||
if utils.bit_length(number) > 160: # As defined in RFC 5280
|
||||
raise ValueError('The serial number should not be more than 160 '
|
||||
if number <= 0:
|
||||
raise ValueError('The serial number should be positive.')
|
||||
|
||||
# ASN.1 integers are always signed, so most significant bit must be
|
||||
# zero.
|
||||
if number.bit_length() >= 160: # As defined in RFC 5280
|
||||
raise ValueError('The serial number should not be more than 159 '
|
||||
'bits.')
|
||||
return CertificateBuilder(
|
||||
self._issuer_name, self._subject_name,
|
||||
|
|
@ -438,6 +515,7 @@ class CertificateBuilder(object):
|
|||
raise TypeError('Expecting datetime object.')
|
||||
if self._not_valid_before is not None:
|
||||
raise ValueError('The not valid before may only be set once.')
|
||||
time = _convert_to_naive_utc_time(time)
|
||||
if time <= _UNIX_EPOCH:
|
||||
raise ValueError('The not valid before date must be after the unix'
|
||||
' epoch (1970 January 1).')
|
||||
|
|
@ -460,6 +538,7 @@ class CertificateBuilder(object):
|
|||
raise TypeError('Expecting datetime object.')
|
||||
if self._not_valid_after is not None:
|
||||
raise ValueError('The not valid after may only be set once.')
|
||||
time = _convert_to_naive_utc_time(time)
|
||||
if time <= _UNIX_EPOCH:
|
||||
raise ValueError('The not valid after date must be after the unix'
|
||||
' epoch (1970 January 1).')
|
||||
|
|
@ -483,11 +562,7 @@ class CertificateBuilder(object):
|
|||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = Extension(extension.oid, critical, extension)
|
||||
|
||||
# TODO: This is quadratic in the number of extensions
|
||||
for e in self._extensions:
|
||||
if e.oid == extension.oid:
|
||||
raise ValueError('This extension has already been set.')
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
|
||||
return CertificateBuilder(
|
||||
self._issuer_name, self._subject_name,
|
||||
|
|
@ -544,6 +619,7 @@ class CertificateRevocationListBuilder(object):
|
|||
raise TypeError('Expecting datetime object.')
|
||||
if self._last_update is not None:
|
||||
raise ValueError('Last update may only be set once.')
|
||||
last_update = _convert_to_naive_utc_time(last_update)
|
||||
if last_update <= _UNIX_EPOCH:
|
||||
raise ValueError('The last update date must be after the unix'
|
||||
' epoch (1970 January 1).')
|
||||
|
|
@ -561,6 +637,7 @@ class CertificateRevocationListBuilder(object):
|
|||
raise TypeError('Expecting datetime object.')
|
||||
if self._next_update is not None:
|
||||
raise ValueError('Last update may only be set once.')
|
||||
next_update = _convert_to_naive_utc_time(next_update)
|
||||
if next_update <= _UNIX_EPOCH:
|
||||
raise ValueError('The last update date must be after the unix'
|
||||
' epoch (1970 January 1).')
|
||||
|
|
@ -581,11 +658,7 @@ class CertificateRevocationListBuilder(object):
|
|||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = Extension(extension.oid, critical, extension)
|
||||
|
||||
# TODO: This is quadratic in the number of extensions
|
||||
for e in self._extensions:
|
||||
if e.oid == extension.oid:
|
||||
raise ValueError('This extension has already been set.')
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
return CertificateRevocationListBuilder(
|
||||
self._issuer_name, self._last_update, self._next_update,
|
||||
self._extensions + [extension], self._revoked_certificates
|
||||
|
|
@ -629,10 +702,13 @@ class RevokedCertificateBuilder(object):
|
|||
raise TypeError('Serial number must be of integral type.')
|
||||
if self._serial_number is not None:
|
||||
raise ValueError('The serial number may only be set once.')
|
||||
if number < 0:
|
||||
raise ValueError('The serial number should be non-negative.')
|
||||
if utils.bit_length(number) > 160: # As defined in RFC 5280
|
||||
raise ValueError('The serial number should not be more than 160 '
|
||||
if number <= 0:
|
||||
raise ValueError('The serial number should be positive')
|
||||
|
||||
# ASN.1 integers are always signed, so most significant bit must be
|
||||
# zero.
|
||||
if number.bit_length() >= 160: # As defined in RFC 5280
|
||||
raise ValueError('The serial number should not be more than 159 '
|
||||
'bits.')
|
||||
return RevokedCertificateBuilder(
|
||||
number, self._revocation_date, self._extensions
|
||||
|
|
@ -643,6 +719,7 @@ class RevokedCertificateBuilder(object):
|
|||
raise TypeError('Expecting datetime object.')
|
||||
if self._revocation_date is not None:
|
||||
raise ValueError('The revocation date may only be set once.')
|
||||
time = _convert_to_naive_utc_time(time)
|
||||
if time <= _UNIX_EPOCH:
|
||||
raise ValueError('The revocation date must be after the unix'
|
||||
' epoch (1970 January 1).')
|
||||
|
|
@ -655,11 +732,7 @@ class RevokedCertificateBuilder(object):
|
|||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = Extension(extension.oid, critical, extension)
|
||||
|
||||
# TODO: This is quadratic in the number of extensions
|
||||
for e in self._extensions:
|
||||
if e.oid == extension.oid:
|
||||
raise ValueError('This extension has already been set.')
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
return RevokedCertificateBuilder(
|
||||
self._serial_number, self._revocation_date,
|
||||
self._extensions + [extension]
|
||||
|
|
@ -674,3 +747,7 @@ class RevokedCertificateBuilder(object):
|
|||
)
|
||||
|
||||
return backend.create_x509_revoked_certificate(self)
|
||||
|
||||
|
||||
def random_serial_number():
|
||||
return utils.int_from_bytes(os.urandom(20), "big") >> 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import abc
|
||||
from enum import Enum
|
||||
|
||||
import six
|
||||
|
||||
|
||||
class LogEntryType(Enum):
|
||||
X509_CERTIFICATE = 0
|
||||
PRE_CERTIFICATE = 1
|
||||
|
||||
|
||||
class Version(Enum):
|
||||
v1 = 0
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class SignedCertificateTimestamp(object):
|
||||
@abc.abstractproperty
|
||||
def version(self):
|
||||
"""
|
||||
Returns the SCT version.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def log_id(self):
|
||||
"""
|
||||
Returns an identifier indicating which log this SCT is for.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def timestamp(self):
|
||||
"""
|
||||
Returns the timestamp for this SCT.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def entry_type(self):
|
||||
"""
|
||||
Returns whether this is an SCT for a certificate or pre-certificate.
|
||||
"""
|
||||
|
|
@ -10,45 +10,41 @@ import hashlib
|
|||
import ipaddress
|
||||
from enum import Enum
|
||||
|
||||
from pyasn1.codec.der import decoder
|
||||
from pyasn1.type import namedtype, univ
|
||||
from asn1crypto.keys import PublicKeyInfo
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.hazmat.primitives import constant_time, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
|
||||
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
|
||||
from cryptography.x509.certificate_transparency import (
|
||||
SignedCertificateTimestamp
|
||||
)
|
||||
from cryptography.x509.general_name import GeneralName, IPAddress, OtherName
|
||||
from cryptography.x509.name import Name
|
||||
from cryptography.x509.name import RelativeDistinguishedName
|
||||
from cryptography.x509.oid import (
|
||||
CRLEntryExtensionOID, ExtensionOID, ObjectIdentifier
|
||||
CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ObjectIdentifier,
|
||||
)
|
||||
|
||||
|
||||
class _SubjectPublicKeyInfo(univ.Sequence):
|
||||
componentType = namedtype.NamedTypes(
|
||||
namedtype.NamedType('algorithm', univ.Sequence()),
|
||||
namedtype.NamedType('subjectPublicKey', univ.BitString())
|
||||
)
|
||||
|
||||
|
||||
def _key_identifier_from_public_key(public_key):
|
||||
# This is a very slow way to do this.
|
||||
serialized = public_key.public_bytes(
|
||||
serialization.Encoding.DER,
|
||||
serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
spki, remaining = decoder.decode(
|
||||
serialized, asn1Spec=_SubjectPublicKeyInfo()
|
||||
)
|
||||
assert not remaining
|
||||
# the univ.BitString object is a tuple of bits. We need bytes and
|
||||
# pyasn1 really doesn't want to give them to us. To get it we'll
|
||||
# build an integer and convert that to bytes.
|
||||
bits = 0
|
||||
for bit in spki.getComponentByName("subjectPublicKey"):
|
||||
bits = bits << 1 | bit
|
||||
if isinstance(public_key, RSAPublicKey):
|
||||
data = public_key.public_bytes(
|
||||
serialization.Encoding.DER,
|
||||
serialization.PublicFormat.PKCS1,
|
||||
)
|
||||
elif isinstance(public_key, EllipticCurvePublicKey):
|
||||
data = public_key.public_numbers().encode_point()
|
||||
else:
|
||||
# This is a very slow way to do this.
|
||||
serialized = public_key.public_bytes(
|
||||
serialization.Encoding.DER,
|
||||
serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
|
||||
data = six.binary_type(PublicKeyInfo.load(serialized)['public_key'])
|
||||
|
||||
data = utils.int_to_bytes(bits)
|
||||
return hashlib.sha1(data).digest()
|
||||
|
||||
|
||||
|
|
@ -58,12 +54,6 @@ class DuplicateExtension(Exception):
|
|||
self.oid = oid
|
||||
|
||||
|
||||
class UnsupportedExtension(Exception):
|
||||
def __init__(self, msg, oid):
|
||||
super(UnsupportedExtension, self).__init__(msg)
|
||||
self.oid = oid
|
||||
|
||||
|
||||
class ExtensionNotFound(Exception):
|
||||
def __init__(self, msg, oid):
|
||||
super(ExtensionNotFound, self).__init__(msg)
|
||||
|
|
@ -163,13 +153,15 @@ class AuthorityKeyIdentifier(object):
|
|||
"must both be present or both None"
|
||||
)
|
||||
|
||||
if authority_cert_issuer is not None and not all(
|
||||
isinstance(x, GeneralName) for x in authority_cert_issuer
|
||||
):
|
||||
raise TypeError(
|
||||
"authority_cert_issuer must be a list of GeneralName "
|
||||
"objects"
|
||||
)
|
||||
if authority_cert_issuer is not None:
|
||||
authority_cert_issuer = list(authority_cert_issuer)
|
||||
if not all(
|
||||
isinstance(x, GeneralName) for x in authority_cert_issuer
|
||||
):
|
||||
raise TypeError(
|
||||
"authority_cert_issuer must be a list of GeneralName "
|
||||
"objects"
|
||||
)
|
||||
|
||||
if authority_cert_serial_number is not None and not isinstance(
|
||||
authority_cert_serial_number, six.integer_types
|
||||
|
|
@ -191,6 +183,14 @@ class AuthorityKeyIdentifier(object):
|
|||
authority_cert_serial_number=None
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_issuer_subject_key_identifier(cls, ski):
|
||||
return cls(
|
||||
key_identifier=ski.value.digest,
|
||||
authority_cert_issuer=None,
|
||||
authority_cert_serial_number=None
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
"<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
|
||||
|
|
@ -213,6 +213,15 @@ class AuthorityKeyIdentifier(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
if self.authority_cert_issuer is None:
|
||||
aci = None
|
||||
else:
|
||||
aci = tuple(self.authority_cert_issuer)
|
||||
return hash((
|
||||
self.key_identifier, aci, self.authority_cert_serial_number
|
||||
))
|
||||
|
||||
key_identifier = utils.read_only_property("_key_identifier")
|
||||
authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
|
||||
authority_cert_serial_number = utils.read_only_property(
|
||||
|
|
@ -254,6 +263,7 @@ class AuthorityInformationAccess(object):
|
|||
oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
|
||||
|
||||
def __init__(self, descriptions):
|
||||
descriptions = list(descriptions)
|
||||
if not all(isinstance(x, AccessDescription) for x in descriptions):
|
||||
raise TypeError(
|
||||
"Every item in the descriptions list must be an "
|
||||
|
|
@ -283,6 +293,9 @@ class AuthorityInformationAccess(object):
|
|||
def __getitem__(self, idx):
|
||||
return self._descriptions[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._descriptions))
|
||||
|
||||
|
||||
class AccessDescription(object):
|
||||
def __init__(self, access_method, access_location):
|
||||
|
|
@ -313,6 +326,9 @@ class AccessDescription(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.access_method, self.access_location))
|
||||
|
||||
access_method = utils.read_only_property("_access_method")
|
||||
access_location = utils.read_only_property("_access_location")
|
||||
|
||||
|
|
@ -359,11 +375,40 @@ class BasicConstraints(object):
|
|||
return hash((self.ca, self.path_length))
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class DeltaCRLIndicator(object):
|
||||
oid = ExtensionOID.DELTA_CRL_INDICATOR
|
||||
|
||||
def __init__(self, crl_number):
|
||||
if not isinstance(crl_number, six.integer_types):
|
||||
raise TypeError("crl_number must be an integer")
|
||||
|
||||
self._crl_number = crl_number
|
||||
|
||||
crl_number = utils.read_only_property("_crl_number")
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, DeltaCRLIndicator):
|
||||
return NotImplemented
|
||||
|
||||
return self.crl_number == other.crl_number
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.crl_number)
|
||||
|
||||
def __repr__(self):
|
||||
return "<DeltaCRLIndicator(crl_number={0.crl_number})>".format(self)
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class CRLDistributionPoints(object):
|
||||
oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
|
||||
|
||||
def __init__(self, distribution_points):
|
||||
distribution_points = list(distribution_points)
|
||||
if not all(
|
||||
isinstance(x, DistributionPoint) for x in distribution_points
|
||||
):
|
||||
|
|
@ -395,6 +440,50 @@ class CRLDistributionPoints(object):
|
|||
def __getitem__(self, idx):
|
||||
return self._distribution_points[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._distribution_points))
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class FreshestCRL(object):
|
||||
oid = ExtensionOID.FRESHEST_CRL
|
||||
|
||||
def __init__(self, distribution_points):
|
||||
distribution_points = list(distribution_points)
|
||||
if not all(
|
||||
isinstance(x, DistributionPoint) for x in distribution_points
|
||||
):
|
||||
raise TypeError(
|
||||
"distribution_points must be a list of DistributionPoint "
|
||||
"objects"
|
||||
)
|
||||
|
||||
self._distribution_points = distribution_points
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._distribution_points)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._distribution_points)
|
||||
|
||||
def __repr__(self):
|
||||
return "<FreshestCRL({0})>".format(self._distribution_points)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, FreshestCRL):
|
||||
return NotImplemented
|
||||
|
||||
return self._distribution_points == other._distribution_points
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self._distribution_points[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._distribution_points))
|
||||
|
||||
|
||||
class DistributionPoint(object):
|
||||
def __init__(self, full_name, relative_name, reasons, crl_issuer):
|
||||
|
|
@ -404,22 +493,25 @@ class DistributionPoint(object):
|
|||
"least one must be None."
|
||||
)
|
||||
|
||||
if full_name and not all(
|
||||
isinstance(x, GeneralName) for x in full_name
|
||||
):
|
||||
raise TypeError(
|
||||
"full_name must be a list of GeneralName objects"
|
||||
)
|
||||
if full_name:
|
||||
full_name = list(full_name)
|
||||
if not all(isinstance(x, GeneralName) for x in full_name):
|
||||
raise TypeError(
|
||||
"full_name must be a list of GeneralName objects"
|
||||
)
|
||||
|
||||
if relative_name and not isinstance(relative_name, Name):
|
||||
raise TypeError("relative_name must be a Name")
|
||||
if relative_name:
|
||||
if not isinstance(relative_name, RelativeDistinguishedName):
|
||||
raise TypeError(
|
||||
"relative_name must be a RelativeDistinguishedName"
|
||||
)
|
||||
|
||||
if crl_issuer and not all(
|
||||
isinstance(x, GeneralName) for x in crl_issuer
|
||||
):
|
||||
raise TypeError(
|
||||
"crl_issuer must be None or a list of general names"
|
||||
)
|
||||
if crl_issuer:
|
||||
crl_issuer = list(crl_issuer)
|
||||
if not all(isinstance(x, GeneralName) for x in crl_issuer):
|
||||
raise TypeError(
|
||||
"crl_issuer must be None or a list of general names"
|
||||
)
|
||||
|
||||
if reasons and (not isinstance(reasons, frozenset) or not all(
|
||||
isinstance(x, ReasonFlags) for x in reasons
|
||||
|
|
@ -467,6 +559,19 @@ class DistributionPoint(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
if self.full_name is not None:
|
||||
fn = tuple(self.full_name)
|
||||
else:
|
||||
fn = None
|
||||
|
||||
if self.crl_issuer is not None:
|
||||
crl_issuer = tuple(self.crl_issuer)
|
||||
else:
|
||||
crl_issuer = None
|
||||
|
||||
return hash((fn, self.relative_name, self.reasons, crl_issuer))
|
||||
|
||||
full_name = utils.read_only_property("_full_name")
|
||||
relative_name = utils.read_only_property("_relative_name")
|
||||
reasons = utils.read_only_property("_reasons")
|
||||
|
|
@ -486,11 +591,73 @@ class ReasonFlags(Enum):
|
|||
remove_from_crl = "removeFromCRL"
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class PolicyConstraints(object):
|
||||
oid = ExtensionOID.POLICY_CONSTRAINTS
|
||||
|
||||
def __init__(self, require_explicit_policy, inhibit_policy_mapping):
|
||||
if require_explicit_policy is not None and not isinstance(
|
||||
require_explicit_policy, six.integer_types
|
||||
):
|
||||
raise TypeError(
|
||||
"require_explicit_policy must be a non-negative integer or "
|
||||
"None"
|
||||
)
|
||||
|
||||
if inhibit_policy_mapping is not None and not isinstance(
|
||||
inhibit_policy_mapping, six.integer_types
|
||||
):
|
||||
raise TypeError(
|
||||
"inhibit_policy_mapping must be a non-negative integer or None"
|
||||
)
|
||||
|
||||
if inhibit_policy_mapping is None and require_explicit_policy is None:
|
||||
raise ValueError(
|
||||
"At least one of require_explicit_policy and "
|
||||
"inhibit_policy_mapping must not be None"
|
||||
)
|
||||
|
||||
self._require_explicit_policy = require_explicit_policy
|
||||
self._inhibit_policy_mapping = inhibit_policy_mapping
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
u"<PolicyConstraints(require_explicit_policy={0.require_explicit"
|
||||
u"_policy}, inhibit_policy_mapping={0.inhibit_policy_"
|
||||
u"mapping})>".format(self)
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, PolicyConstraints):
|
||||
return NotImplemented
|
||||
|
||||
return (
|
||||
self.require_explicit_policy == other.require_explicit_policy and
|
||||
self.inhibit_policy_mapping == other.inhibit_policy_mapping
|
||||
)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(
|
||||
(self.require_explicit_policy, self.inhibit_policy_mapping)
|
||||
)
|
||||
|
||||
require_explicit_policy = utils.read_only_property(
|
||||
"_require_explicit_policy"
|
||||
)
|
||||
inhibit_policy_mapping = utils.read_only_property(
|
||||
"_inhibit_policy_mapping"
|
||||
)
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class CertificatePolicies(object):
|
||||
oid = ExtensionOID.CERTIFICATE_POLICIES
|
||||
|
||||
def __init__(self, policies):
|
||||
policies = list(policies)
|
||||
if not all(isinstance(x, PolicyInformation) for x in policies):
|
||||
raise TypeError(
|
||||
"Every item in the policies list must be a "
|
||||
|
|
@ -520,6 +687,9 @@ class CertificatePolicies(object):
|
|||
def __getitem__(self, idx):
|
||||
return self._policies[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._policies))
|
||||
|
||||
|
||||
class PolicyInformation(object):
|
||||
def __init__(self, policy_identifier, policy_qualifiers):
|
||||
|
|
@ -527,15 +697,17 @@ class PolicyInformation(object):
|
|||
raise TypeError("policy_identifier must be an ObjectIdentifier")
|
||||
|
||||
self._policy_identifier = policy_identifier
|
||||
if policy_qualifiers and not all(
|
||||
isinstance(
|
||||
x, (six.text_type, UserNotice)
|
||||
) for x in policy_qualifiers
|
||||
):
|
||||
raise TypeError(
|
||||
"policy_qualifiers must be a list of strings and/or UserNotice"
|
||||
" objects or None"
|
||||
)
|
||||
|
||||
if policy_qualifiers:
|
||||
policy_qualifiers = list(policy_qualifiers)
|
||||
if not all(
|
||||
isinstance(x, (six.text_type, UserNotice))
|
||||
for x in policy_qualifiers
|
||||
):
|
||||
raise TypeError(
|
||||
"policy_qualifiers must be a list of strings and/or "
|
||||
"UserNotice objects or None"
|
||||
)
|
||||
|
||||
self._policy_qualifiers = policy_qualifiers
|
||||
|
||||
|
|
@ -557,6 +729,14 @@ class PolicyInformation(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
if self.policy_qualifiers is not None:
|
||||
pq = tuple(self.policy_qualifiers)
|
||||
else:
|
||||
pq = None
|
||||
|
||||
return hash((self.policy_identifier, pq))
|
||||
|
||||
policy_identifier = utils.read_only_property("_policy_identifier")
|
||||
policy_qualifiers = utils.read_only_property("_policy_qualifiers")
|
||||
|
||||
|
|
@ -591,6 +771,9 @@ class UserNotice(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.notice_reference, self.explicit_text))
|
||||
|
||||
notice_reference = utils.read_only_property("_notice_reference")
|
||||
explicit_text = utils.read_only_property("_explicit_text")
|
||||
|
||||
|
|
@ -598,9 +781,8 @@ class UserNotice(object):
|
|||
class NoticeReference(object):
|
||||
def __init__(self, organization, notice_numbers):
|
||||
self._organization = organization
|
||||
if not isinstance(notice_numbers, list) or not all(
|
||||
isinstance(x, int) for x in notice_numbers
|
||||
):
|
||||
notice_numbers = list(notice_numbers)
|
||||
if not all(isinstance(x, int) for x in notice_numbers):
|
||||
raise TypeError(
|
||||
"notice_numbers must be a list of integers"
|
||||
)
|
||||
|
|
@ -625,6 +807,9 @@ class NoticeReference(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.organization, tuple(self.notice_numbers)))
|
||||
|
||||
organization = utils.read_only_property("_organization")
|
||||
notice_numbers = utils.read_only_property("_notice_numbers")
|
||||
|
||||
|
|
@ -634,6 +819,7 @@ class ExtendedKeyUsage(object):
|
|||
oid = ExtensionOID.EXTENDED_KEY_USAGE
|
||||
|
||||
def __init__(self, usages):
|
||||
usages = list(usages)
|
||||
if not all(isinstance(x, ObjectIdentifier) for x in usages):
|
||||
raise TypeError(
|
||||
"Every item in the usages list must be an ObjectIdentifier"
|
||||
|
|
@ -659,12 +845,76 @@ class ExtendedKeyUsage(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._usages))
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class OCSPNoCheck(object):
|
||||
oid = ExtensionOID.OCSP_NO_CHECK
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class PrecertPoison(object):
|
||||
oid = ExtensionOID.PRECERT_POISON
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class TLSFeature(object):
|
||||
oid = ExtensionOID.TLS_FEATURE
|
||||
|
||||
def __init__(self, features):
|
||||
features = list(features)
|
||||
if (
|
||||
not all(isinstance(x, TLSFeatureType) for x in features) or
|
||||
len(features) == 0
|
||||
):
|
||||
raise TypeError(
|
||||
"features must be a list of elements from the TLSFeatureType "
|
||||
"enum"
|
||||
)
|
||||
|
||||
self._features = features
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._features)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._features)
|
||||
|
||||
def __repr__(self):
|
||||
return "<TLSFeature(features={0._features})>".format(self)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, TLSFeature):
|
||||
return NotImplemented
|
||||
|
||||
return self._features == other._features
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self._features[idx]
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._features))
|
||||
|
||||
|
||||
class TLSFeatureType(Enum):
|
||||
# status_request is defined in RFC 6066 and is used for what is commonly
|
||||
# called OCSP Must-Staple when present in the TLS Feature extension in an
|
||||
# X.509 certificate.
|
||||
status_request = 5
|
||||
# status_request_v2 is defined in RFC 6961 and allows multiple OCSP
|
||||
# responses to be provided. It is not currently in use by clients or
|
||||
# servers.
|
||||
status_request_v2 = 17
|
||||
|
||||
|
||||
_TLS_FEATURE_TYPE_TO_ENUM = dict((x.value, x) for x in TLSFeatureType)
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class InhibitAnyPolicy(object):
|
||||
oid = ExtensionOID.INHIBIT_ANY_POLICY
|
||||
|
|
@ -690,6 +940,9 @@ class InhibitAnyPolicy(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.skip_certs)
|
||||
|
||||
skip_certs = utils.read_only_property("_skip_certs")
|
||||
|
||||
|
||||
|
|
@ -778,6 +1031,15 @@ class KeyUsage(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((
|
||||
self.digital_signature, self.content_commitment,
|
||||
self.key_encipherment, self.data_encipherment,
|
||||
self.key_agreement, self.key_cert_sign,
|
||||
self.crl_sign, self._encipher_only,
|
||||
self._decipher_only
|
||||
))
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class NameConstraints(object):
|
||||
|
|
@ -785,6 +1047,7 @@ class NameConstraints(object):
|
|||
|
||||
def __init__(self, permitted_subtrees, excluded_subtrees):
|
||||
if permitted_subtrees is not None:
|
||||
permitted_subtrees = list(permitted_subtrees)
|
||||
if not all(
|
||||
isinstance(x, GeneralName) for x in permitted_subtrees
|
||||
):
|
||||
|
|
@ -796,6 +1059,7 @@ class NameConstraints(object):
|
|||
self._validate_ip_name(permitted_subtrees)
|
||||
|
||||
if excluded_subtrees is not None:
|
||||
excluded_subtrees = list(excluded_subtrees)
|
||||
if not all(
|
||||
isinstance(x, GeneralName) for x in excluded_subtrees
|
||||
):
|
||||
|
|
@ -842,6 +1106,19 @@ class NameConstraints(object):
|
|||
u"excluded_subtrees={0.excluded_subtrees})>".format(self)
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
if self.permitted_subtrees is not None:
|
||||
ps = tuple(self.permitted_subtrees)
|
||||
else:
|
||||
ps = None
|
||||
|
||||
if self.excluded_subtrees is not None:
|
||||
es = tuple(self.excluded_subtrees)
|
||||
else:
|
||||
es = None
|
||||
|
||||
return hash((ps, es))
|
||||
|
||||
permitted_subtrees = utils.read_only_property("_permitted_subtrees")
|
||||
excluded_subtrees = utils.read_only_property("_excluded_subtrees")
|
||||
|
||||
|
|
@ -881,9 +1158,13 @@ class Extension(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.oid, self.critical, self.value))
|
||||
|
||||
|
||||
class GeneralNames(object):
|
||||
def __init__(self, general_names):
|
||||
general_names = list(general_names)
|
||||
if not all(isinstance(x, GeneralName) for x in general_names):
|
||||
raise TypeError(
|
||||
"Every item in the general_names list must be an "
|
||||
|
|
@ -922,6 +1203,9 @@ class GeneralNames(object):
|
|||
def __getitem__(self, idx):
|
||||
return self._general_names[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._general_names))
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class SubjectAlternativeName(object):
|
||||
|
|
@ -954,6 +1238,9 @@ class SubjectAlternativeName(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._general_names)
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class IssuerAlternativeName(object):
|
||||
|
|
@ -986,6 +1273,9 @@ class IssuerAlternativeName(object):
|
|||
def __getitem__(self, idx):
|
||||
return self._general_names[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._general_names)
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class CertificateIssuer(object):
|
||||
|
|
@ -1018,6 +1308,9 @@ class CertificateIssuer(object):
|
|||
def __getitem__(self, idx):
|
||||
return self._general_names[idx]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._general_names)
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class CRLReason(object):
|
||||
|
|
@ -1077,6 +1370,82 @@ class InvalidityDate(object):
|
|||
invalidity_date = utils.read_only_property("_invalidity_date")
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class PrecertificateSignedCertificateTimestamps(object):
|
||||
oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
|
||||
|
||||
def __init__(self, signed_certificate_timestamps):
|
||||
signed_certificate_timestamps = list(signed_certificate_timestamps)
|
||||
if not all(
|
||||
isinstance(sct, SignedCertificateTimestamp)
|
||||
for sct in signed_certificate_timestamps
|
||||
):
|
||||
raise TypeError(
|
||||
"Every item in the signed_certificate_timestamps list must be "
|
||||
"a SignedCertificateTimestamp"
|
||||
)
|
||||
self._signed_certificate_timestamps = signed_certificate_timestamps
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._signed_certificate_timestamps)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._signed_certificate_timestamps)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self._signed_certificate_timestamps[idx]
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
"<PrecertificateSignedCertificateTimestamps({0})>".format(
|
||||
list(self)
|
||||
)
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self._signed_certificate_timestamps))
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, PrecertificateSignedCertificateTimestamps):
|
||||
return NotImplemented
|
||||
|
||||
return (
|
||||
self._signed_certificate_timestamps ==
|
||||
other._signed_certificate_timestamps
|
||||
)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class OCSPNonce(object):
|
||||
oid = OCSPExtensionOID.NONCE
|
||||
|
||||
def __init__(self, nonce):
|
||||
if not isinstance(nonce, bytes):
|
||||
raise TypeError("nonce must be bytes")
|
||||
|
||||
self._nonce = nonce
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, OCSPNonce):
|
||||
return NotImplemented
|
||||
|
||||
return self.nonce == other.nonce
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.nonce)
|
||||
|
||||
def __repr__(self):
|
||||
return "<OCSPNonce(nonce={0.nonce!r})>".format(self)
|
||||
|
||||
nonce = utils.read_only_property("_nonce")
|
||||
|
||||
|
||||
@utils.register_interface(ExtensionType)
|
||||
class UnrecognizedExtension(object):
|
||||
def __init__(self, oid, value):
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ from __future__ import absolute_import, division, print_function
|
|||
|
||||
import abc
|
||||
import ipaddress
|
||||
import warnings
|
||||
from email.utils import parseaddr
|
||||
|
||||
import idna
|
||||
|
||||
import six
|
||||
|
||||
from six.moves import urllib_parse
|
||||
|
||||
from cryptography import utils
|
||||
|
|
@ -50,31 +50,45 @@ class GeneralName(object):
|
|||
@utils.register_interface(GeneralName)
|
||||
class RFC822Name(object):
|
||||
def __init__(self, value):
|
||||
if not isinstance(value, six.text_type):
|
||||
raise TypeError("value must be a unicode string")
|
||||
if isinstance(value, six.text_type):
|
||||
try:
|
||||
value.encode("ascii")
|
||||
except UnicodeEncodeError:
|
||||
value = self._idna_encode(value)
|
||||
warnings.warn(
|
||||
"RFC822Name values should be passed as an A-label string. "
|
||||
"This means unicode characters should be encoded via "
|
||||
"idna. Support for passing unicode strings (aka U-label) "
|
||||
"will be removed in a future version.",
|
||||
utils.DeprecatedIn21,
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
raise TypeError("value must be string")
|
||||
|
||||
name, address = parseaddr(value)
|
||||
parts = address.split(u"@")
|
||||
if name or not address:
|
||||
# parseaddr has found a name (e.g. Name <email>) or the entire
|
||||
# value is an empty string.
|
||||
raise ValueError("Invalid rfc822name value")
|
||||
elif len(parts) == 1:
|
||||
# Single label email name. This is valid for local delivery.
|
||||
# No IDNA encoding needed since there is no domain component.
|
||||
encoded = address.encode("ascii")
|
||||
else:
|
||||
# A normal email of the form user@domain.com. Let's attempt to
|
||||
# encode the domain component and reconstruct the address.
|
||||
encoded = parts[0].encode("ascii") + b"@" + idna.encode(parts[1])
|
||||
|
||||
self._value = value
|
||||
self._encoded = encoded
|
||||
|
||||
value = utils.read_only_property("_value")
|
||||
|
||||
@classmethod
|
||||
def _init_without_validation(cls, value):
|
||||
instance = cls.__new__(cls)
|
||||
instance._value = value
|
||||
return instance
|
||||
|
||||
def _idna_encode(self, value):
|
||||
_, address = parseaddr(value)
|
||||
parts = address.split(u"@")
|
||||
return parts[0] + "@" + idna.encode(parts[1]).decode("ascii")
|
||||
|
||||
def __repr__(self):
|
||||
return "<RFC822Name(value={0})>".format(self.value)
|
||||
return "<RFC822Name(value={0!r})>".format(self.value)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, RFC822Name):
|
||||
|
|
@ -89,18 +103,46 @@ class RFC822Name(object):
|
|||
return hash(self.value)
|
||||
|
||||
|
||||
def _idna_encode(value):
|
||||
# Retain prefixes '*.' for common/alt names and '.' for name constraints
|
||||
for prefix in ['*.', '.']:
|
||||
if value.startswith(prefix):
|
||||
value = value[len(prefix):]
|
||||
return prefix + idna.encode(value).decode("ascii")
|
||||
return idna.encode(value).decode("ascii")
|
||||
|
||||
|
||||
@utils.register_interface(GeneralName)
|
||||
class DNSName(object):
|
||||
def __init__(self, value):
|
||||
if not isinstance(value, six.text_type):
|
||||
raise TypeError("value must be a unicode string")
|
||||
if isinstance(value, six.text_type):
|
||||
try:
|
||||
value.encode("ascii")
|
||||
except UnicodeEncodeError:
|
||||
value = _idna_encode(value)
|
||||
warnings.warn(
|
||||
"DNSName values should be passed as an A-label string. "
|
||||
"This means unicode characters should be encoded via "
|
||||
"idna. Support for passing unicode strings (aka U-label) "
|
||||
"will be removed in a future version.",
|
||||
utils.DeprecatedIn21,
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
raise TypeError("value must be string")
|
||||
|
||||
self._value = value
|
||||
|
||||
value = utils.read_only_property("_value")
|
||||
|
||||
@classmethod
|
||||
def _init_without_validation(cls, value):
|
||||
instance = cls.__new__(cls)
|
||||
instance._value = value
|
||||
return instance
|
||||
|
||||
def __repr__(self):
|
||||
return "<DNSName(value={0})>".format(self.value)
|
||||
return "<DNSName(value={0!r})>".format(self.value)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, DNSName):
|
||||
|
|
@ -111,17 +153,42 @@ class DNSName(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.value)
|
||||
|
||||
|
||||
@utils.register_interface(GeneralName)
|
||||
class UniformResourceIdentifier(object):
|
||||
def __init__(self, value):
|
||||
if not isinstance(value, six.text_type):
|
||||
raise TypeError("value must be a unicode string")
|
||||
if isinstance(value, six.text_type):
|
||||
try:
|
||||
value.encode("ascii")
|
||||
except UnicodeEncodeError:
|
||||
value = self._idna_encode(value)
|
||||
warnings.warn(
|
||||
"URI values should be passed as an A-label string. "
|
||||
"This means unicode characters should be encoded via "
|
||||
"idna. Support for passing unicode strings (aka U-label) "
|
||||
" will be removed in a future version.",
|
||||
utils.DeprecatedIn21,
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
raise TypeError("value must be string")
|
||||
|
||||
self._value = value
|
||||
|
||||
value = utils.read_only_property("_value")
|
||||
|
||||
@classmethod
|
||||
def _init_without_validation(cls, value):
|
||||
instance = cls.__new__(cls)
|
||||
instance._value = value
|
||||
return instance
|
||||
|
||||
def _idna_encode(self, value):
|
||||
parsed = urllib_parse.urlparse(value)
|
||||
if not parsed.hostname:
|
||||
netloc = ""
|
||||
elif parsed.port:
|
||||
if parsed.port:
|
||||
netloc = (
|
||||
idna.encode(parsed.hostname) +
|
||||
":{0}".format(parsed.port).encode("ascii")
|
||||
|
|
@ -132,22 +199,17 @@ class UniformResourceIdentifier(object):
|
|||
# Note that building a URL in this fashion means it should be
|
||||
# semantically indistinguishable from the original but is not
|
||||
# guaranteed to be exactly the same.
|
||||
uri = urllib_parse.urlunparse((
|
||||
return urllib_parse.urlunparse((
|
||||
parsed.scheme,
|
||||
netloc,
|
||||
parsed.path,
|
||||
parsed.params,
|
||||
parsed.query,
|
||||
parsed.fragment
|
||||
)).encode("ascii")
|
||||
|
||||
self._value = value
|
||||
self._encoded = uri
|
||||
|
||||
value = utils.read_only_property("_value")
|
||||
))
|
||||
|
||||
def __repr__(self):
|
||||
return "<UniformResourceIdentifier(value={0})>".format(self.value)
|
||||
return "<UniformResourceIdentifier(value={0!r})>".format(self.value)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, UniformResourceIdentifier):
|
||||
|
|
@ -184,6 +246,9 @@ class DirectoryName(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.value)
|
||||
|
||||
|
||||
@utils.register_interface(GeneralName)
|
||||
class RegisteredID(object):
|
||||
|
|
@ -207,6 +272,9 @@ class RegisteredID(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.value)
|
||||
|
||||
|
||||
@utils.register_interface(GeneralName)
|
||||
class IPAddress(object):
|
||||
|
|
@ -242,6 +310,9 @@ class IPAddress(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.value)
|
||||
|
||||
|
||||
@utils.register_interface(GeneralName)
|
||||
class OtherName(object):
|
||||
|
|
@ -269,3 +340,6 @@ class OtherName(object):
|
|||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.type_id, self.value))
|
||||
|
|
|
|||
|
|
@ -4,14 +4,41 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from enum import Enum
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.x509.oid import ObjectIdentifier
|
||||
from cryptography.x509.oid import NameOID, ObjectIdentifier
|
||||
|
||||
|
||||
class _ASN1Type(Enum):
|
||||
UTF8String = 12
|
||||
NumericString = 18
|
||||
PrintableString = 19
|
||||
T61String = 20
|
||||
IA5String = 22
|
||||
UTCTime = 23
|
||||
GeneralizedTime = 24
|
||||
VisibleString = 26
|
||||
UniversalString = 28
|
||||
BMPString = 30
|
||||
|
||||
|
||||
_ASN1_TYPE_TO_ENUM = dict((i.value, i) for i in _ASN1Type)
|
||||
_SENTINEL = object()
|
||||
_NAMEOID_DEFAULT_TYPE = {
|
||||
NameOID.COUNTRY_NAME: _ASN1Type.PrintableString,
|
||||
NameOID.JURISDICTION_COUNTRY_NAME: _ASN1Type.PrintableString,
|
||||
NameOID.SERIAL_NUMBER: _ASN1Type.PrintableString,
|
||||
NameOID.DN_QUALIFIER: _ASN1Type.PrintableString,
|
||||
NameOID.EMAIL_ADDRESS: _ASN1Type.IA5String,
|
||||
NameOID.DOMAIN_COMPONENT: _ASN1Type.IA5String,
|
||||
}
|
||||
|
||||
|
||||
class NameAttribute(object):
|
||||
def __init__(self, oid, value):
|
||||
def __init__(self, oid, value, _type=_SENTINEL):
|
||||
if not isinstance(oid, ObjectIdentifier):
|
||||
raise TypeError(
|
||||
"oid argument must be an ObjectIdentifier instance."
|
||||
|
|
@ -22,8 +49,33 @@ class NameAttribute(object):
|
|||
"value argument must be a text type."
|
||||
)
|
||||
|
||||
if (
|
||||
oid == NameOID.COUNTRY_NAME or
|
||||
oid == NameOID.JURISDICTION_COUNTRY_NAME
|
||||
):
|
||||
if len(value.encode("utf8")) != 2:
|
||||
raise ValueError(
|
||||
"Country name must be a 2 character country code"
|
||||
)
|
||||
|
||||
if len(value) == 0:
|
||||
raise ValueError("Value cannot be an empty string")
|
||||
|
||||
# The appropriate ASN1 string type varies by OID and is defined across
|
||||
# multiple RFCs including 2459, 3280, and 5280. In general UTF8String
|
||||
# is preferred (2459), but 3280 and 5280 specify several OIDs with
|
||||
# alternate types. This means when we see the sentinel value we need
|
||||
# to look up whether the OID has a non-UTF8 type. If it does, set it
|
||||
# to that. Otherwise, UTF8!
|
||||
if _type == _SENTINEL:
|
||||
_type = _NAMEOID_DEFAULT_TYPE.get(oid, _ASN1Type.UTF8String)
|
||||
|
||||
if not isinstance(_type, _ASN1Type):
|
||||
raise TypeError("_type must be from the _ASN1Type enum")
|
||||
|
||||
self._oid = oid
|
||||
self._value = value
|
||||
self._type = _type
|
||||
|
||||
oid = utils.read_only_property("_oid")
|
||||
value = utils.read_only_property("_value")
|
||||
|
|
@ -47,13 +99,71 @@ class NameAttribute(object):
|
|||
return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self)
|
||||
|
||||
|
||||
class Name(object):
|
||||
class RelativeDistinguishedName(object):
|
||||
def __init__(self, attributes):
|
||||
attributes = list(attributes)
|
||||
if not attributes:
|
||||
raise ValueError("a relative distinguished name cannot be empty")
|
||||
if not all(isinstance(x, NameAttribute) for x in attributes):
|
||||
raise TypeError("attributes must be an iterable of NameAttribute")
|
||||
|
||||
# Keep list and frozenset to preserve attribute order where it matters
|
||||
self._attributes = attributes
|
||||
self._attribute_set = frozenset(attributes)
|
||||
|
||||
if len(self._attribute_set) != len(attributes):
|
||||
raise ValueError("duplicate attributes are not allowed")
|
||||
|
||||
def get_attributes_for_oid(self, oid):
|
||||
return [i for i in self if i.oid == oid]
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, RelativeDistinguishedName):
|
||||
return NotImplemented
|
||||
|
||||
return self._attribute_set == other._attribute_set
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._attribute_set)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._attributes)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._attributes)
|
||||
|
||||
def __repr__(self):
|
||||
return "<RelativeDistinguishedName({0!r})>".format(list(self))
|
||||
|
||||
|
||||
class Name(object):
|
||||
def __init__(self, attributes):
|
||||
attributes = list(attributes)
|
||||
if all(isinstance(x, NameAttribute) for x in attributes):
|
||||
self._attributes = [
|
||||
RelativeDistinguishedName([x]) for x in attributes
|
||||
]
|
||||
elif all(isinstance(x, RelativeDistinguishedName) for x in attributes):
|
||||
self._attributes = attributes
|
||||
else:
|
||||
raise TypeError(
|
||||
"attributes must be a list of NameAttribute"
|
||||
" or a list RelativeDistinguishedName"
|
||||
)
|
||||
|
||||
def get_attributes_for_oid(self, oid):
|
||||
return [i for i in self if i.oid == oid]
|
||||
|
||||
@property
|
||||
def rdns(self):
|
||||
return self._attributes
|
||||
|
||||
def public_bytes(self, backend):
|
||||
return backend.x509_name_bytes(self)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Name):
|
||||
return NotImplemented
|
||||
|
|
@ -69,10 +179,12 @@ class Name(object):
|
|||
return hash(tuple(self._attributes))
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._attributes)
|
||||
for rdn in self._attributes:
|
||||
for ava in rdn:
|
||||
yield ava
|
||||
|
||||
def __len__(self):
|
||||
return len(self._attributes)
|
||||
return sum(len(rdn) for rdn in self._attributes)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Name({0!r})>".format(self._attributes)
|
||||
return "<Name({0!r})>".format(list(self))
|
||||
|
|
|
|||
416
Lib/site-packages/cryptography/x509/ocsp.py
Normal file
416
Lib/site-packages/cryptography/x509/ocsp.py
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
# This file is dual licensed under the terms of the Apache License, Version
|
||||
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
|
||||
# for complete details.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import abc
|
||||
import datetime
|
||||
from enum import Enum
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.x509.base import (
|
||||
_UNIX_EPOCH, _convert_to_naive_utc_time, _reject_duplicate_extension
|
||||
)
|
||||
|
||||
|
||||
_OIDS_TO_HASH = {
|
||||
"1.3.14.3.2.26": hashes.SHA1(),
|
||||
"2.16.840.1.101.3.4.2.4": hashes.SHA224(),
|
||||
"2.16.840.1.101.3.4.2.1": hashes.SHA256(),
|
||||
"2.16.840.1.101.3.4.2.2": hashes.SHA384(),
|
||||
"2.16.840.1.101.3.4.2.3": hashes.SHA512(),
|
||||
}
|
||||
|
||||
|
||||
class OCSPResponderEncoding(Enum):
|
||||
HASH = "By Hash"
|
||||
NAME = "By Name"
|
||||
|
||||
|
||||
class OCSPResponseStatus(Enum):
|
||||
SUCCESSFUL = 0
|
||||
MALFORMED_REQUEST = 1
|
||||
INTERNAL_ERROR = 2
|
||||
TRY_LATER = 3
|
||||
SIG_REQUIRED = 5
|
||||
UNAUTHORIZED = 6
|
||||
|
||||
|
||||
_RESPONSE_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPResponseStatus)
|
||||
_ALLOWED_HASHES = (
|
||||
hashes.SHA1, hashes.SHA224, hashes.SHA256,
|
||||
hashes.SHA384, hashes.SHA512
|
||||
)
|
||||
|
||||
|
||||
def _verify_algorithm(algorithm):
|
||||
if not isinstance(algorithm, _ALLOWED_HASHES):
|
||||
raise ValueError(
|
||||
"Algorithm must be SHA1, SHA224, SHA256, SHA384, or SHA512"
|
||||
)
|
||||
|
||||
|
||||
class OCSPCertStatus(Enum):
|
||||
GOOD = 0
|
||||
REVOKED = 1
|
||||
UNKNOWN = 2
|
||||
|
||||
|
||||
_CERT_STATUS_TO_ENUM = dict((x.value, x) for x in OCSPCertStatus)
|
||||
|
||||
|
||||
def load_der_ocsp_request(data):
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
return backend.load_der_ocsp_request(data)
|
||||
|
||||
|
||||
def load_der_ocsp_response(data):
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
return backend.load_der_ocsp_response(data)
|
||||
|
||||
|
||||
class OCSPRequestBuilder(object):
|
||||
def __init__(self, request=None, extensions=[]):
|
||||
self._request = request
|
||||
self._extensions = extensions
|
||||
|
||||
def add_certificate(self, cert, issuer, algorithm):
|
||||
if self._request is not None:
|
||||
raise ValueError("Only one certificate can be added to a request")
|
||||
|
||||
_verify_algorithm(algorithm)
|
||||
if (
|
||||
not isinstance(cert, x509.Certificate) or
|
||||
not isinstance(issuer, x509.Certificate)
|
||||
):
|
||||
raise TypeError("cert and issuer must be a Certificate")
|
||||
|
||||
return OCSPRequestBuilder((cert, issuer, algorithm), self._extensions)
|
||||
|
||||
def add_extension(self, extension, critical):
|
||||
if not isinstance(extension, x509.ExtensionType):
|
||||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = x509.Extension(extension.oid, critical, extension)
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
|
||||
return OCSPRequestBuilder(
|
||||
self._request, self._extensions + [extension]
|
||||
)
|
||||
|
||||
def build(self):
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
if self._request is None:
|
||||
raise ValueError("You must add a certificate before building")
|
||||
|
||||
return backend.create_ocsp_request(self)
|
||||
|
||||
|
||||
class _SingleResponse(object):
|
||||
def __init__(self, cert, issuer, algorithm, cert_status, this_update,
|
||||
next_update, revocation_time, revocation_reason):
|
||||
if (
|
||||
not isinstance(cert, x509.Certificate) or
|
||||
not isinstance(issuer, x509.Certificate)
|
||||
):
|
||||
raise TypeError("cert and issuer must be a Certificate")
|
||||
|
||||
_verify_algorithm(algorithm)
|
||||
if not isinstance(this_update, datetime.datetime):
|
||||
raise TypeError("this_update must be a datetime object")
|
||||
if (
|
||||
next_update is not None and
|
||||
not isinstance(next_update, datetime.datetime)
|
||||
):
|
||||
raise TypeError("next_update must be a datetime object or None")
|
||||
|
||||
self._cert = cert
|
||||
self._issuer = issuer
|
||||
self._algorithm = algorithm
|
||||
self._this_update = this_update
|
||||
self._next_update = next_update
|
||||
|
||||
if not isinstance(cert_status, OCSPCertStatus):
|
||||
raise TypeError(
|
||||
"cert_status must be an item from the OCSPCertStatus enum"
|
||||
)
|
||||
if cert_status is not OCSPCertStatus.REVOKED:
|
||||
if revocation_time is not None:
|
||||
raise ValueError(
|
||||
"revocation_time can only be provided if the certificate "
|
||||
"is revoked"
|
||||
)
|
||||
if revocation_reason is not None:
|
||||
raise ValueError(
|
||||
"revocation_reason can only be provided if the certificate"
|
||||
" is revoked"
|
||||
)
|
||||
else:
|
||||
if not isinstance(revocation_time, datetime.datetime):
|
||||
raise TypeError("revocation_time must be a datetime object")
|
||||
|
||||
revocation_time = _convert_to_naive_utc_time(revocation_time)
|
||||
if revocation_time <= _UNIX_EPOCH:
|
||||
raise ValueError('The revocation_time must be after the unix'
|
||||
' epoch (1970 January 1).')
|
||||
|
||||
if (
|
||||
revocation_reason is not None and
|
||||
not isinstance(revocation_reason, x509.ReasonFlags)
|
||||
):
|
||||
raise TypeError(
|
||||
"revocation_reason must be an item from the ReasonFlags "
|
||||
"enum or None"
|
||||
)
|
||||
|
||||
self._cert_status = cert_status
|
||||
self._revocation_time = revocation_time
|
||||
self._revocation_reason = revocation_reason
|
||||
|
||||
|
||||
class OCSPResponseBuilder(object):
|
||||
def __init__(self, response=None, responder_id=None, certs=None,
|
||||
extensions=[]):
|
||||
self._response = response
|
||||
self._responder_id = responder_id
|
||||
self._certs = certs
|
||||
self._extensions = extensions
|
||||
|
||||
def add_response(self, cert, issuer, algorithm, cert_status, this_update,
|
||||
next_update, revocation_time, revocation_reason):
|
||||
if self._response is not None:
|
||||
raise ValueError("Only one response per OCSPResponse.")
|
||||
|
||||
singleresp = _SingleResponse(
|
||||
cert, issuer, algorithm, cert_status, this_update, next_update,
|
||||
revocation_time, revocation_reason
|
||||
)
|
||||
return OCSPResponseBuilder(
|
||||
singleresp, self._responder_id,
|
||||
self._certs, self._extensions,
|
||||
)
|
||||
|
||||
def responder_id(self, encoding, responder_cert):
|
||||
if self._responder_id is not None:
|
||||
raise ValueError("responder_id can only be set once")
|
||||
if not isinstance(responder_cert, x509.Certificate):
|
||||
raise TypeError("responder_cert must be a Certificate")
|
||||
if not isinstance(encoding, OCSPResponderEncoding):
|
||||
raise TypeError(
|
||||
"encoding must be an element from OCSPResponderEncoding"
|
||||
)
|
||||
|
||||
return OCSPResponseBuilder(
|
||||
self._response, (responder_cert, encoding),
|
||||
self._certs, self._extensions,
|
||||
)
|
||||
|
||||
def certificates(self, certs):
|
||||
if self._certs is not None:
|
||||
raise ValueError("certificates may only be set once")
|
||||
certs = list(certs)
|
||||
if len(certs) == 0:
|
||||
raise ValueError("certs must not be an empty list")
|
||||
if not all(isinstance(x, x509.Certificate) for x in certs):
|
||||
raise TypeError("certs must be a list of Certificates")
|
||||
return OCSPResponseBuilder(
|
||||
self._response, self._responder_id,
|
||||
certs, self._extensions,
|
||||
)
|
||||
|
||||
def add_extension(self, extension, critical):
|
||||
if not isinstance(extension, x509.ExtensionType):
|
||||
raise TypeError("extension must be an ExtensionType")
|
||||
|
||||
extension = x509.Extension(extension.oid, critical, extension)
|
||||
_reject_duplicate_extension(extension, self._extensions)
|
||||
|
||||
return OCSPResponseBuilder(
|
||||
self._response, self._responder_id,
|
||||
self._certs, self._extensions + [extension],
|
||||
)
|
||||
|
||||
def sign(self, private_key, algorithm):
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
if self._response is None:
|
||||
raise ValueError("You must add a response before signing")
|
||||
if self._responder_id is None:
|
||||
raise ValueError("You must add a responder_id before signing")
|
||||
|
||||
if not isinstance(algorithm, hashes.HashAlgorithm):
|
||||
raise TypeError("Algorithm must be a registered hash algorithm.")
|
||||
|
||||
return backend.create_ocsp_response(
|
||||
OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def build_unsuccessful(cls, response_status):
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
if not isinstance(response_status, OCSPResponseStatus):
|
||||
raise TypeError(
|
||||
"response_status must be an item from OCSPResponseStatus"
|
||||
)
|
||||
if response_status is OCSPResponseStatus.SUCCESSFUL:
|
||||
raise ValueError("response_status cannot be SUCCESSFUL")
|
||||
|
||||
return backend.create_ocsp_response(response_status, None, None, None)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class OCSPRequest(object):
|
||||
@abc.abstractproperty
|
||||
def issuer_key_hash(self):
|
||||
"""
|
||||
The hash of the issuer public key
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def issuer_name_hash(self):
|
||||
"""
|
||||
The hash of the issuer name
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def hash_algorithm(self):
|
||||
"""
|
||||
The hash algorithm used in the issuer name and key hashes
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def serial_number(self):
|
||||
"""
|
||||
The serial number of the cert whose status is being checked
|
||||
"""
|
||||
@abc.abstractmethod
|
||||
def public_bytes(self, encoding):
|
||||
"""
|
||||
Serializes the request to DER
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def extensions(self):
|
||||
"""
|
||||
The list of request extensions. Not single request extensions.
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class OCSPResponse(object):
|
||||
@abc.abstractproperty
|
||||
def response_status(self):
|
||||
"""
|
||||
The status of the response. This is a value from the OCSPResponseStatus
|
||||
enumeration
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def signature_algorithm_oid(self):
|
||||
"""
|
||||
The ObjectIdentifier of the signature algorithm
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def signature(self):
|
||||
"""
|
||||
The signature bytes
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def tbs_response_bytes(self):
|
||||
"""
|
||||
The tbsResponseData bytes
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def certificates(self):
|
||||
"""
|
||||
A list of certificates used to help build a chain to verify the OCSP
|
||||
response. This situation occurs when the OCSP responder uses a delegate
|
||||
certificate.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def responder_key_hash(self):
|
||||
"""
|
||||
The responder's key hash or None
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def responder_name(self):
|
||||
"""
|
||||
The responder's Name or None
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def produced_at(self):
|
||||
"""
|
||||
The time the response was produced
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def certificate_status(self):
|
||||
"""
|
||||
The status of the certificate (an element from the OCSPCertStatus enum)
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def revocation_time(self):
|
||||
"""
|
||||
The date of when the certificate was revoked or None if not
|
||||
revoked.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def revocation_reason(self):
|
||||
"""
|
||||
The reason the certificate was revoked or None if not specified or
|
||||
not revoked.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def this_update(self):
|
||||
"""
|
||||
The most recent time at which the status being indicated is known by
|
||||
the responder to have been correct
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def next_update(self):
|
||||
"""
|
||||
The time when newer information will be available
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def issuer_key_hash(self):
|
||||
"""
|
||||
The hash of the issuer public key
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def issuer_name_hash(self):
|
||||
"""
|
||||
The hash of the issuer name
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def hash_algorithm(self):
|
||||
"""
|
||||
The hash algorithm used in the issuer name and key hashes
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def serial_number(self):
|
||||
"""
|
||||
The serial number of the cert whose status is being checked
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def extensions(self):
|
||||
"""
|
||||
The list of response extensions. Not single response extensions.
|
||||
"""
|
||||
|
|
@ -4,68 +4,10 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.hazmat._oid import ObjectIdentifier
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
|
||||
|
||||
class ObjectIdentifier(object):
|
||||
def __init__(self, dotted_string):
|
||||
self._dotted_string = dotted_string
|
||||
|
||||
nodes = self._dotted_string.split(".")
|
||||
intnodes = []
|
||||
|
||||
# There must be at least 2 nodes, the first node must be 0..2, and
|
||||
# if less than 2, the second node cannot have a value outside the
|
||||
# range 0..39. All nodes must be integers.
|
||||
for node in nodes:
|
||||
try:
|
||||
intnodes.append(int(node, 0))
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
"Malformed OID: %s (non-integer nodes)" % (
|
||||
self._dotted_string))
|
||||
|
||||
if len(nodes) < 2:
|
||||
raise ValueError(
|
||||
"Malformed OID: %s (insufficient number of nodes)" % (
|
||||
self._dotted_string))
|
||||
|
||||
if intnodes[0] > 2:
|
||||
raise ValueError(
|
||||
"Malformed OID: %s (first node outside valid range)" % (
|
||||
self._dotted_string))
|
||||
|
||||
if intnodes[0] < 2 and intnodes[1] >= 40:
|
||||
raise ValueError(
|
||||
"Malformed OID: %s (second node outside valid range)" % (
|
||||
self._dotted_string))
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, ObjectIdentifier):
|
||||
return NotImplemented
|
||||
|
||||
return self.dotted_string == other.dotted_string
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __repr__(self):
|
||||
return "<ObjectIdentifier(oid={0}, name={1})>".format(
|
||||
self.dotted_string,
|
||||
self._name
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.dotted_string)
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
return _OID_NAMES.get(self, "Unknown OID")
|
||||
|
||||
dotted_string = utils.read_only_property("_dotted_string")
|
||||
|
||||
|
||||
class ExtensionOID(object):
|
||||
SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9")
|
||||
SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14")
|
||||
|
|
@ -82,10 +24,23 @@ class ExtensionOID(object):
|
|||
EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37")
|
||||
FRESHEST_CRL = ObjectIdentifier("2.5.29.46")
|
||||
INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54")
|
||||
ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28")
|
||||
AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1")
|
||||
SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11")
|
||||
OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5")
|
||||
TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24")
|
||||
CRL_NUMBER = ObjectIdentifier("2.5.29.20")
|
||||
DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27")
|
||||
PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = (
|
||||
ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2")
|
||||
)
|
||||
PRECERT_POISON = (
|
||||
ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3")
|
||||
)
|
||||
|
||||
|
||||
class OCSPExtensionOID(object):
|
||||
NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2")
|
||||
|
||||
|
||||
class CRLEntryExtensionOID(object):
|
||||
|
|
@ -94,19 +49,12 @@ class CRLEntryExtensionOID(object):
|
|||
INVALIDITY_DATE = ObjectIdentifier("2.5.29.24")
|
||||
|
||||
|
||||
CRLExtensionOID = utils.deprecated(
|
||||
CRLEntryExtensionOID,
|
||||
__name__,
|
||||
"CRLExtensionOID has been renamed to CRLEntryExtensionOID",
|
||||
utils.DeprecatedIn12
|
||||
)
|
||||
|
||||
|
||||
class NameOID(object):
|
||||
COMMON_NAME = ObjectIdentifier("2.5.4.3")
|
||||
COUNTRY_NAME = ObjectIdentifier("2.5.4.6")
|
||||
LOCALITY_NAME = ObjectIdentifier("2.5.4.7")
|
||||
STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8")
|
||||
STREET_ADDRESS = ObjectIdentifier("2.5.4.9")
|
||||
ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10")
|
||||
ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11")
|
||||
SERIAL_NUMBER = ObjectIdentifier("2.5.4.5")
|
||||
|
|
@ -114,8 +62,10 @@ class NameOID(object):
|
|||
GIVEN_NAME = ObjectIdentifier("2.5.4.42")
|
||||
TITLE = ObjectIdentifier("2.5.4.12")
|
||||
GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44")
|
||||
X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45")
|
||||
DN_QUALIFIER = ObjectIdentifier("2.5.4.46")
|
||||
PSEUDONYM = ObjectIdentifier("2.5.4.65")
|
||||
USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1")
|
||||
DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25")
|
||||
EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1")
|
||||
JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3")
|
||||
|
|
@ -124,15 +74,20 @@ class NameOID(object):
|
|||
"1.3.6.1.4.1.311.60.2.1.2"
|
||||
)
|
||||
BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15")
|
||||
POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16")
|
||||
POSTAL_CODE = ObjectIdentifier("2.5.4.17")
|
||||
|
||||
|
||||
class SignatureAlgorithmOID(object):
|
||||
RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4")
|
||||
RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5")
|
||||
# This is an alternate OID for RSA with SHA1 that is occasionally seen
|
||||
_RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29")
|
||||
RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14")
|
||||
RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11")
|
||||
RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12")
|
||||
RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13")
|
||||
RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10")
|
||||
ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1")
|
||||
ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1")
|
||||
ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2")
|
||||
|
|
@ -142,21 +97,23 @@ class SignatureAlgorithmOID(object):
|
|||
DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1")
|
||||
DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2")
|
||||
|
||||
|
||||
_SIG_OIDS_TO_HASH = {
|
||||
SignatureAlgorithmOID.RSA_WITH_MD5.dotted_string: hashes.MD5(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA1.dotted_string: hashes.SHA1(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA224.dotted_string: hashes.SHA224(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA256.dotted_string: hashes.SHA256(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA384.dotted_string: hashes.SHA384(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA512.dotted_string: hashes.SHA512(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA1.dotted_string: hashes.SHA1(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA224.dotted_string: hashes.SHA224(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA256.dotted_string: hashes.SHA256(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA384.dotted_string: hashes.SHA384(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA512.dotted_string: hashes.SHA512(),
|
||||
SignatureAlgorithmOID.DSA_WITH_SHA1.dotted_string: hashes.SHA1(),
|
||||
SignatureAlgorithmOID.DSA_WITH_SHA224.dotted_string: hashes.SHA224(),
|
||||
SignatureAlgorithmOID.DSA_WITH_SHA256.dotted_string: hashes.SHA256()
|
||||
SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(),
|
||||
SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(),
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(),
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(),
|
||||
SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(),
|
||||
SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(),
|
||||
SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256()
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -167,6 +124,7 @@ class ExtendedKeyUsageOID(object):
|
|||
EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4")
|
||||
TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8")
|
||||
OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9")
|
||||
ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0")
|
||||
|
||||
|
||||
class AuthorityInformationAccessOID(object):
|
||||
|
|
@ -179,11 +137,13 @@ class CertificatePoliciesOID(object):
|
|||
CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2")
|
||||
ANY_POLICY = ObjectIdentifier("2.5.29.32.0")
|
||||
|
||||
|
||||
_OID_NAMES = {
|
||||
NameOID.COMMON_NAME: "commonName",
|
||||
NameOID.COUNTRY_NAME: "countryName",
|
||||
NameOID.LOCALITY_NAME: "localityName",
|
||||
NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName",
|
||||
NameOID.STREET_ADDRESS: "streetAddress",
|
||||
NameOID.ORGANIZATION_NAME: "organizationName",
|
||||
NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName",
|
||||
NameOID.SERIAL_NUMBER: "serialNumber",
|
||||
|
|
@ -191,8 +151,10 @@ _OID_NAMES = {
|
|||
NameOID.GIVEN_NAME: "givenName",
|
||||
NameOID.TITLE: "title",
|
||||
NameOID.GENERATION_QUALIFIER: "generationQualifier",
|
||||
NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier",
|
||||
NameOID.DN_QUALIFIER: "dnQualifier",
|
||||
NameOID.PSEUDONYM: "pseudonym",
|
||||
NameOID.USER_ID: "userID",
|
||||
NameOID.DOMAIN_COMPONENT: "domainComponent",
|
||||
NameOID.EMAIL_ADDRESS: "emailAddress",
|
||||
NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName",
|
||||
|
|
@ -201,6 +163,8 @@ _OID_NAMES = {
|
|||
"jurisdictionStateOrProvinceName"
|
||||
),
|
||||
NameOID.BUSINESS_CATEGORY: "businessCategory",
|
||||
NameOID.POSTAL_ADDRESS: "postalAddress",
|
||||
NameOID.POSTAL_CODE: "postalCode",
|
||||
|
||||
SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption",
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption",
|
||||
|
|
@ -208,6 +172,7 @@ _OID_NAMES = {
|
|||
SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption",
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption",
|
||||
SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption",
|
||||
SignatureAlgorithmOID.RSASSA_PSS: "RSASSA-PSS",
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1",
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224",
|
||||
SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256",
|
||||
|
|
@ -228,6 +193,9 @@ _OID_NAMES = {
|
|||
ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName",
|
||||
ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName",
|
||||
ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints",
|
||||
ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: (
|
||||
"signedCertificateTimestampList"
|
||||
),
|
||||
CRLEntryExtensionOID.CRL_REASON: "cRLReason",
|
||||
CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate",
|
||||
CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer",
|
||||
|
|
@ -240,12 +208,18 @@ _OID_NAMES = {
|
|||
ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage",
|
||||
ExtensionOID.FRESHEST_CRL: "freshestCRL",
|
||||
ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy",
|
||||
ExtensionOID.ISSUING_DISTRIBUTION_POINT: (
|
||||
"issuingDistributionPoint"
|
||||
),
|
||||
ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess",
|
||||
ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess",
|
||||
ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck",
|
||||
ExtensionOID.CRL_NUMBER: "cRLNumber",
|
||||
ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator",
|
||||
ExtensionOID.TLS_FEATURE: "TLSFeature",
|
||||
AuthorityInformationAccessOID.OCSP: "OCSP",
|
||||
AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers",
|
||||
CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps",
|
||||
CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice",
|
||||
OCSPExtensionOID.NONCE: "OCSPNonce",
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue