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