Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
extensions.py2534 linesDownload Raw Back to x509
1# This file is dual licensed under the terms of the Apache License, Version2# 2.0, and the BSD License. See the LICENSE file in the root of this repository3# for complete details.4 5from __future__ import annotations6 7import abc8import datetime9import hashlib10import ipaddress11import typing12from collections.abc import Iterable, Iterator13 14from cryptography import utils15from cryptography.hazmat.bindings._rust import asn116from cryptography.hazmat.bindings._rust import x509 as rust_x50917from cryptography.hazmat.primitives import constant_time, serialization18from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey19from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey20from cryptography.hazmat.primitives.asymmetric.types import (21    CertificateIssuerPublicKeyTypes,22    CertificatePublicKeyTypes,23)24from cryptography.x509.certificate_transparency import (25    SignedCertificateTimestamp,26)27from cryptography.x509.general_name import (28    DirectoryName,29    DNSName,30    GeneralName,31    IPAddress,32    OtherName,33    RegisteredID,34    RFC822Name,35    UniformResourceIdentifier,36    _IPAddressTypes,37)38from cryptography.x509.name import Name, RelativeDistinguishedName39from cryptography.x509.oid import (40    CRLEntryExtensionOID,41    ExtensionOID,42    ObjectIdentifier,43    OCSPExtensionOID,44)45 46ExtensionTypeVar = typing.TypeVar(47    "ExtensionTypeVar", bound="ExtensionType", covariant=True48)49 50 51def _key_identifier_from_public_key(52    public_key: CertificatePublicKeyTypes,53) -> bytes:54    if isinstance(public_key, RSAPublicKey):55        data = public_key.public_bytes(56            serialization.Encoding.DER,57            serialization.PublicFormat.PKCS1,58        )59    elif isinstance(public_key, EllipticCurvePublicKey):60        data = public_key.public_bytes(61            serialization.Encoding.X962,62            serialization.PublicFormat.UncompressedPoint,63        )64    else:65        # This is a very slow way to do this.66        serialized = public_key.public_bytes(67            serialization.Encoding.DER,68            serialization.PublicFormat.SubjectPublicKeyInfo,69        )70        data = asn1.parse_spki_for_data(serialized)71 72    return hashlib.sha1(data).digest()73 74 75def _make_sequence_methods(field_name: str):76    def len_method(self) -> int:77        return len(getattr(self, field_name))78 79    def iter_method(self):80        return iter(getattr(self, field_name))81 82    def getitem_method(self, idx):83        return getattr(self, field_name)[idx]84 85    return len_method, iter_method, getitem_method86 87 88class DuplicateExtension(Exception):89    def __init__(self, msg: str, oid: ObjectIdentifier) -> None:90        super().__init__(msg)91        self.oid = oid92 93 94class ExtensionNotFound(Exception):95    def __init__(self, msg: str, oid: ObjectIdentifier) -> None:96        super().__init__(msg)97        self.oid = oid98 99 100class ExtensionType(metaclass=abc.ABCMeta):101    oid: typing.ClassVar[ObjectIdentifier]102 103    def public_bytes(self) -> bytes:104        """105        Serializes the extension type to DER.106        """107        raise NotImplementedError(108            f"public_bytes is not implemented for extension type {self!r}"109        )110 111 112class Extensions:113    def __init__(self, extensions: Iterable[Extension[ExtensionType]]) -> None:114        self._extensions = list(extensions)115 116    def get_extension_for_oid(117        self, oid: ObjectIdentifier118    ) -> Extension[ExtensionType]:119        for ext in self:120            if ext.oid == oid:121                return ext122 123        raise ExtensionNotFound(f"No {oid} extension was found", oid)124 125    def get_extension_for_class(126        self, extclass: type[ExtensionTypeVar]127    ) -> Extension[ExtensionTypeVar]:128        if extclass is UnrecognizedExtension:129            raise TypeError(130                "UnrecognizedExtension can't be used with "131                "get_extension_for_class because more than one instance of the"132                " class may be present."133            )134 135        for ext in self:136            if isinstance(ext.value, extclass):137                return ext138 139        raise ExtensionNotFound(140            f"No {extclass} extension was found", extclass.oid141        )142 143    __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions")144 145    def __repr__(self) -> str:146        return f"<Extensions({self._extensions})>"147 148 149class CRLNumber(ExtensionType):150    oid = ExtensionOID.CRL_NUMBER151 152    def __init__(self, crl_number: int) -> None:153        if not isinstance(crl_number, int):154            raise TypeError("crl_number must be an integer")155 156        self._crl_number = crl_number157 158    def __eq__(self, other: object) -> bool:159        if not isinstance(other, CRLNumber):160            return NotImplemented161 162        return self.crl_number == other.crl_number163 164    def __hash__(self) -> int:165        return hash(self.crl_number)166 167    def __repr__(self) -> str:168        return f"<CRLNumber({self.crl_number})>"169 170    @property171    def crl_number(self) -> int:172        return self._crl_number173 174    def public_bytes(self) -> bytes:175        return rust_x509.encode_extension_value(self)176 177 178class AuthorityKeyIdentifier(ExtensionType):179    oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER180 181    def __init__(182        self,183        key_identifier: bytes | None,184        authority_cert_issuer: Iterable[GeneralName] | None,185        authority_cert_serial_number: int | None,186    ) -> None:187        if (authority_cert_issuer is None) != (188            authority_cert_serial_number is None189        ):190            raise ValueError(191                "authority_cert_issuer and authority_cert_serial_number "192                "must both be present or both None"193            )194 195        if authority_cert_issuer is not None:196            authority_cert_issuer = list(authority_cert_issuer)197            if not all(198                isinstance(x, GeneralName) for x in authority_cert_issuer199            ):200                raise TypeError(201                    "authority_cert_issuer must be a list of GeneralName "202                    "objects"203                )204 205        if authority_cert_serial_number is not None and not isinstance(206            authority_cert_serial_number, int207        ):208            raise TypeError("authority_cert_serial_number must be an integer")209 210        self._key_identifier = key_identifier211        self._authority_cert_issuer = authority_cert_issuer212        self._authority_cert_serial_number = authority_cert_serial_number213 214    # This takes a subset of CertificatePublicKeyTypes because an issuer215    # cannot have an X25519/X448 key. This introduces some unfortunate216    # asymmetry that requires typing users to explicitly217    # narrow their type, but we should make this accurate and not just218    # convenient.219    @classmethod220    def from_issuer_public_key(221        cls, public_key: CertificateIssuerPublicKeyTypes222    ) -> AuthorityKeyIdentifier:223        digest = _key_identifier_from_public_key(public_key)224        return cls(225            key_identifier=digest,226            authority_cert_issuer=None,227            authority_cert_serial_number=None,228        )229 230    @classmethod231    def from_issuer_subject_key_identifier(232        cls, ski: SubjectKeyIdentifier233    ) -> AuthorityKeyIdentifier:234        return cls(235            key_identifier=ski.digest,236            authority_cert_issuer=None,237            authority_cert_serial_number=None,238        )239 240    def __repr__(self) -> str:241        return (242            f"<AuthorityKeyIdentifier(key_identifier={self.key_identifier!r}, "243            f"authority_cert_issuer={self.authority_cert_issuer}, "244            f"authority_cert_serial_number={self.authority_cert_serial_number}"245            ")>"246        )247 248    def __eq__(self, other: object) -> bool:249        if not isinstance(other, AuthorityKeyIdentifier):250            return NotImplemented251 252        return (253            self.key_identifier == other.key_identifier254            and self.authority_cert_issuer == other.authority_cert_issuer255            and self.authority_cert_serial_number256            == other.authority_cert_serial_number257        )258 259    def __hash__(self) -> int:260        if self.authority_cert_issuer is None:261            aci = None262        else:263            aci = tuple(self.authority_cert_issuer)264        return hash(265            (self.key_identifier, aci, self.authority_cert_serial_number)266        )267 268    @property269    def key_identifier(self) -> bytes | None:270        return self._key_identifier271 272    @property273    def authority_cert_issuer(274        self,275    ) -> list[GeneralName] | None:276        return self._authority_cert_issuer277 278    @property279    def authority_cert_serial_number(self) -> int | None:280        return self._authority_cert_serial_number281 282    def public_bytes(self) -> bytes:283        return rust_x509.encode_extension_value(self)284 285 286class SubjectKeyIdentifier(ExtensionType):287    oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER288 289    def __init__(self, digest: bytes) -> None:290        self._digest = digest291 292    @classmethod293    def from_public_key(294        cls, public_key: CertificatePublicKeyTypes295    ) -> SubjectKeyIdentifier:296        return cls(_key_identifier_from_public_key(public_key))297 298    @property299    def digest(self) -> bytes:300        return self._digest301 302    @property303    def key_identifier(self) -> bytes:304        return self._digest305 306    def __repr__(self) -> str:307        return f"<SubjectKeyIdentifier(digest={self.digest!r})>"308 309    def __eq__(self, other: object) -> bool:310        if not isinstance(other, SubjectKeyIdentifier):311            return NotImplemented312 313        return constant_time.bytes_eq(self.digest, other.digest)314 315    def __hash__(self) -> int:316        return hash(self.digest)317 318    def public_bytes(self) -> bytes:319        return rust_x509.encode_extension_value(self)320 321 322class AuthorityInformationAccess(ExtensionType):323    oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS324 325    def __init__(self, descriptions: Iterable[AccessDescription]) -> None:326        descriptions = list(descriptions)327        if not all(isinstance(x, AccessDescription) for x in descriptions):328            raise TypeError(329                "Every item in the descriptions list must be an "330                "AccessDescription"331            )332 333        self._descriptions = descriptions334 335    __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")336 337    def __repr__(self) -> str:338        return f"<AuthorityInformationAccess({self._descriptions})>"339 340    def __eq__(self, other: object) -> bool:341        if not isinstance(other, AuthorityInformationAccess):342            return NotImplemented343 344        return self._descriptions == other._descriptions345 346    def __hash__(self) -> int:347        return hash(tuple(self._descriptions))348 349    def public_bytes(self) -> bytes:350        return rust_x509.encode_extension_value(self)351 352 353class SubjectInformationAccess(ExtensionType):354    oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS355 356    def __init__(self, descriptions: Iterable[AccessDescription]) -> None:357        descriptions = list(descriptions)358        if not all(isinstance(x, AccessDescription) for x in descriptions):359            raise TypeError(360                "Every item in the descriptions list must be an "361                "AccessDescription"362            )363 364        self._descriptions = descriptions365 366    __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")367 368    def __repr__(self) -> str:369        return f"<SubjectInformationAccess({self._descriptions})>"370 371    def __eq__(self, other: object) -> bool:372        if not isinstance(other, SubjectInformationAccess):373            return NotImplemented374 375        return self._descriptions == other._descriptions376 377    def __hash__(self) -> int:378        return hash(tuple(self._descriptions))379 380    def public_bytes(self) -> bytes:381        return rust_x509.encode_extension_value(self)382 383 384class AccessDescription:385    def __init__(386        self, access_method: ObjectIdentifier, access_location: GeneralName387    ) -> None:388        if not isinstance(access_method, ObjectIdentifier):389            raise TypeError("access_method must be an ObjectIdentifier")390 391        if not isinstance(access_location, GeneralName):392            raise TypeError("access_location must be a GeneralName")393 394        self._access_method = access_method395        self._access_location = access_location396 397    def __repr__(self) -> str:398        return (399            f"<AccessDescription(access_method={self.access_method}, "400            f"access_location={self.access_location})>"401        )402 403    def __eq__(self, other: object) -> bool:404        if not isinstance(other, AccessDescription):405            return NotImplemented406 407        return (408            self.access_method == other.access_method409            and self.access_location == other.access_location410        )411 412    def __hash__(self) -> int:413        return hash((self.access_method, self.access_location))414 415    @property416    def access_method(self) -> ObjectIdentifier:417        return self._access_method418 419    @property420    def access_location(self) -> GeneralName:421        return self._access_location422 423 424class BasicConstraints(ExtensionType):425    oid = ExtensionOID.BASIC_CONSTRAINTS426 427    def __init__(self, ca: bool, path_length: int | None) -> None:428        if not isinstance(ca, bool):429            raise TypeError("ca must be a boolean value")430 431        if path_length is not None and not ca:432            raise ValueError("path_length must be None when ca is False")433 434        if path_length is not None and (435            not isinstance(path_length, int) or path_length < 0436        ):437            raise TypeError(438                "path_length must be a non-negative integer or None"439            )440 441        self._ca = ca442        self._path_length = path_length443 444    @property445    def ca(self) -> bool:446        return self._ca447 448    @property449    def path_length(self) -> int | None:450        return self._path_length451 452    def __repr__(self) -> str:453        return (454            f"<BasicConstraints(ca={self.ca}, path_length={self.path_length})>"455        )456 457    def __eq__(self, other: object) -> bool:458        if not isinstance(other, BasicConstraints):459            return NotImplemented460 461        return self.ca == other.ca and self.path_length == other.path_length462 463    def __hash__(self) -> int:464        return hash((self.ca, self.path_length))465 466    def public_bytes(self) -> bytes:467        return rust_x509.encode_extension_value(self)468 469 470class DeltaCRLIndicator(ExtensionType):471    oid = ExtensionOID.DELTA_CRL_INDICATOR472 473    def __init__(self, crl_number: int) -> None:474        if not isinstance(crl_number, int):475            raise TypeError("crl_number must be an integer")476 477        self._crl_number = crl_number478 479    @property480    def crl_number(self) -> int:481        return self._crl_number482 483    def __eq__(self, other: object) -> bool:484        if not isinstance(other, DeltaCRLIndicator):485            return NotImplemented486 487        return self.crl_number == other.crl_number488 489    def __hash__(self) -> int:490        return hash(self.crl_number)491 492    def __repr__(self) -> str:493        return f"<DeltaCRLIndicator(crl_number={self.crl_number})>"494 495    def public_bytes(self) -> bytes:496        return rust_x509.encode_extension_value(self)497 498 499class CRLDistributionPoints(ExtensionType):500    oid = ExtensionOID.CRL_DISTRIBUTION_POINTS501 502    def __init__(503        self, distribution_points: Iterable[DistributionPoint]504    ) -> None:505        distribution_points = list(distribution_points)506        if not all(507            isinstance(x, DistributionPoint) for x in distribution_points508        ):509            raise TypeError(510                "distribution_points must be a list of DistributionPoint "511                "objects"512            )513 514        self._distribution_points = distribution_points515 516    __len__, __iter__, __getitem__ = _make_sequence_methods(517        "_distribution_points"518    )519 520    def __repr__(self) -> str:521        return f"<CRLDistributionPoints({self._distribution_points})>"522 523    def __eq__(self, other: object) -> bool:524        if not isinstance(other, CRLDistributionPoints):525            return NotImplemented526 527        return self._distribution_points == other._distribution_points528 529    def __hash__(self) -> int:530        return hash(tuple(self._distribution_points))531 532    def public_bytes(self) -> bytes:533        return rust_x509.encode_extension_value(self)534 535 536class FreshestCRL(ExtensionType):537    oid = ExtensionOID.FRESHEST_CRL538 539    def __init__(540        self, distribution_points: Iterable[DistributionPoint]541    ) -> None:542        distribution_points = list(distribution_points)543        if not all(544            isinstance(x, DistributionPoint) for x in distribution_points545        ):546            raise TypeError(547                "distribution_points must be a list of DistributionPoint "548                "objects"549            )550 551        self._distribution_points = distribution_points552 553    __len__, __iter__, __getitem__ = _make_sequence_methods(554        "_distribution_points"555    )556 557    def __repr__(self) -> str:558        return f"<FreshestCRL({self._distribution_points})>"559 560    def __eq__(self, other: object) -> bool:561        if not isinstance(other, FreshestCRL):562            return NotImplemented563 564        return self._distribution_points == other._distribution_points565 566    def __hash__(self) -> int:567        return hash(tuple(self._distribution_points))568 569    def public_bytes(self) -> bytes:570        return rust_x509.encode_extension_value(self)571 572 573class DistributionPoint:574    def __init__(575        self,576        full_name: Iterable[GeneralName] | None,577        relative_name: RelativeDistinguishedName | None,578        reasons: frozenset[ReasonFlags] | None,579        crl_issuer: Iterable[GeneralName] | None,580    ) -> None:581        if full_name and relative_name:582            raise ValueError(583                "You cannot provide both full_name and relative_name, at "584                "least one must be None."585            )586        if not full_name and not relative_name and not crl_issuer:587            raise ValueError(588                "Either full_name, relative_name or crl_issuer must be "589                "provided."590            )591 592        if full_name is not None:593            full_name = list(full_name)594            if not all(isinstance(x, GeneralName) for x in full_name):595                raise TypeError(596                    "full_name must be a list of GeneralName objects"597                )598 599        if relative_name:600            if not isinstance(relative_name, RelativeDistinguishedName):601                raise TypeError(602                    "relative_name must be a RelativeDistinguishedName"603                )604 605        if crl_issuer is not None:606            crl_issuer = list(crl_issuer)607            if not all(isinstance(x, GeneralName) for x in crl_issuer):608                raise TypeError(609                    "crl_issuer must be None or a list of general names"610                )611 612        if reasons and (613            not isinstance(reasons, frozenset)614            or not all(isinstance(x, ReasonFlags) for x in reasons)615        ):616            raise TypeError("reasons must be None or frozenset of ReasonFlags")617 618        if reasons and (619            ReasonFlags.unspecified in reasons620            or ReasonFlags.remove_from_crl in reasons621        ):622            raise ValueError(623                "unspecified and remove_from_crl are not valid reasons in a "624                "DistributionPoint"625            )626 627        self._full_name = full_name628        self._relative_name = relative_name629        self._reasons = reasons630        self._crl_issuer = crl_issuer631 632    def __repr__(self) -> str:633        return (634            "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"635            "tive_name}, reasons={0.reasons}, "636            "crl_issuer={0.crl_issuer})>".format(self)637        )638 639    def __eq__(self, other: object) -> bool:640        if not isinstance(other, DistributionPoint):641            return NotImplemented642 643        return (644            self.full_name == other.full_name645            and self.relative_name == other.relative_name646            and self.reasons == other.reasons647            and self.crl_issuer == other.crl_issuer648        )649 650    def __hash__(self) -> int:651        if self.full_name is not None:652            fn: tuple[GeneralName, ...] | None = tuple(self.full_name)653        else:654            fn = None655 656        if self.crl_issuer is not None:657            crl_issuer: tuple[GeneralName, ...] | None = tuple(self.crl_issuer)658        else:659            crl_issuer = None660 661        return hash((fn, self.relative_name, self.reasons, crl_issuer))662 663    @property664    def full_name(self) -> list[GeneralName] | None:665        return self._full_name666 667    @property668    def relative_name(self) -> RelativeDistinguishedName | None:669        return self._relative_name670 671    @property672    def reasons(self) -> frozenset[ReasonFlags] | None:673        return self._reasons674 675    @property676    def crl_issuer(self) -> list[GeneralName] | None:677        return self._crl_issuer678 679 680class ReasonFlags(utils.Enum):681    unspecified = "unspecified"682    key_compromise = "keyCompromise"683    ca_compromise = "cACompromise"684    affiliation_changed = "affiliationChanged"685    superseded = "superseded"686    cessation_of_operation = "cessationOfOperation"687    certificate_hold = "certificateHold"688    privilege_withdrawn = "privilegeWithdrawn"689    aa_compromise = "aACompromise"690    remove_from_crl = "removeFromCRL"691 692 693# These are distribution point bit string mappings. Not to be confused with694# CRLReason reason flags bit string mappings.695# ReasonFlags ::= BIT STRING {696#      unused                  (0),697#      keyCompromise           (1),698#      cACompromise            (2),699#      affiliationChanged      (3),700#      superseded              (4),701#      cessationOfOperation    (5),702#      certificateHold         (6),703#      privilegeWithdrawn      (7),704#      aACompromise            (8) }705_REASON_BIT_MAPPING = {706    1: ReasonFlags.key_compromise,707    2: ReasonFlags.ca_compromise,708    3: ReasonFlags.affiliation_changed,709    4: ReasonFlags.superseded,710    5: ReasonFlags.cessation_of_operation,711    6: ReasonFlags.certificate_hold,712    7: ReasonFlags.privilege_withdrawn,713    8: ReasonFlags.aa_compromise,714}715 716_CRLREASONFLAGS = {717    ReasonFlags.key_compromise: 1,718    ReasonFlags.ca_compromise: 2,719    ReasonFlags.affiliation_changed: 3,720    ReasonFlags.superseded: 4,721    ReasonFlags.cessation_of_operation: 5,722    ReasonFlags.certificate_hold: 6,723    ReasonFlags.privilege_withdrawn: 7,724    ReasonFlags.aa_compromise: 8,725}726 727#    CRLReason ::= ENUMERATED {728#        unspecified             (0),729#        keyCompromise           (1),730#        cACompromise            (2),731#        affiliationChanged      (3),732#        superseded              (4),733#        cessationOfOperation    (5),734#        certificateHold         (6),735#             -- value 7 is not used736#        removeFromCRL           (8),737#        privilegeWithdrawn      (9),738#        aACompromise           (10) }739_CRL_ENTRY_REASON_ENUM_TO_CODE = {740    ReasonFlags.unspecified: 0,741    ReasonFlags.key_compromise: 1,742    ReasonFlags.ca_compromise: 2,743    ReasonFlags.affiliation_changed: 3,744    ReasonFlags.superseded: 4,745    ReasonFlags.cessation_of_operation: 5,746    ReasonFlags.certificate_hold: 6,747    ReasonFlags.remove_from_crl: 8,748    ReasonFlags.privilege_withdrawn: 9,749    ReasonFlags.aa_compromise: 10,750}751 752 753class PolicyConstraints(ExtensionType):754    oid = ExtensionOID.POLICY_CONSTRAINTS755 756    def __init__(757        self,758        require_explicit_policy: int | None,759        inhibit_policy_mapping: int | None,760    ) -> None:761        if require_explicit_policy is not None and not isinstance(762            require_explicit_policy, int763        ):764            raise TypeError(765                "require_explicit_policy must be a non-negative integer or "766                "None"767            )768 769        if inhibit_policy_mapping is not None and not isinstance(770            inhibit_policy_mapping, int771        ):772            raise TypeError(773                "inhibit_policy_mapping must be a non-negative integer or None"774            )775 776        if inhibit_policy_mapping is None and require_explicit_policy is None:777            raise ValueError(778                "At least one of require_explicit_policy and "779                "inhibit_policy_mapping must not be None"780            )781 782        self._require_explicit_policy = require_explicit_policy783        self._inhibit_policy_mapping = inhibit_policy_mapping784 785    def __repr__(self) -> str:786        return (787            "<PolicyConstraints(require_explicit_policy={0.require_explicit"788            "_policy}, inhibit_policy_mapping={0.inhibit_policy_"789            "mapping})>".format(self)790        )791 792    def __eq__(self, other: object) -> bool:793        if not isinstance(other, PolicyConstraints):794            return NotImplemented795 796        return (797            self.require_explicit_policy == other.require_explicit_policy798            and self.inhibit_policy_mapping == other.inhibit_policy_mapping799        )800 801    def __hash__(self) -> int:802        return hash(803            (self.require_explicit_policy, self.inhibit_policy_mapping)804        )805 806    @property807    def require_explicit_policy(self) -> int | None:808        return self._require_explicit_policy809 810    @property811    def inhibit_policy_mapping(self) -> int | None:812        return self._inhibit_policy_mapping813 814    def public_bytes(self) -> bytes:815        return rust_x509.encode_extension_value(self)816 817 818class CertificatePolicies(ExtensionType):819    oid = ExtensionOID.CERTIFICATE_POLICIES820 821    def __init__(self, policies: Iterable[PolicyInformation]) -> None:822        policies = list(policies)823        if not all(isinstance(x, PolicyInformation) for x in policies):824            raise TypeError(825                "Every item in the policies list must be a PolicyInformation"826            )827 828        self._policies = policies829 830    __len__, __iter__, __getitem__ = _make_sequence_methods("_policies")831 832    def __repr__(self) -> str:833        return f"<CertificatePolicies({self._policies})>"834 835    def __eq__(self, other: object) -> bool:836        if not isinstance(other, CertificatePolicies):837            return NotImplemented838 839        return self._policies == other._policies840 841    def __hash__(self) -> int:842        return hash(tuple(self._policies))843 844    def public_bytes(self) -> bytes:845        return rust_x509.encode_extension_value(self)846 847 848class PolicyInformation:849    def __init__(850        self,851        policy_identifier: ObjectIdentifier,852        policy_qualifiers: Iterable[str | UserNotice] | None,853    ) -> None:854        if not isinstance(policy_identifier, ObjectIdentifier):855            raise TypeError("policy_identifier must be an ObjectIdentifier")856 857        self._policy_identifier = policy_identifier858 859        if policy_qualifiers is not None:860            policy_qualifiers = list(policy_qualifiers)861            if not all(862                isinstance(x, (str, UserNotice)) for x in policy_qualifiers863            ):864                raise TypeError(865                    "policy_qualifiers must be a list of strings and/or "866                    "UserNotice objects or None"867                )868 869        self._policy_qualifiers = policy_qualifiers870 871    def __repr__(self) -> str:872        return (873            f"<PolicyInformation(policy_identifier={self.policy_identifier}, "874            f"policy_qualifiers={self.policy_qualifiers})>"875        )876 877    def __eq__(self, other: object) -> bool:878        if not isinstance(other, PolicyInformation):879            return NotImplemented880 881        return (882            self.policy_identifier == other.policy_identifier883            and self.policy_qualifiers == other.policy_qualifiers884        )885 886    def __hash__(self) -> int:887        if self.policy_qualifiers is not None:888            pq = tuple(self.policy_qualifiers)889        else:890            pq = None891 892        return hash((self.policy_identifier, pq))893 894    @property895    def policy_identifier(self) -> ObjectIdentifier:896        return self._policy_identifier897 898    @property899    def policy_qualifiers(900        self,901    ) -> list[str | UserNotice] | None:902        return self._policy_qualifiers903 904 905class UserNotice:906    def __init__(907        self,908        notice_reference: NoticeReference | None,909        explicit_text: str | None,910    ) -> None:911        if notice_reference and not isinstance(912            notice_reference, NoticeReference913        ):914            raise TypeError(915                "notice_reference must be None or a NoticeReference"916            )917 918        self._notice_reference = notice_reference919        self._explicit_text = explicit_text920 921    def __repr__(self) -> str:922        return (923            f"<UserNotice(notice_reference={self.notice_reference}, "924            f"explicit_text={self.explicit_text!r})>"925        )926 927    def __eq__(self, other: object) -> bool:928        if not isinstance(other, UserNotice):929            return NotImplemented930 931        return (932            self.notice_reference == other.notice_reference933            and self.explicit_text == other.explicit_text934        )935 936    def __hash__(self) -> int:937        return hash((self.notice_reference, self.explicit_text))938 939    @property940    def notice_reference(self) -> NoticeReference | None:941        return self._notice_reference942 943    @property944    def explicit_text(self) -> str | None:945        return self._explicit_text946 947 948class NoticeReference:949    def __init__(950        self,951        organization: str | None,952        notice_numbers: Iterable[int],953    ) -> None:954        self._organization = organization955        notice_numbers = list(notice_numbers)956        if not all(isinstance(x, int) for x in notice_numbers):957            raise TypeError("notice_numbers must be a list of integers")958 959        self._notice_numbers = notice_numbers960 961    def __repr__(self) -> str:962        return (963            f"<NoticeReference(organization={self.organization!r}, "964            f"notice_numbers={self.notice_numbers})>"965        )966 967    def __eq__(self, other: object) -> bool:968        if not isinstance(other, NoticeReference):969            return NotImplemented970 971        return (972            self.organization == other.organization973            and self.notice_numbers == other.notice_numbers974        )975 976    def __hash__(self) -> int:977        return hash((self.organization, tuple(self.notice_numbers)))978 979    @property980    def organization(self) -> str | None:981        return self._organization982 983    @property984    def notice_numbers(self) -> list[int]:985        return self._notice_numbers986 987 988class ExtendedKeyUsage(ExtensionType):989    oid = ExtensionOID.EXTENDED_KEY_USAGE990 991    def __init__(self, usages: Iterable[ObjectIdentifier]) -> None:992        usages = list(usages)993        if not all(isinstance(x, ObjectIdentifier) for x in usages):994            raise TypeError(995                "Every item in the usages list must be an ObjectIdentifier"996            )997 998        self._usages = usages999 1000    __len__, __iter__, __getitem__ = _make_sequence_methods("_usages")1001 1002    def __repr__(self) -> str:1003        return f"<ExtendedKeyUsage({self._usages})>"1004 1005    def __eq__(self, other: object) -> bool:1006        if not isinstance(other, ExtendedKeyUsage):1007            return NotImplemented1008 1009        return self._usages == other._usages1010 1011    def __hash__(self) -> int:1012        return hash(tuple(self._usages))1013 1014    def public_bytes(self) -> bytes:1015        return rust_x509.encode_extension_value(self)1016 1017 1018class OCSPNoCheck(ExtensionType):1019    oid = ExtensionOID.OCSP_NO_CHECK1020 1021    def __eq__(self, other: object) -> bool:1022        if not isinstance(other, OCSPNoCheck):1023            return NotImplemented1024 1025        return True1026 1027    def __hash__(self) -> int:1028        return hash(OCSPNoCheck)1029 1030    def __repr__(self) -> str:1031        return "<OCSPNoCheck()>"1032 1033    def public_bytes(self) -> bytes:1034        return rust_x509.encode_extension_value(self)1035 1036 1037class PrecertPoison(ExtensionType):1038    oid = ExtensionOID.PRECERT_POISON1039 1040    def __eq__(self, other: object) -> bool:1041        if not isinstance(other, PrecertPoison):1042            return NotImplemented1043 1044        return True1045 1046    def __hash__(self) -> int:1047        return hash(PrecertPoison)1048 1049    def __repr__(self) -> str:1050        return "<PrecertPoison()>"1051 1052    def public_bytes(self) -> bytes:1053        return rust_x509.encode_extension_value(self)1054 1055 1056class TLSFeature(ExtensionType):1057    oid = ExtensionOID.TLS_FEATURE1058 1059    def __init__(self, features: Iterable[TLSFeatureType]) -> None:1060        features = list(features)1061        if (1062            not all(isinstance(x, TLSFeatureType) for x in features)1063            or len(features) == 01064        ):1065            raise TypeError(1066                "features must be a list of elements from the TLSFeatureType "1067                "enum"1068            )1069 1070        self._features = features1071 1072    __len__, __iter__, __getitem__ = _make_sequence_methods("_features")1073 1074    def __repr__(self) -> str:1075        return f"<TLSFeature(features={self._features})>"1076 1077    def __eq__(self, other: object) -> bool:1078        if not isinstance(other, TLSFeature):1079            return NotImplemented1080 1081        return self._features == other._features1082 1083    def __hash__(self) -> int:1084        return hash(tuple(self._features))1085 1086    def public_bytes(self) -> bytes:1087        return rust_x509.encode_extension_value(self)1088 1089 1090class TLSFeatureType(utils.Enum):1091    # status_request is defined in RFC 6066 and is used for what is commonly1092    # called OCSP Must-Staple when present in the TLS Feature extension in an1093    # X.509 certificate.1094    status_request = 51095    # status_request_v2 is defined in RFC 6961 and allows multiple OCSP1096    # responses to be provided. It is not currently in use by clients or1097    # servers.1098    status_request_v2 = 171099 1100 1101_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType}1102 1103 1104class InhibitAnyPolicy(ExtensionType):1105    oid = ExtensionOID.INHIBIT_ANY_POLICY1106 1107    def __init__(self, skip_certs: int) -> None:1108        if not isinstance(skip_certs, int):1109            raise TypeError("skip_certs must be an integer")1110 1111        if skip_certs < 0:1112            raise ValueError("skip_certs must be a non-negative integer")1113 1114        self._skip_certs = skip_certs1115 1116    def __repr__(self) -> str:1117        return f"<InhibitAnyPolicy(skip_certs={self.skip_certs})>"1118 1119    def __eq__(self, other: object) -> bool:1120        if not isinstance(other, InhibitAnyPolicy):1121            return NotImplemented1122 1123        return self.skip_certs == other.skip_certs1124 1125    def __hash__(self) -> int:1126        return hash(self.skip_certs)1127 1128    @property1129    def skip_certs(self) -> int:1130        return self._skip_certs1131 1132    def public_bytes(self) -> bytes:1133        return rust_x509.encode_extension_value(self)1134 1135 1136class KeyUsage(ExtensionType):1137    oid = ExtensionOID.KEY_USAGE1138 1139    def __init__(1140        self,1141        digital_signature: bool,1142        content_commitment: bool,1143        key_encipherment: bool,1144        data_encipherment: bool,1145        key_agreement: bool,1146        key_cert_sign: bool,1147        crl_sign: bool,1148        encipher_only: bool,1149        decipher_only: bool,1150    ) -> None:1151        if not key_agreement and (encipher_only or decipher_only):1152            raise ValueError(1153                "encipher_only and decipher_only can only be true when "1154                "key_agreement is true"1155            )1156 1157        self._digital_signature = digital_signature1158        self._content_commitment = content_commitment1159        self._key_encipherment = key_encipherment1160        self._data_encipherment = data_encipherment1161        self._key_agreement = key_agreement1162        self._key_cert_sign = key_cert_sign1163        self._crl_sign = crl_sign1164        self._encipher_only = encipher_only1165        self._decipher_only = decipher_only1166 1167    @property1168    def digital_signature(self) -> bool:1169        return self._digital_signature1170 1171    @property1172    def content_commitment(self) -> bool:1173        return self._content_commitment1174 1175    @property1176    def key_encipherment(self) -> bool:1177        return self._key_encipherment1178 1179    @property1180    def data_encipherment(self) -> bool:1181        return self._data_encipherment1182 1183    @property1184    def key_agreement(self) -> bool:1185        return self._key_agreement1186 1187    @property1188    def key_cert_sign(self) -> bool:1189        return self._key_cert_sign1190 1191    @property1192    def crl_sign(self) -> bool:1193        return self._crl_sign1194 1195    @property1196    def encipher_only(self) -> bool:1197        if not self.key_agreement:1198            raise ValueError(1199                "encipher_only is undefined unless key_agreement is true"1200            )

Showing the first 1,200 of 2534 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai