1# This file is dual licensed under the terms of the Apache License, Version 
    2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 
    3# for complete details. 
    4 
    5from __future__ import annotations 
    6 
    7import abc 
    8import typing 
    9 
    10from cryptography import utils 
    11from cryptography.exceptions import UnsupportedAlgorithm, _Reasons 
    12from cryptography.hazmat._oid import ObjectIdentifier 
    13from cryptography.hazmat.bindings._rust import openssl as rust_openssl 
    14from cryptography.hazmat.primitives import _serialization, hashes 
    15from cryptography.hazmat.primitives.asymmetric import utils as asym_utils 
    16 
    17 
    18class EllipticCurveOID: 
    19    SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") 
    20    SECP224R1 = ObjectIdentifier("1.3.132.0.33") 
    21    SECP256K1 = ObjectIdentifier("1.3.132.0.10") 
    22    SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") 
    23    SECP384R1 = ObjectIdentifier("1.3.132.0.34") 
    24    SECP521R1 = ObjectIdentifier("1.3.132.0.35") 
    25    BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") 
    26    BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") 
    27    BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") 
    28    SECT163K1 = ObjectIdentifier("1.3.132.0.1") 
    29    SECT163R2 = ObjectIdentifier("1.3.132.0.15") 
    30    SECT233K1 = ObjectIdentifier("1.3.132.0.26") 
    31    SECT233R1 = ObjectIdentifier("1.3.132.0.27") 
    32    SECT283K1 = ObjectIdentifier("1.3.132.0.16") 
    33    SECT283R1 = ObjectIdentifier("1.3.132.0.17") 
    34    SECT409K1 = ObjectIdentifier("1.3.132.0.36") 
    35    SECT409R1 = ObjectIdentifier("1.3.132.0.37") 
    36    SECT571K1 = ObjectIdentifier("1.3.132.0.38") 
    37    SECT571R1 = ObjectIdentifier("1.3.132.0.39") 
    38 
    39 
    40class EllipticCurve(metaclass=abc.ABCMeta): 
    41    @property 
    42    @abc.abstractmethod 
    43    def name(self) -> str: 
    44        """ 
    45        The name of the curve. e.g. secp256r1. 
    46        """ 
    47 
    48    @property 
    49    @abc.abstractmethod 
    50    def key_size(self) -> int: 
    51        """ 
    52        Bit size of a secret scalar for the curve. 
    53        """ 
    54 
    55    @property 
    56    @abc.abstractmethod 
    57    def group_order(self) -> int: 
    58        """ 
    59        The order of the curve's group. 
    60        """ 
    61 
    62 
    63class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): 
    64    @property 
    65    @abc.abstractmethod 
    66    def algorithm( 
    67        self, 
    68    ) -> asym_utils.Prehashed | hashes.HashAlgorithm: 
    69        """ 
    70        The digest algorithm used with this signature. 
    71        """ 
    72 
    73 
    74class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): 
    75    @abc.abstractmethod 
    76    def exchange( 
    77        self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey 
    78    ) -> bytes: 
    79        """ 
    80        Performs a key exchange operation using the provided algorithm with the 
    81        provided peer's public key. 
    82        """ 
    83 
    84    @abc.abstractmethod 
    85    def public_key(self) -> EllipticCurvePublicKey: 
    86        """ 
    87        The EllipticCurvePublicKey for this private key. 
    88        """ 
    89 
    90    @property 
    91    @abc.abstractmethod 
    92    def curve(self) -> EllipticCurve: 
    93        """ 
    94        The EllipticCurve that this key is on. 
    95        """ 
    96 
    97    @property 
    98    @abc.abstractmethod 
    99    def key_size(self) -> int: 
    100        """ 
    101        Bit size of a secret scalar for the curve. 
    102        """ 
    103 
    104    @abc.abstractmethod 
    105    def sign( 
    106        self, 
    107        data: utils.Buffer, 
    108        signature_algorithm: EllipticCurveSignatureAlgorithm, 
    109    ) -> bytes: 
    110        """ 
    111        Signs the data 
    112        """ 
    113 
    114    @abc.abstractmethod 
    115    def private_numbers(self) -> EllipticCurvePrivateNumbers: 
    116        """ 
    117        Returns an EllipticCurvePrivateNumbers. 
    118        """ 
    119 
    120    @abc.abstractmethod 
    121    def private_bytes( 
    122        self, 
    123        encoding: _serialization.Encoding, 
    124        format: _serialization.PrivateFormat, 
    125        encryption_algorithm: _serialization.KeySerializationEncryption, 
    126    ) -> bytes: 
    127        """ 
    128        Returns the key serialized as bytes. 
    129        """ 
    130 
    131    @abc.abstractmethod 
    132    def __copy__(self) -> EllipticCurvePrivateKey: 
    133        """ 
    134        Returns a copy. 
    135        """ 
    136 
    137 
    138EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey 
    139EllipticCurvePrivateKey.register(rust_openssl.ec.ECPrivateKey) 
    140 
    141 
    142class EllipticCurvePublicKey(metaclass=abc.ABCMeta): 
    143    @property 
    144    @abc.abstractmethod 
    145    def curve(self) -> EllipticCurve: 
    146        """ 
    147        The EllipticCurve that this key is on. 
    148        """ 
    149 
    150    @property 
    151    @abc.abstractmethod 
    152    def key_size(self) -> int: 
    153        """ 
    154        Bit size of a secret scalar for the curve. 
    155        """ 
    156 
    157    @abc.abstractmethod 
    158    def public_numbers(self) -> EllipticCurvePublicNumbers: 
    159        """ 
    160        Returns an EllipticCurvePublicNumbers. 
    161        """ 
    162 
    163    @abc.abstractmethod 
    164    def public_bytes( 
    165        self, 
    166        encoding: _serialization.Encoding, 
    167        format: _serialization.PublicFormat, 
    168    ) -> bytes: 
    169        """ 
    170        Returns the key serialized as bytes. 
    171        """ 
    172 
    173    @abc.abstractmethod 
    174    def verify( 
    175        self, 
    176        signature: utils.Buffer, 
    177        data: utils.Buffer, 
    178        signature_algorithm: EllipticCurveSignatureAlgorithm, 
    179    ) -> None: 
    180        """ 
    181        Verifies the signature of the data. 
    182        """ 
    183 
    184    @classmethod 
    185    def from_encoded_point( 
    186        cls, curve: EllipticCurve, data: bytes 
    187    ) -> EllipticCurvePublicKey: 
    188        utils._check_bytes("data", data) 
    189 
    190        if len(data) == 0: 
    191            raise ValueError("data must not be an empty byte string") 
    192 
    193        if data[0] not in [0x02, 0x03, 0x04]: 
    194            raise ValueError("Unsupported elliptic curve point type") 
    195 
    196        return rust_openssl.ec.from_public_bytes(curve, data) 
    197 
    198    @abc.abstractmethod 
    199    def __eq__(self, other: object) -> bool: 
    200        """ 
    201        Checks equality. 
    202        """ 
    203 
    204    @abc.abstractmethod 
    205    def __copy__(self) -> EllipticCurvePublicKey: 
    206        """ 
    207        Returns a copy. 
    208        """ 
    209 
    210 
    211EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey 
    212EllipticCurvePublicKey.register(rust_openssl.ec.ECPublicKey) 
    213 
    214EllipticCurvePrivateNumbers = rust_openssl.ec.EllipticCurvePrivateNumbers 
    215EllipticCurvePublicNumbers = rust_openssl.ec.EllipticCurvePublicNumbers 
    216 
    217 
    218class SECT571R1(EllipticCurve): 
    219    name = "sect571r1" 
    220    key_size = 570 
    221    group_order = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47  # noqa: E501 
    222 
    223 
    224class SECT409R1(EllipticCurve): 
    225    name = "sect409r1" 
    226    key_size = 409 
    227    group_order = 0x10000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173  # noqa: E501 
    228 
    229 
    230class SECT283R1(EllipticCurve): 
    231    name = "sect283r1" 
    232    key_size = 283 
    233    group_order = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307  # noqa: E501 
    234 
    235 
    236class SECT233R1(EllipticCurve): 
    237    name = "sect233r1" 
    238    key_size = 233 
    239    group_order = 0x1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7 
    240 
    241 
    242class SECT163R2(EllipticCurve): 
    243    name = "sect163r2" 
    244    key_size = 163 
    245    group_order = 0x40000000000000000000292FE77E70C12A4234C33 
    246 
    247 
    248class SECT571K1(EllipticCurve): 
    249    name = "sect571k1" 
    250    key_size = 571 
    251    group_order = 0x20000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001  # noqa: E501 
    252 
    253 
    254class SECT409K1(EllipticCurve): 
    255    name = "sect409k1" 
    256    key_size = 409 
    257    group_order = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF  # noqa: E501 
    258 
    259 
    260class SECT283K1(EllipticCurve): 
    261    name = "sect283k1" 
    262    key_size = 283 
    263    group_order = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61  # noqa: E501 
    264 
    265 
    266class SECT233K1(EllipticCurve): 
    267    name = "sect233k1" 
    268    key_size = 233 
    269    group_order = 0x8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF 
    270 
    271 
    272class SECT163K1(EllipticCurve): 
    273    name = "sect163k1" 
    274    key_size = 163 
    275    group_order = 0x4000000000000000000020108A2E0CC0D99F8A5EF 
    276 
    277 
    278class SECP521R1(EllipticCurve): 
    279    name = "secp521r1" 
    280    key_size = 521 
    281    group_order = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409  # noqa: E501 
    282 
    283 
    284class SECP384R1(EllipticCurve): 
    285    name = "secp384r1" 
    286    key_size = 384 
    287    group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973  # noqa: E501 
    288 
    289 
    290class SECP256R1(EllipticCurve): 
    291    name = "secp256r1" 
    292    key_size = 256 
    293    group_order = ( 
    294        0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 
    295    ) 
    296 
    297 
    298class SECP256K1(EllipticCurve): 
    299    name = "secp256k1" 
    300    key_size = 256 
    301    group_order = ( 
    302        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 
    303    ) 
    304 
    305 
    306class SECP224R1(EllipticCurve): 
    307    name = "secp224r1" 
    308    key_size = 224 
    309    group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D 
    310 
    311 
    312class SECP192R1(EllipticCurve): 
    313    name = "secp192r1" 
    314    key_size = 192 
    315    group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831 
    316 
    317 
    318class BrainpoolP256R1(EllipticCurve): 
    319    name = "brainpoolP256r1" 
    320    key_size = 256 
    321    group_order = ( 
    322        0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7 
    323    ) 
    324 
    325 
    326class BrainpoolP384R1(EllipticCurve): 
    327    name = "brainpoolP384r1" 
    328    key_size = 384 
    329    group_order = 0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565  # noqa: E501 
    330 
    331 
    332class BrainpoolP512R1(EllipticCurve): 
    333    name = "brainpoolP512r1" 
    334    key_size = 512 
    335    group_order = 0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069  # noqa: E501 
    336 
    337 
    338_CURVE_TYPES: dict[str, EllipticCurve] = { 
    339    "prime192v1": SECP192R1(), 
    340    "prime256v1": SECP256R1(), 
    341    "secp192r1": SECP192R1(), 
    342    "secp224r1": SECP224R1(), 
    343    "secp256r1": SECP256R1(), 
    344    "secp384r1": SECP384R1(), 
    345    "secp521r1": SECP521R1(), 
    346    "secp256k1": SECP256K1(), 
    347    "sect163k1": SECT163K1(), 
    348    "sect233k1": SECT233K1(), 
    349    "sect283k1": SECT283K1(), 
    350    "sect409k1": SECT409K1(), 
    351    "sect571k1": SECT571K1(), 
    352    "sect163r2": SECT163R2(), 
    353    "sect233r1": SECT233R1(), 
    354    "sect283r1": SECT283R1(), 
    355    "sect409r1": SECT409R1(), 
    356    "sect571r1": SECT571R1(), 
    357    "brainpoolP256r1": BrainpoolP256R1(), 
    358    "brainpoolP384r1": BrainpoolP384R1(), 
    359    "brainpoolP512r1": BrainpoolP512R1(), 
    360} 
    361 
    362 
    363class ECDSA(EllipticCurveSignatureAlgorithm): 
    364    def __init__( 
    365        self, 
    366        algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, 
    367        deterministic_signing: bool = False, 
    368    ): 
    369        from cryptography.hazmat.backends.openssl.backend import backend 
    370 
    371        if ( 
    372            deterministic_signing 
    373            and not backend.ecdsa_deterministic_supported() 
    374        ): 
    375            raise UnsupportedAlgorithm( 
    376                "ECDSA with deterministic signature (RFC 6979) is not " 
    377                "supported by this version of OpenSSL.", 
    378                _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, 
    379            ) 
    380        self._algorithm = algorithm 
    381        self._deterministic_signing = deterministic_signing 
    382 
    383    @property 
    384    def algorithm( 
    385        self, 
    386    ) -> asym_utils.Prehashed | hashes.HashAlgorithm: 
    387        return self._algorithm 
    388 
    389    @property 
    390    def deterministic_signing( 
    391        self, 
    392    ) -> bool: 
    393        return self._deterministic_signing 
    394 
    395 
    396generate_private_key = rust_openssl.ec.generate_private_key 
    397 
    398 
    399def derive_private_key( 
    400    private_value: int, 
    401    curve: EllipticCurve, 
    402    backend: typing.Any = None, 
    403) -> EllipticCurvePrivateKey: 
    404    if not isinstance(private_value, int): 
    405        raise TypeError("private_value must be an integer type.") 
    406 
    407    if private_value <= 0: 
    408        raise ValueError("private_value must be a positive integer.") 
    409 
    410    return rust_openssl.ec.derive_private_key(private_value, curve) 
    411 
    412 
    413class ECDH: 
    414    pass 
    415 
    416 
    417_OID_TO_CURVE = { 
    418    EllipticCurveOID.SECP192R1: SECP192R1, 
    419    EllipticCurveOID.SECP224R1: SECP224R1, 
    420    EllipticCurveOID.SECP256K1: SECP256K1, 
    421    EllipticCurveOID.SECP256R1: SECP256R1, 
    422    EllipticCurveOID.SECP384R1: SECP384R1, 
    423    EllipticCurveOID.SECP521R1: SECP521R1, 
    424    EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, 
    425    EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, 
    426    EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, 
    427    EllipticCurveOID.SECT163K1: SECT163K1, 
    428    EllipticCurveOID.SECT163R2: SECT163R2, 
    429    EllipticCurveOID.SECT233K1: SECT233K1, 
    430    EllipticCurveOID.SECT233R1: SECT233R1, 
    431    EllipticCurveOID.SECT283K1: SECT283K1, 
    432    EllipticCurveOID.SECT283R1: SECT283R1, 
    433    EllipticCurveOID.SECT409K1: SECT409K1, 
    434    EllipticCurveOID.SECT409R1: SECT409R1, 
    435    EllipticCurveOID.SECT571K1: SECT571K1, 
    436    EllipticCurveOID.SECT571R1: SECT571R1, 
    437} 
    438 
    439 
    440def get_curve_for_oid(oid: ObjectIdentifier) -> type[EllipticCurve]: 
    441    try: 
    442        return _OID_TO_CURVE[oid] 
    443    except KeyError: 
    444        raise LookupError( 
    445            "The provided object identifier has no matching elliptic " 
    446            "curve class" 
    447        )