0x1949 Team - FAZEMRX - MANAGER
Edit File: extensions.py
# 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. import abc import datetime import hashlib import ipaddress import typing from cryptography import utils from cryptography.hazmat._der import ( BIT_STRING, DERReader, OBJECT_IDENTIFIER, SEQUENCE, ) from cryptography.hazmat._types import _PUBLIC_KEY_TYPES 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 RelativeDistinguishedName from cryptography.x509.oid import ( CRLEntryExtensionOID, ExtensionOID, OCSPExtensionOID, ObjectIdentifier, ) def _key_identifier_from_public_key(public_key: _PUBLIC_KEY_TYPES) -> bytes: 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_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint, ) else: # This is a very slow way to do this. serialized = public_key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo, ) reader = DERReader(serialized) with reader.read_single_element(SEQUENCE) as public_key_info: algorithm = public_key_info.read_element(SEQUENCE) public_key_data = public_key_info.read_element(BIT_STRING) # Double-check the algorithm structure. with algorithm: algorithm.read_element(OBJECT_IDENTIFIER) if not algorithm.is_empty(): # Skip the optional parameters field. algorithm.read_any_element() # BIT STRING contents begin with the number of padding bytes added. It # must be zero for SubjectPublicKeyInfo structures. if public_key_data.read_byte() != 0: raise ValueError("Invalid public key encoding") data = public_key_data.data return hashlib.sha1(data).digest() def _make_sequence_methods(field_name): def len_method(self): return len(getattr(self, field_name)) def iter_method(self): return iter(getattr(self, field_name)) def getitem_method(self, idx): return getattr(self, field_name)[idx] return len_method, iter_method, getitem_method class DuplicateExtension(Exception): def __init__(self, msg: str, oid: ObjectIdentifier): super(DuplicateExtension, self).__init__(msg) self.oid = oid class ExtensionNotFound(Exception): def __init__(self, msg: str, oid: ObjectIdentifier): super(ExtensionNotFound, self).__init__(msg) self.oid = oid class ExtensionType(metaclass=abc.ABCMeta): @abc.abstractproperty def oid(self) -> ObjectIdentifier: """ Returns the oid associated with the given extension type. """ class Extensions(object): def __init__(self, extensions: typing.List["Extension"]): self._extensions = extensions def get_extension_for_oid(self, oid: ObjectIdentifier) -> "Extension": for ext in self: if ext.oid == oid: return ext raise ExtensionNotFound("No {} extension was found".format(oid), oid) def get_extension_for_class(self, extclass) -> "Extension": if extclass is UnrecognizedExtension: raise TypeError( "UnrecognizedExtension can't be used with " "get_extension_for_class because more than one instance of the" " class may be present." ) for ext in self: if isinstance(ext.value, extclass): return ext raise ExtensionNotFound( "No {} extension was found".format(extclass), extclass.oid ) __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions") def __repr__(self): return "<Extensions({})>".format(self._extensions) class CRLNumber(ExtensionType): oid = ExtensionOID.CRL_NUMBER def __init__(self, crl_number: int): if not isinstance(crl_number, int): raise TypeError("crl_number must be an integer") self._crl_number = crl_number def __eq__(self, other): if not isinstance(other, CRLNumber): 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 "<CRLNumber({})>".format(self.crl_number) crl_number = utils.read_only_property("_crl_number") class AuthorityKeyIdentifier(ExtensionType): oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER def __init__( self, key_identifier: typing.Optional[bytes], authority_cert_issuer: typing.Optional[typing.Iterable[GeneralName]], authority_cert_serial_number: typing.Optional[int], ): if (authority_cert_issuer is None) != ( authority_cert_serial_number is None ): raise ValueError( "authority_cert_issuer and authority_cert_serial_number " "must both be present or both None" ) 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, int ): raise TypeError("authority_cert_serial_number must be an integer") self._key_identifier = key_identifier self._authority_cert_issuer = authority_cert_issuer self._authority_cert_serial_number = authority_cert_serial_number @classmethod def from_issuer_public_key( cls, public_key: _PUBLIC_KEY_TYPES ) -> "AuthorityKeyIdentifier": digest = _key_identifier_from_public_key(public_key) return cls( key_identifier=digest, authority_cert_issuer=None, authority_cert_serial_number=None, ) @classmethod def from_issuer_subject_key_identifier( cls, ski: "SubjectKeyIdentifier" ) -> "AuthorityKeyIdentifier": return cls( key_identifier=ski.digest, authority_cert_issuer=None, authority_cert_serial_number=None, ) def __repr__(self): return ( "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, " "authority_cert_issuer={0.authority_cert_issuer}, " "authority_cert_serial_number={0.authority_cert_serial_number}" ")>".format(self) ) def __eq__(self, other): if not isinstance(other, AuthorityKeyIdentifier): return NotImplemented return ( self.key_identifier == other.key_identifier and self.authority_cert_issuer == other.authority_cert_issuer and self.authority_cert_serial_number == other.authority_cert_serial_number ) 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( "_authority_cert_serial_number" ) class SubjectKeyIdentifier(ExtensionType): oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER def __init__(self, digest: bytes): self._digest = digest @classmethod def from_public_key( cls, public_key: _PUBLIC_KEY_TYPES ) -> "SubjectKeyIdentifier": return cls(_key_identifier_from_public_key(public_key)) digest = utils.read_only_property("_digest") def __repr__(self): return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest) def __eq__(self, other): if not isinstance(other, SubjectKeyIdentifier): return NotImplemented return constant_time.bytes_eq(self.digest, other.digest) def __ne__(self, other): return not self == other def __hash__(self): return hash(self.digest) class AuthorityInformationAccess(ExtensionType): oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS def __init__(self, descriptions: typing.Iterable["AccessDescription"]): descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( "Every item in the descriptions list must be an " "AccessDescription" ) self._descriptions = descriptions __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") def __repr__(self): return "<AuthorityInformationAccess({})>".format(self._descriptions) def __eq__(self, other): if not isinstance(other, AuthorityInformationAccess): return NotImplemented return self._descriptions == other._descriptions def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._descriptions)) class SubjectInformationAccess(ExtensionType): oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS def __init__(self, descriptions: typing.Iterable["AccessDescription"]): descriptions = list(descriptions) if not all(isinstance(x, AccessDescription) for x in descriptions): raise TypeError( "Every item in the descriptions list must be an " "AccessDescription" ) self._descriptions = descriptions __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") def __repr__(self): return "<SubjectInformationAccess({})>".format(self._descriptions) def __eq__(self, other): if not isinstance(other, SubjectInformationAccess): return NotImplemented return self._descriptions == other._descriptions def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._descriptions)) class AccessDescription(object): def __init__( self, access_method: ObjectIdentifier, access_location: GeneralName ): if not isinstance(access_method, ObjectIdentifier): raise TypeError("access_method must be an ObjectIdentifier") if not isinstance(access_location, GeneralName): raise TypeError("access_location must be a GeneralName") self._access_method = access_method self._access_location = access_location def __repr__(self): return ( "<AccessDescription(access_method={0.access_method}, access_locati" "on={0.access_location})>".format(self) ) def __eq__(self, other): if not isinstance(other, AccessDescription): return NotImplemented return ( self.access_method == other.access_method and self.access_location == other.access_location ) 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") class BasicConstraints(ExtensionType): oid = ExtensionOID.BASIC_CONSTRAINTS def __init__(self, ca: bool, path_length: typing.Optional[int]): if not isinstance(ca, bool): raise TypeError("ca must be a boolean value") if path_length is not None and not ca: raise ValueError("path_length must be None when ca is False") if path_length is not None and ( not isinstance(path_length, int) or path_length < 0 ): raise TypeError( "path_length must be a non-negative integer or None" ) self._ca = ca self._path_length = path_length ca = utils.read_only_property("_ca") path_length = utils.read_only_property("_path_length") def __repr__(self): return ( "<BasicConstraints(ca={0.ca}, " "path_length={0.path_length})>" ).format(self) def __eq__(self, other): if not isinstance(other, BasicConstraints): return NotImplemented return self.ca == other.ca and self.path_length == other.path_length def __ne__(self, other): return not self == other def __hash__(self): return hash((self.ca, self.path_length)) class DeltaCRLIndicator(ExtensionType): oid = ExtensionOID.DELTA_CRL_INDICATOR def __init__(self, crl_number: int): if not isinstance(crl_number, int): 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) class CRLDistributionPoints(ExtensionType): oid = ExtensionOID.CRL_DISTRIBUTION_POINTS def __init__( self, distribution_points: typing.Iterable["DistributionPoint"] ): 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 __len__, __iter__, __getitem__ = _make_sequence_methods( "_distribution_points" ) def __repr__(self): return "<CRLDistributionPoints({})>".format(self._distribution_points) def __eq__(self, other): if not isinstance(other, CRLDistributionPoints): return NotImplemented return self._distribution_points == other._distribution_points def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._distribution_points)) class FreshestCRL(ExtensionType): oid = ExtensionOID.FRESHEST_CRL def __init__( self, distribution_points: typing.Iterable["DistributionPoint"] ): 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 __len__, __iter__, __getitem__ = _make_sequence_methods( "_distribution_points" ) def __repr__(self): return "<FreshestCRL({})>".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 __hash__(self): return hash(tuple(self._distribution_points)) class DistributionPoint(object): def __init__( self, full_name: typing.Optional[typing.Iterable[GeneralName]], relative_name: typing.Optional[RelativeDistinguishedName], reasons: typing.Optional[typing.FrozenSet["ReasonFlags"]], crl_issuer: typing.Optional[typing.Iterable[GeneralName]], ): if full_name and relative_name: raise ValueError( "You cannot provide both full_name and relative_name, at " "least one must be None." ) 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: if not isinstance(relative_name, RelativeDistinguishedName): raise TypeError( "relative_name must be a RelativeDistinguishedName" ) 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) ): raise TypeError("reasons must be None or frozenset of ReasonFlags") if reasons and ( ReasonFlags.unspecified in reasons or ReasonFlags.remove_from_crl in reasons ): raise ValueError( "unspecified and remove_from_crl are not valid reasons in a " "DistributionPoint" ) if reasons and not crl_issuer and not (full_name or relative_name): raise ValueError( "You must supply crl_issuer, full_name, or relative_name when " "reasons is not None" ) self._full_name = full_name self._relative_name = relative_name self._reasons = reasons self._crl_issuer = crl_issuer def __repr__(self): return ( "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela" "tive_name}, reasons={0.reasons}, " "crl_issuer={0.crl_issuer})>".format(self) ) def __eq__(self, other): if not isinstance(other, DistributionPoint): return NotImplemented return ( self.full_name == other.full_name and self.relative_name == other.relative_name and self.reasons == other.reasons and self.crl_issuer == other.crl_issuer ) def __ne__(self, other): return not self == other def __hash__(self): if self.full_name is not None: fn: typing.Optional[tuple] = tuple(self.full_name) else: fn = None if self.crl_issuer is not None: crl_issuer: typing.Optional[tuple] = 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") crl_issuer = utils.read_only_property("_crl_issuer") class ReasonFlags(utils.Enum): unspecified = "unspecified" key_compromise = "keyCompromise" ca_compromise = "cACompromise" affiliation_changed = "affiliationChanged" superseded = "superseded" cessation_of_operation = "cessationOfOperation" certificate_hold = "certificateHold" privilege_withdrawn = "privilegeWithdrawn" aa_compromise = "aACompromise" remove_from_crl = "removeFromCRL" class PolicyConstraints(ExtensionType): oid = ExtensionOID.POLICY_CONSTRAINTS def __init__( self, require_explicit_policy: typing.Optional[int], inhibit_policy_mapping: typing.Optional[int], ): if require_explicit_policy is not None and not isinstance( require_explicit_policy, int ): 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, int ): 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 ( "<PolicyConstraints(require_explicit_policy={0.require_explicit" "_policy}, inhibit_policy_mapping={0.inhibit_policy_" "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" ) class CertificatePolicies(ExtensionType): oid = ExtensionOID.CERTIFICATE_POLICIES def __init__(self, policies: typing.Iterable["PolicyInformation"]): policies = list(policies) if not all(isinstance(x, PolicyInformation) for x in policies): raise TypeError( "Every item in the policies list must be a " "PolicyInformation" ) self._policies = policies __len__, __iter__, __getitem__ = _make_sequence_methods("_policies") def __repr__(self): return "<CertificatePolicies({})>".format(self._policies) def __eq__(self, other): if not isinstance(other, CertificatePolicies): return NotImplemented return self._policies == other._policies def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._policies)) class PolicyInformation(object): def __init__( self, policy_identifier: ObjectIdentifier, policy_qualifiers: typing.Optional[ typing.Iterable[typing.Union[str, "UserNotice"]] ], ): if not isinstance(policy_identifier, ObjectIdentifier): raise TypeError("policy_identifier must be an ObjectIdentifier") self._policy_identifier = policy_identifier if policy_qualifiers: policy_qualifiers = list(policy_qualifiers) if not all( isinstance(x, (str, 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 def __repr__(self): return ( "<PolicyInformation(policy_identifier={0.policy_identifier}, polic" "y_qualifiers={0.policy_qualifiers})>".format(self) ) def __eq__(self, other): if not isinstance(other, PolicyInformation): return NotImplemented return ( self.policy_identifier == other.policy_identifier and self.policy_qualifiers == other.policy_qualifiers ) def __ne__(self, other): return not self == other def __hash__(self): if self.policy_qualifiers is not None: pq: typing.Optional[tuple] = 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") class UserNotice(object): def __init__( self, notice_reference: typing.Optional["NoticeReference"], explicit_text: typing.Optional[str], ): if notice_reference and not isinstance( notice_reference, NoticeReference ): raise TypeError( "notice_reference must be None or a NoticeReference" ) self._notice_reference = notice_reference self._explicit_text = explicit_text def __repr__(self): return ( "<UserNotice(notice_reference={0.notice_reference}, explicit_text=" "{0.explicit_text!r})>".format(self) ) def __eq__(self, other): if not isinstance(other, UserNotice): return NotImplemented return ( self.notice_reference == other.notice_reference and self.explicit_text == other.explicit_text ) 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") class NoticeReference(object): def __init__( self, organization: typing.Optional[str], notice_numbers: typing.Iterable[int], ): self._organization = organization 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") self._notice_numbers = notice_numbers def __repr__(self): return ( "<NoticeReference(organization={0.organization!r}, notice_numbers=" "{0.notice_numbers})>".format(self) ) def __eq__(self, other): if not isinstance(other, NoticeReference): return NotImplemented return ( self.organization == other.organization and self.notice_numbers == other.notice_numbers ) 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") class ExtendedKeyUsage(ExtensionType): oid = ExtensionOID.EXTENDED_KEY_USAGE def __init__(self, usages: typing.Iterable[ObjectIdentifier]): 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" ) self._usages = usages __len__, __iter__, __getitem__ = _make_sequence_methods("_usages") def __repr__(self): return "<ExtendedKeyUsage({})>".format(self._usages) def __eq__(self, other): if not isinstance(other, ExtendedKeyUsage): return NotImplemented return self._usages == other._usages def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._usages)) class OCSPNoCheck(ExtensionType): oid = ExtensionOID.OCSP_NO_CHECK def __eq__(self, other): if not isinstance(other, OCSPNoCheck): return NotImplemented return True def __ne__(self, other): return not self == other def __hash__(self): return hash(OCSPNoCheck) def __repr__(self): return "<OCSPNoCheck()>" class PrecertPoison(ExtensionType): oid = ExtensionOID.PRECERT_POISON def __eq__(self, other): if not isinstance(other, PrecertPoison): return NotImplemented return True def __ne__(self, other): return not self == other def __hash__(self): return hash(PrecertPoison) def __repr__(self): return "<PrecertPoison()>" class TLSFeature(ExtensionType): oid = ExtensionOID.TLS_FEATURE def __init__(self, features: typing.Iterable["TLSFeatureType"]): 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 __len__, __iter__, __getitem__ = _make_sequence_methods("_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 __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._features)) class TLSFeatureType(utils.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 = {x.value: x for x in TLSFeatureType} class InhibitAnyPolicy(ExtensionType): oid = ExtensionOID.INHIBIT_ANY_POLICY def __init__(self, skip_certs: int): if not isinstance(skip_certs, int): raise TypeError("skip_certs must be an integer") if skip_certs < 0: raise ValueError("skip_certs must be a non-negative integer") self._skip_certs = skip_certs def __repr__(self): return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self) def __eq__(self, other): if not isinstance(other, InhibitAnyPolicy): return NotImplemented return self.skip_certs == other.skip_certs def __ne__(self, other): return not self == other def __hash__(self): return hash(self.skip_certs) skip_certs = utils.read_only_property("_skip_certs") class KeyUsage(ExtensionType): oid = ExtensionOID.KEY_USAGE def __init__( self, digital_signature: bool, content_commitment: bool, key_encipherment: bool, data_encipherment: bool, key_agreement: bool, key_cert_sign: bool, crl_sign: bool, encipher_only: bool, decipher_only: bool, ): if not key_agreement and (encipher_only or decipher_only): raise ValueError( "encipher_only and decipher_only can only be true when " "key_agreement is true" ) self._digital_signature = digital_signature self._content_commitment = content_commitment self._key_encipherment = key_encipherment self._data_encipherment = data_encipherment self._key_agreement = key_agreement self._key_cert_sign = key_cert_sign self._crl_sign = crl_sign self._encipher_only = encipher_only self._decipher_only = decipher_only digital_signature = utils.read_only_property("_digital_signature") content_commitment = utils.read_only_property("_content_commitment") key_encipherment = utils.read_only_property("_key_encipherment") data_encipherment = utils.read_only_property("_data_encipherment") key_agreement = utils.read_only_property("_key_agreement") key_cert_sign = utils.read_only_property("_key_cert_sign") crl_sign = utils.read_only_property("_crl_sign") @property def encipher_only(self): if not self.key_agreement: raise ValueError( "encipher_only is undefined unless key_agreement is true" ) else: return self._encipher_only @property def decipher_only(self): if not self.key_agreement: raise ValueError( "decipher_only is undefined unless key_agreement is true" ) else: return self._decipher_only def __repr__(self): try: encipher_only = self.encipher_only decipher_only = self.decipher_only except ValueError: # Users found None confusing because even though encipher/decipher # have no meaning unless key_agreement is true, to construct an # instance of the class you still need to pass False. encipher_only = False decipher_only = False return ( "<KeyUsage(digital_signature={0.digital_signature}, " "content_commitment={0.content_commitment}, " "key_encipherment={0.key_encipherment}, " "data_encipherment={0.data_encipherment}, " "key_agreement={0.key_agreement}, " "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, " "encipher_only={1}, decipher_only={2})>" ).format(self, encipher_only, decipher_only) def __eq__(self, other): if not isinstance(other, KeyUsage): return NotImplemented return ( self.digital_signature == other.digital_signature and self.content_commitment == other.content_commitment and self.key_encipherment == other.key_encipherment and self.data_encipherment == other.data_encipherment and self.key_agreement == other.key_agreement and self.key_cert_sign == other.key_cert_sign and self.crl_sign == other.crl_sign and self._encipher_only == other._encipher_only and self._decipher_only == other._decipher_only ) 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, ) ) class NameConstraints(ExtensionType): oid = ExtensionOID.NAME_CONSTRAINTS def __init__( self, permitted_subtrees: typing.Optional[typing.Iterable[GeneralName]], excluded_subtrees: typing.Optional[typing.Iterable[GeneralName]], ): if permitted_subtrees is not None: permitted_subtrees = list(permitted_subtrees) if not all(isinstance(x, GeneralName) for x in permitted_subtrees): raise TypeError( "permitted_subtrees must be a list of GeneralName objects " "or None" ) 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): raise TypeError( "excluded_subtrees must be a list of GeneralName objects " "or None" ) self._validate_ip_name(excluded_subtrees) if permitted_subtrees is None and excluded_subtrees is None: raise ValueError( "At least one of permitted_subtrees and excluded_subtrees " "must not be None" ) self._permitted_subtrees = permitted_subtrees self._excluded_subtrees = excluded_subtrees def __eq__(self, other): if not isinstance(other, NameConstraints): return NotImplemented return ( self.excluded_subtrees == other.excluded_subtrees and self.permitted_subtrees == other.permitted_subtrees ) def __ne__(self, other): return not self == other def _validate_ip_name(self, tree): if any( isinstance(name, IPAddress) and not isinstance( name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network) ) for name in tree ): raise TypeError( "IPAddress name constraints must be an IPv4Network or" " IPv6Network object" ) def __repr__(self): return ( "<NameConstraints(permitted_subtrees={0.permitted_subtrees}, " "excluded_subtrees={0.excluded_subtrees})>".format(self) ) def __hash__(self): if self.permitted_subtrees is not None: ps: typing.Optional[tuple] = tuple(self.permitted_subtrees) else: ps = None if self.excluded_subtrees is not None: es: typing.Optional[tuple] = 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") class Extension(object): def __init__( self, oid: ObjectIdentifier, critical: bool, value: ExtensionType ): if not isinstance(oid, ObjectIdentifier): raise TypeError( "oid argument must be an ObjectIdentifier instance." ) if not isinstance(critical, bool): raise TypeError("critical must be a boolean value") self._oid = oid self._critical = critical self._value = value oid = utils.read_only_property("_oid") critical = utils.read_only_property("_critical") value = utils.read_only_property("_value") def __repr__(self): return ( "<Extension(oid={0.oid}, critical={0.critical}, " "value={0.value})>" ).format(self) def __eq__(self, other): if not isinstance(other, Extension): return NotImplemented return ( self.oid == other.oid and self.critical == other.critical and self.value == other.value ) 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: typing.Iterable[GeneralName]): 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 " "object conforming to the GeneralName interface" ) self._general_names = general_names __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type: typing.Type[GeneralName]): # Return the value of each GeneralName, except for OtherName instances # which we return directly because it has two important properties not # just one value. objs = (i for i in self if isinstance(i, type)) if type != OtherName: objs = (i.value for i in objs) return list(objs) def __repr__(self): return "<GeneralNames({})>".format(self._general_names) def __eq__(self, other): if not isinstance(other, GeneralNames): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(tuple(self._general_names)) class SubjectAlternativeName(ExtensionType): oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME def __init__(self, general_names: typing.Iterable[GeneralName]): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): return self._general_names.get_values_for_type(type) def __repr__(self): return "<SubjectAlternativeName({})>".format(self._general_names) def __eq__(self, other): if not isinstance(other, SubjectAlternativeName): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(self._general_names) class IssuerAlternativeName(ExtensionType): oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME def __init__(self, general_names: typing.Iterable[GeneralName]): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): return self._general_names.get_values_for_type(type) def __repr__(self): return "<IssuerAlternativeName({})>".format(self._general_names) def __eq__(self, other): if not isinstance(other, IssuerAlternativeName): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(self._general_names) class CertificateIssuer(ExtensionType): oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER def __init__(self, general_names: typing.Iterable[GeneralName]): self._general_names = GeneralNames(general_names) __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") def get_values_for_type(self, type): return self._general_names.get_values_for_type(type) def __repr__(self): return "<CertificateIssuer({})>".format(self._general_names) def __eq__(self, other): if not isinstance(other, CertificateIssuer): return NotImplemented return self._general_names == other._general_names def __ne__(self, other): return not self == other def __hash__(self): return hash(self._general_names) class CRLReason(ExtensionType): oid = CRLEntryExtensionOID.CRL_REASON def __init__(self, reason: ReasonFlags): if not isinstance(reason, ReasonFlags): raise TypeError("reason must be an element from ReasonFlags") self._reason = reason def __repr__(self): return "<CRLReason(reason={})>".format(self._reason) def __eq__(self, other): if not isinstance(other, CRLReason): return NotImplemented return self.reason == other.reason def __ne__(self, other): return not self == other def __hash__(self): return hash(self.reason) reason = utils.read_only_property("_reason") class InvalidityDate(ExtensionType): oid = CRLEntryExtensionOID.INVALIDITY_DATE def __init__(self, invalidity_date: datetime.datetime): if not isinstance(invalidity_date, datetime.datetime): raise TypeError("invalidity_date must be a datetime.datetime") self._invalidity_date = invalidity_date def __repr__(self): return "<InvalidityDate(invalidity_date={})>".format( self._invalidity_date ) def __eq__(self, other): if not isinstance(other, InvalidityDate): return NotImplemented return self.invalidity_date == other.invalidity_date def __ne__(self, other): return not self == other def __hash__(self): return hash(self.invalidity_date) invalidity_date = utils.read_only_property("_invalidity_date") class PrecertificateSignedCertificateTimestamps(ExtensionType): oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS def __init__( self, signed_certificate_timestamps: typing.Iterable[ SignedCertificateTimestamp ], ): 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 __len__, __iter__, __getitem__ = _make_sequence_methods( "_signed_certificate_timestamps" ) def __repr__(self): return "<PrecertificateSignedCertificateTimestamps({})>".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 class SignedCertificateTimestamps(ExtensionType): oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS def __init__( self, signed_certificate_timestamps: typing.Iterable[ SignedCertificateTimestamp ], ): 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 __len__, __iter__, __getitem__ = _make_sequence_methods( "_signed_certificate_timestamps" ) def __repr__(self): return "<SignedCertificateTimestamps({})>".format(list(self)) def __hash__(self): return hash(tuple(self._signed_certificate_timestamps)) def __eq__(self, other): if not isinstance(other, SignedCertificateTimestamps): return NotImplemented return ( self._signed_certificate_timestamps == other._signed_certificate_timestamps ) def __ne__(self, other): return not self == other class OCSPNonce(ExtensionType): oid = OCSPExtensionOID.NONCE def __init__(self, nonce: bytes): 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") class IssuingDistributionPoint(ExtensionType): oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT def __init__( self, full_name, relative_name, only_contains_user_certs, only_contains_ca_certs, only_some_reasons, indirect_crl, only_contains_attribute_certs, ): if only_some_reasons and ( not isinstance(only_some_reasons, frozenset) or not all(isinstance(x, ReasonFlags) for x in only_some_reasons) ): raise TypeError( "only_some_reasons must be None or frozenset of ReasonFlags" ) if only_some_reasons and ( ReasonFlags.unspecified in only_some_reasons or ReasonFlags.remove_from_crl in only_some_reasons ): raise ValueError( "unspecified and remove_from_crl are not valid reasons in an " "IssuingDistributionPoint" ) if not ( isinstance(only_contains_user_certs, bool) and isinstance(only_contains_ca_certs, bool) and isinstance(indirect_crl, bool) and isinstance(only_contains_attribute_certs, bool) ): raise TypeError( "only_contains_user_certs, only_contains_ca_certs, " "indirect_crl and only_contains_attribute_certs " "must all be boolean." ) crl_constraints = [ only_contains_user_certs, only_contains_ca_certs, indirect_crl, only_contains_attribute_certs, ] if len([x for x in crl_constraints if x]) > 1: raise ValueError( "Only one of the following can be set to True: " "only_contains_user_certs, only_contains_ca_certs, " "indirect_crl, only_contains_attribute_certs" ) if not any( [ only_contains_user_certs, only_contains_ca_certs, indirect_crl, only_contains_attribute_certs, full_name, relative_name, only_some_reasons, ] ): raise ValueError( "Cannot create empty extension: " "if only_contains_user_certs, only_contains_ca_certs, " "indirect_crl, and only_contains_attribute_certs are all False" ", then either full_name, relative_name, or only_some_reasons " "must have a value." ) self._only_contains_user_certs = only_contains_user_certs self._only_contains_ca_certs = only_contains_ca_certs self._indirect_crl = indirect_crl self._only_contains_attribute_certs = only_contains_attribute_certs self._only_some_reasons = only_some_reasons self._full_name = full_name self._relative_name = relative_name def __repr__(self): return ( "<IssuingDistributionPoint(full_name={0.full_name}, " "relative_name={0.relative_name}, " "only_contains_user_certs={0.only_contains_user_certs}, " "only_contains_ca_certs={0.only_contains_ca_certs}, " "only_some_reasons={0.only_some_reasons}, " "indirect_crl={0.indirect_crl}, " "only_contains_attribute_certs=" "{0.only_contains_attribute_certs})>".format(self) ) def __eq__(self, other): if not isinstance(other, IssuingDistributionPoint): return NotImplemented return ( self.full_name == other.full_name and self.relative_name == other.relative_name and self.only_contains_user_certs == other.only_contains_user_certs and self.only_contains_ca_certs == other.only_contains_ca_certs and self.only_some_reasons == other.only_some_reasons and self.indirect_crl == other.indirect_crl and self.only_contains_attribute_certs == other.only_contains_attribute_certs ) def __ne__(self, other): return not self == other def __hash__(self): return hash( ( self.full_name, self.relative_name, self.only_contains_user_certs, self.only_contains_ca_certs, self.only_some_reasons, self.indirect_crl, self.only_contains_attribute_certs, ) ) full_name = utils.read_only_property("_full_name") relative_name = utils.read_only_property("_relative_name") only_contains_user_certs = utils.read_only_property( "_only_contains_user_certs" ) only_contains_ca_certs = utils.read_only_property( "_only_contains_ca_certs" ) only_some_reasons = utils.read_only_property("_only_some_reasons") indirect_crl = utils.read_only_property("_indirect_crl") only_contains_attribute_certs = utils.read_only_property( "_only_contains_attribute_certs" ) class UnrecognizedExtension(ExtensionType): def __init__(self, oid: ObjectIdentifier, value: bytes): if not isinstance(oid, ObjectIdentifier): raise TypeError("oid must be an ObjectIdentifier") self._oid = oid self._value = value oid = utils.read_only_property("_oid") value = utils.read_only_property("_value") def __repr__(self): return ( "<UnrecognizedExtension(oid={0.oid}, " "value={0.value!r})>".format(self) ) def __eq__(self, other): if not isinstance(other, UnrecognizedExtension): return NotImplemented return self.oid == other.oid and self.value == other.value def __ne__(self, other): return not self == other def __hash__(self): return hash((self.oid, self.value))