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 absolute_import, division, print_function 6 7import abc 8import warnings 9 10import six 11 12from cryptography import utils 13from cryptography.hazmat._oid import ObjectIdentifier 14from cryptography.hazmat.backends import _get_backend 15 16 17class EllipticCurveOID(object): 18 SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") 19 SECP224R1 = ObjectIdentifier("1.3.132.0.33") 20 SECP256K1 = ObjectIdentifier("1.3.132.0.10") 21 SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") 22 SECP384R1 = ObjectIdentifier("1.3.132.0.34") 23 SECP521R1 = ObjectIdentifier("1.3.132.0.35") 24 BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") 25 BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") 26 BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") 27 SECT163K1 = ObjectIdentifier("1.3.132.0.1") 28 SECT163R2 = ObjectIdentifier("1.3.132.0.15") 29 SECT233K1 = ObjectIdentifier("1.3.132.0.26") 30 SECT233R1 = ObjectIdentifier("1.3.132.0.27") 31 SECT283K1 = ObjectIdentifier("1.3.132.0.16") 32 SECT283R1 = ObjectIdentifier("1.3.132.0.17") 33 SECT409K1 = ObjectIdentifier("1.3.132.0.36") 34 SECT409R1 = ObjectIdentifier("1.3.132.0.37") 35 SECT571K1 = ObjectIdentifier("1.3.132.0.38") 36 SECT571R1 = ObjectIdentifier("1.3.132.0.39") 37 38 39@six.add_metaclass(abc.ABCMeta) 40class EllipticCurve(object): 41 @abc.abstractproperty 42 def name(self): 43 """ 44 The name of the curve. e.g. secp256r1. 45 """ 46 47 @abc.abstractproperty 48 def key_size(self): 49 """ 50 Bit size of a secret scalar for the curve. 51 """ 52 53 54@six.add_metaclass(abc.ABCMeta) 55class EllipticCurveSignatureAlgorithm(object): 56 @abc.abstractproperty 57 def algorithm(self): 58 """ 59 The digest algorithm used with this signature. 60 """ 61 62 63@six.add_metaclass(abc.ABCMeta) 64class EllipticCurvePrivateKey(object): 65 @abc.abstractmethod 66 def signer(self, signature_algorithm): 67 """ 68 Returns an AsymmetricSignatureContext used for signing data. 69 """ 70 71 @abc.abstractmethod 72 def exchange(self, algorithm, peer_public_key): 73 """ 74 Performs a key exchange operation using the provided algorithm with the 75 provided peer's public key. 76 """ 77 78 @abc.abstractmethod 79 def public_key(self): 80 """ 81 The EllipticCurvePublicKey for this private key. 82 """ 83 84 @abc.abstractproperty 85 def curve(self): 86 """ 87 The EllipticCurve that this key is on. 88 """ 89 90 @abc.abstractproperty 91 def key_size(self): 92 """ 93 Bit size of a secret scalar for the curve. 94 """ 95 96 @abc.abstractmethod 97 def sign(self, data, signature_algorithm): 98 """ 99 Signs the data 100 """ 101 102 103@six.add_metaclass(abc.ABCMeta) 104class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey): 105 @abc.abstractmethod 106 def private_numbers(self): 107 """ 108 Returns an EllipticCurvePrivateNumbers. 109 """ 110 111 @abc.abstractmethod 112 def private_bytes(self, encoding, format, encryption_algorithm): 113 """ 114 Returns the key serialized as bytes. 115 """ 116 117 118@six.add_metaclass(abc.ABCMeta) 119class EllipticCurvePublicKey(object): 120 @abc.abstractmethod 121 def verifier(self, signature, signature_algorithm): 122 """ 123 Returns an AsymmetricVerificationContext used for signing data. 124 """ 125 126 @abc.abstractproperty 127 def curve(self): 128 """ 129 The EllipticCurve that this key is on. 130 """ 131 132 @abc.abstractproperty 133 def key_size(self): 134 """ 135 Bit size of a secret scalar for the curve. 136 """ 137 138 @abc.abstractmethod 139 def public_numbers(self): 140 """ 141 Returns an EllipticCurvePublicNumbers. 142 """ 143 144 @abc.abstractmethod 145 def public_bytes(self, encoding, format): 146 """ 147 Returns the key serialized as bytes. 148 """ 149 150 @abc.abstractmethod 151 def verify(self, signature, data, signature_algorithm): 152 """ 153 Verifies the signature of the data. 154 """ 155 156 @classmethod 157 def from_encoded_point(cls, curve, data): 158 utils._check_bytes("data", data) 159 160 if not isinstance(curve, EllipticCurve): 161 raise TypeError("curve must be an EllipticCurve instance") 162 163 if len(data) == 0: 164 raise ValueError("data must not be an empty byte string") 165 166 if six.indexbytes(data, 0) not in [0x02, 0x03, 0x04]: 167 raise ValueError("Unsupported elliptic curve point type") 168 169 from cryptography.hazmat.backends.openssl.backend import backend 170 171 return backend.load_elliptic_curve_public_bytes(curve, data) 172 173 174EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey 175 176 177@utils.register_interface(EllipticCurve) 178class SECT571R1(object): 179 name = "sect571r1" 180 key_size = 570 181 182 183@utils.register_interface(EllipticCurve) 184class SECT409R1(object): 185 name = "sect409r1" 186 key_size = 409 187 188 189@utils.register_interface(EllipticCurve) 190class SECT283R1(object): 191 name = "sect283r1" 192 key_size = 283 193 194 195@utils.register_interface(EllipticCurve) 196class SECT233R1(object): 197 name = "sect233r1" 198 key_size = 233 199 200 201@utils.register_interface(EllipticCurve) 202class SECT163R2(object): 203 name = "sect163r2" 204 key_size = 163 205 206 207@utils.register_interface(EllipticCurve) 208class SECT571K1(object): 209 name = "sect571k1" 210 key_size = 571 211 212 213@utils.register_interface(EllipticCurve) 214class SECT409K1(object): 215 name = "sect409k1" 216 key_size = 409 217 218 219@utils.register_interface(EllipticCurve) 220class SECT283K1(object): 221 name = "sect283k1" 222 key_size = 283 223 224 225@utils.register_interface(EllipticCurve) 226class SECT233K1(object): 227 name = "sect233k1" 228 key_size = 233 229 230 231@utils.register_interface(EllipticCurve) 232class SECT163K1(object): 233 name = "sect163k1" 234 key_size = 163 235 236 237@utils.register_interface(EllipticCurve) 238class SECP521R1(object): 239 name = "secp521r1" 240 key_size = 521 241 242 243@utils.register_interface(EllipticCurve) 244class SECP384R1(object): 245 name = "secp384r1" 246 key_size = 384 247 248 249@utils.register_interface(EllipticCurve) 250class SECP256R1(object): 251 name = "secp256r1" 252 key_size = 256 253 254 255@utils.register_interface(EllipticCurve) 256class SECP256K1(object): 257 name = "secp256k1" 258 key_size = 256 259 260 261@utils.register_interface(EllipticCurve) 262class SECP224R1(object): 263 name = "secp224r1" 264 key_size = 224 265 266 267@utils.register_interface(EllipticCurve) 268class SECP192R1(object): 269 name = "secp192r1" 270 key_size = 192 271 272 273@utils.register_interface(EllipticCurve) 274class BrainpoolP256R1(object): 275 name = "brainpoolP256r1" 276 key_size = 256 277 278 279@utils.register_interface(EllipticCurve) 280class BrainpoolP384R1(object): 281 name = "brainpoolP384r1" 282 key_size = 384 283 284 285@utils.register_interface(EllipticCurve) 286class BrainpoolP512R1(object): 287 name = "brainpoolP512r1" 288 key_size = 512 289 290 291_CURVE_TYPES = { 292 "prime192v1": SECP192R1, 293 "prime256v1": SECP256R1, 294 "secp192r1": SECP192R1, 295 "secp224r1": SECP224R1, 296 "secp256r1": SECP256R1, 297 "secp384r1": SECP384R1, 298 "secp521r1": SECP521R1, 299 "secp256k1": SECP256K1, 300 "sect163k1": SECT163K1, 301 "sect233k1": SECT233K1, 302 "sect283k1": SECT283K1, 303 "sect409k1": SECT409K1, 304 "sect571k1": SECT571K1, 305 "sect163r2": SECT163R2, 306 "sect233r1": SECT233R1, 307 "sect283r1": SECT283R1, 308 "sect409r1": SECT409R1, 309 "sect571r1": SECT571R1, 310 "brainpoolP256r1": BrainpoolP256R1, 311 "brainpoolP384r1": BrainpoolP384R1, 312 "brainpoolP512r1": BrainpoolP512R1, 313} 314 315 316@utils.register_interface(EllipticCurveSignatureAlgorithm) 317class ECDSA(object): 318 def __init__(self, algorithm): 319 self._algorithm = algorithm 320 321 algorithm = utils.read_only_property("_algorithm") 322 323 324def generate_private_key(curve, backend=None): 325 backend = _get_backend(backend) 326 return backend.generate_elliptic_curve_private_key(curve) 327 328 329def derive_private_key(private_value, curve, backend=None): 330 backend = _get_backend(backend) 331 if not isinstance(private_value, six.integer_types): 332 raise TypeError("private_value must be an integer type.") 333 334 if private_value <= 0: 335 raise ValueError("private_value must be a positive integer.") 336 337 if not isinstance(curve, EllipticCurve): 338 raise TypeError("curve must provide the EllipticCurve interface.") 339 340 return backend.derive_elliptic_curve_private_key(private_value, curve) 341 342 343class EllipticCurvePublicNumbers(object): 344 def __init__(self, x, y, curve): 345 if not isinstance(x, six.integer_types) or not isinstance( 346 y, six.integer_types 347 ): 348 raise TypeError("x and y must be integers.") 349 350 if not isinstance(curve, EllipticCurve): 351 raise TypeError("curve must provide the EllipticCurve interface.") 352 353 self._y = y 354 self._x = x 355 self._curve = curve 356 357 def public_key(self, backend=None): 358 backend = _get_backend(backend) 359 return backend.load_elliptic_curve_public_numbers(self) 360 361 def encode_point(self): 362 warnings.warn( 363 "encode_point has been deprecated on EllipticCurvePublicNumbers" 364 " and will be removed in a future version. Please use " 365 "EllipticCurvePublicKey.public_bytes to obtain both " 366 "compressed and uncompressed point encoding.", 367 utils.PersistentlyDeprecated2019, 368 stacklevel=2, 369 ) 370 # key_size is in bits. Convert to bytes and round up 371 byte_length = (self.curve.key_size + 7) // 8 372 return ( 373 b"\x04" 374 + utils.int_to_bytes(self.x, byte_length) 375 + utils.int_to_bytes(self.y, byte_length) 376 ) 377 378 @classmethod 379 def from_encoded_point(cls, curve, data): 380 if not isinstance(curve, EllipticCurve): 381 raise TypeError("curve must be an EllipticCurve instance") 382 383 warnings.warn( 384 "Support for unsafe construction of public numbers from " 385 "encoded data will be removed in a future version. " 386 "Please use EllipticCurvePublicKey.from_encoded_point", 387 utils.PersistentlyDeprecated2019, 388 stacklevel=2, 389 ) 390 391 if data.startswith(b"\x04"): 392 # key_size is in bits. Convert to bytes and round up 393 byte_length = (curve.key_size + 7) // 8 394 if len(data) == 2 * byte_length + 1: 395 x = utils.int_from_bytes(data[1 : byte_length + 1], "big") 396 y = utils.int_from_bytes(data[byte_length + 1 :], "big") 397 return cls(x, y, curve) 398 else: 399 raise ValueError("Invalid elliptic curve point data length") 400 else: 401 raise ValueError("Unsupported elliptic curve point type") 402 403 curve = utils.read_only_property("_curve") 404 x = utils.read_only_property("_x") 405 y = utils.read_only_property("_y") 406 407 def __eq__(self, other): 408 if not isinstance(other, EllipticCurvePublicNumbers): 409 return NotImplemented 410 411 return ( 412 self.x == other.x 413 and self.y == other.y 414 and self.curve.name == other.curve.name 415 and self.curve.key_size == other.curve.key_size 416 ) 417 418 def __ne__(self, other): 419 return not self == other 420 421 def __hash__(self): 422 return hash((self.x, self.y, self.curve.name, self.curve.key_size)) 423 424 def __repr__(self): 425 return ( 426 "<EllipticCurvePublicNumbers(curve={0.curve.name}, x={0.x}, " 427 "y={0.y}>".format(self) 428 ) 429 430 431class EllipticCurvePrivateNumbers(object): 432 def __init__(self, private_value, public_numbers): 433 if not isinstance(private_value, six.integer_types): 434 raise TypeError("private_value must be an integer.") 435 436 if not isinstance(public_numbers, EllipticCurvePublicNumbers): 437 raise TypeError( 438 "public_numbers must be an EllipticCurvePublicNumbers " 439 "instance." 440 ) 441 442 self._private_value = private_value 443 self._public_numbers = public_numbers 444 445 def private_key(self, backend=None): 446 backend = _get_backend(backend) 447 return backend.load_elliptic_curve_private_numbers(self) 448 449 private_value = utils.read_only_property("_private_value") 450 public_numbers = utils.read_only_property("_public_numbers") 451 452 def __eq__(self, other): 453 if not isinstance(other, EllipticCurvePrivateNumbers): 454 return NotImplemented 455 456 return ( 457 self.private_value == other.private_value 458 and self.public_numbers == other.public_numbers 459 ) 460 461 def __ne__(self, other): 462 return not self == other 463 464 def __hash__(self): 465 return hash((self.private_value, self.public_numbers)) 466 467 468class ECDH(object): 469 pass 470 471 472_OID_TO_CURVE = { 473 EllipticCurveOID.SECP192R1: SECP192R1, 474 EllipticCurveOID.SECP224R1: SECP224R1, 475 EllipticCurveOID.SECP256K1: SECP256K1, 476 EllipticCurveOID.SECP256R1: SECP256R1, 477 EllipticCurveOID.SECP384R1: SECP384R1, 478 EllipticCurveOID.SECP521R1: SECP521R1, 479 EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, 480 EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, 481 EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, 482 EllipticCurveOID.SECT163K1: SECT163K1, 483 EllipticCurveOID.SECT163R2: SECT163R2, 484 EllipticCurveOID.SECT233K1: SECT233K1, 485 EllipticCurveOID.SECT233R1: SECT233R1, 486 EllipticCurveOID.SECT283K1: SECT283K1, 487 EllipticCurveOID.SECT283R1: SECT283R1, 488 EllipticCurveOID.SECT409K1: SECT409K1, 489 EllipticCurveOID.SECT409R1: SECT409R1, 490 EllipticCurveOID.SECT571K1: SECT571K1, 491 EllipticCurveOID.SECT571R1: SECT571R1, 492} 493 494 495def get_curve_for_oid(oid): 496 try: 497 return _OID_TO_CURVE[oid] 498 except KeyError: 499 raise LookupError( 500 "The provided object identifier has no matching elliptic " 501 "curve class" 502 ) 503