Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py: 69%
227 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
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.
6import abc
7import typing
8import warnings
10from cryptography import utils
11from cryptography.hazmat._oid import ObjectIdentifier
12from cryptography.hazmat.primitives import _serialization, hashes
13from cryptography.hazmat.primitives.asymmetric import (
14 utils as asym_utils,
15)
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")
40class EllipticCurve(metaclass=abc.ABCMeta):
41 @abc.abstractproperty
42 def name(self) -> str:
43 """
44 The name of the curve. e.g. secp256r1.
45 """
47 @abc.abstractproperty
48 def key_size(self) -> int:
49 """
50 Bit size of a secret scalar for the curve.
51 """
54class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta):
55 @abc.abstractproperty
56 def algorithm(
57 self,
58 ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]:
59 """
60 The digest algorithm used with this signature.
61 """
64class EllipticCurvePrivateKey(metaclass=abc.ABCMeta):
65 @abc.abstractmethod
66 def exchange(
67 self, algorithm: "ECDH", peer_public_key: "EllipticCurvePublicKey"
68 ) -> bytes:
69 """
70 Performs a key exchange operation using the provided algorithm with the
71 provided peer's public key.
72 """
74 @abc.abstractmethod
75 def public_key(self) -> "EllipticCurvePublicKey":
76 """
77 The EllipticCurvePublicKey for this private key.
78 """
80 @abc.abstractproperty
81 def curve(self) -> EllipticCurve:
82 """
83 The EllipticCurve that this key is on.
84 """
86 @abc.abstractproperty
87 def key_size(self) -> int:
88 """
89 Bit size of a secret scalar for the curve.
90 """
92 @abc.abstractmethod
93 def sign(
94 self,
95 data: bytes,
96 signature_algorithm: EllipticCurveSignatureAlgorithm,
97 ) -> bytes:
98 """
99 Signs the data
100 """
102 @abc.abstractmethod
103 def private_numbers(self) -> "EllipticCurvePrivateNumbers":
104 """
105 Returns an EllipticCurvePrivateNumbers.
106 """
108 @abc.abstractmethod
109 def private_bytes(
110 self,
111 encoding: _serialization.Encoding,
112 format: _serialization.PrivateFormat,
113 encryption_algorithm: _serialization.KeySerializationEncryption,
114 ) -> bytes:
115 """
116 Returns the key serialized as bytes.
117 """
120EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey
123class EllipticCurvePublicKey(metaclass=abc.ABCMeta):
124 @abc.abstractproperty
125 def curve(self) -> EllipticCurve:
126 """
127 The EllipticCurve that this key is on.
128 """
130 @abc.abstractproperty
131 def key_size(self) -> int:
132 """
133 Bit size of a secret scalar for the curve.
134 """
136 @abc.abstractmethod
137 def public_numbers(self) -> "EllipticCurvePublicNumbers":
138 """
139 Returns an EllipticCurvePublicNumbers.
140 """
142 @abc.abstractmethod
143 def public_bytes(
144 self,
145 encoding: _serialization.Encoding,
146 format: _serialization.PublicFormat,
147 ) -> bytes:
148 """
149 Returns the key serialized as bytes.
150 """
152 @abc.abstractmethod
153 def verify(
154 self,
155 signature: bytes,
156 data: bytes,
157 signature_algorithm: EllipticCurveSignatureAlgorithm,
158 ) -> None:
159 """
160 Verifies the signature of the data.
161 """
163 @classmethod
164 def from_encoded_point(
165 cls, curve: EllipticCurve, data: bytes
166 ) -> "EllipticCurvePublicKey":
167 utils._check_bytes("data", data)
169 if not isinstance(curve, EllipticCurve):
170 raise TypeError("curve must be an EllipticCurve instance")
172 if len(data) == 0:
173 raise ValueError("data must not be an empty byte string")
175 if data[0] not in [0x02, 0x03, 0x04]:
176 raise ValueError("Unsupported elliptic curve point type")
178 from cryptography.hazmat.backends.openssl.backend import backend
180 return backend.load_elliptic_curve_public_bytes(curve, data)
183EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey
186class SECT571R1(EllipticCurve):
187 name = "sect571r1"
188 key_size = 570
191class SECT409R1(EllipticCurve):
192 name = "sect409r1"
193 key_size = 409
196class SECT283R1(EllipticCurve):
197 name = "sect283r1"
198 key_size = 283
201class SECT233R1(EllipticCurve):
202 name = "sect233r1"
203 key_size = 233
206class SECT163R2(EllipticCurve):
207 name = "sect163r2"
208 key_size = 163
211class SECT571K1(EllipticCurve):
212 name = "sect571k1"
213 key_size = 571
216class SECT409K1(EllipticCurve):
217 name = "sect409k1"
218 key_size = 409
221class SECT283K1(EllipticCurve):
222 name = "sect283k1"
223 key_size = 283
226class SECT233K1(EllipticCurve):
227 name = "sect233k1"
228 key_size = 233
231class SECT163K1(EllipticCurve):
232 name = "sect163k1"
233 key_size = 163
236class SECP521R1(EllipticCurve):
237 name = "secp521r1"
238 key_size = 521
241class SECP384R1(EllipticCurve):
242 name = "secp384r1"
243 key_size = 384
246class SECP256R1(EllipticCurve):
247 name = "secp256r1"
248 key_size = 256
251class SECP256K1(EllipticCurve):
252 name = "secp256k1"
253 key_size = 256
256class SECP224R1(EllipticCurve):
257 name = "secp224r1"
258 key_size = 224
261class SECP192R1(EllipticCurve):
262 name = "secp192r1"
263 key_size = 192
266class BrainpoolP256R1(EllipticCurve):
267 name = "brainpoolP256r1"
268 key_size = 256
271class BrainpoolP384R1(EllipticCurve):
272 name = "brainpoolP384r1"
273 key_size = 384
276class BrainpoolP512R1(EllipticCurve):
277 name = "brainpoolP512r1"
278 key_size = 512
281_CURVE_TYPES: typing.Dict[str, typing.Type[EllipticCurve]] = {
282 "prime192v1": SECP192R1,
283 "prime256v1": SECP256R1,
284 "secp192r1": SECP192R1,
285 "secp224r1": SECP224R1,
286 "secp256r1": SECP256R1,
287 "secp384r1": SECP384R1,
288 "secp521r1": SECP521R1,
289 "secp256k1": SECP256K1,
290 "sect163k1": SECT163K1,
291 "sect233k1": SECT233K1,
292 "sect283k1": SECT283K1,
293 "sect409k1": SECT409K1,
294 "sect571k1": SECT571K1,
295 "sect163r2": SECT163R2,
296 "sect233r1": SECT233R1,
297 "sect283r1": SECT283R1,
298 "sect409r1": SECT409R1,
299 "sect571r1": SECT571R1,
300 "brainpoolP256r1": BrainpoolP256R1,
301 "brainpoolP384r1": BrainpoolP384R1,
302 "brainpoolP512r1": BrainpoolP512R1,
303}
306class ECDSA(EllipticCurveSignatureAlgorithm):
307 def __init__(
308 self,
309 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm],
310 ):
311 self._algorithm = algorithm
313 @property
314 def algorithm(
315 self,
316 ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]:
317 return self._algorithm
320def generate_private_key(
321 curve: EllipticCurve, backend: typing.Any = None
322) -> EllipticCurvePrivateKey:
323 from cryptography.hazmat.backends.openssl.backend import backend as ossl
325 return ossl.generate_elliptic_curve_private_key(curve)
328def derive_private_key(
329 private_value: int,
330 curve: EllipticCurve,
331 backend: typing.Any = None,
332) -> EllipticCurvePrivateKey:
333 from cryptography.hazmat.backends.openssl.backend import backend as ossl
335 if not isinstance(private_value, int):
336 raise TypeError("private_value must be an integer type.")
338 if private_value <= 0:
339 raise ValueError("private_value must be a positive integer.")
341 if not isinstance(curve, EllipticCurve):
342 raise TypeError("curve must provide the EllipticCurve interface.")
344 return ossl.derive_elliptic_curve_private_key(private_value, curve)
347class EllipticCurvePublicNumbers:
348 def __init__(self, x: int, y: int, curve: EllipticCurve):
349 if not isinstance(x, int) or not isinstance(y, int):
350 raise TypeError("x and y must be integers.")
352 if not isinstance(curve, EllipticCurve):
353 raise TypeError("curve must provide the EllipticCurve interface.")
355 self._y = y
356 self._x = x
357 self._curve = curve
359 def public_key(self, backend: typing.Any = None) -> EllipticCurvePublicKey:
360 from cryptography.hazmat.backends.openssl.backend import (
361 backend as ossl,
362 )
364 return ossl.load_elliptic_curve_public_numbers(self)
366 def encode_point(self) -> bytes:
367 warnings.warn(
368 "encode_point has been deprecated on EllipticCurvePublicNumbers"
369 " and will be removed in a future version. Please use "
370 "EllipticCurvePublicKey.public_bytes to obtain both "
371 "compressed and uncompressed point encoding.",
372 utils.PersistentlyDeprecated2019,
373 stacklevel=2,
374 )
375 # key_size is in bits. Convert to bytes and round up
376 byte_length = (self.curve.key_size + 7) // 8
377 return (
378 b"\x04"
379 + utils.int_to_bytes(self.x, byte_length)
380 + utils.int_to_bytes(self.y, byte_length)
381 )
383 @classmethod
384 def from_encoded_point(
385 cls, curve: EllipticCurve, data: bytes
386 ) -> "EllipticCurvePublicNumbers":
387 if not isinstance(curve, EllipticCurve):
388 raise TypeError("curve must be an EllipticCurve instance")
390 warnings.warn(
391 "Support for unsafe construction of public numbers from "
392 "encoded data will be removed in a future version. "
393 "Please use EllipticCurvePublicKey.from_encoded_point",
394 utils.PersistentlyDeprecated2019,
395 stacklevel=2,
396 )
398 if data.startswith(b"\x04"):
399 # key_size is in bits. Convert to bytes and round up
400 byte_length = (curve.key_size + 7) // 8
401 if len(data) == 2 * byte_length + 1:
402 x = int.from_bytes(data[1 : byte_length + 1], "big")
403 y = int.from_bytes(data[byte_length + 1 :], "big")
404 return cls(x, y, curve)
405 else:
406 raise ValueError("Invalid elliptic curve point data length")
407 else:
408 raise ValueError("Unsupported elliptic curve point type")
410 @property
411 def curve(self) -> EllipticCurve:
412 return self._curve
414 @property
415 def x(self) -> int:
416 return self._x
418 @property
419 def y(self) -> int:
420 return self._y
422 def __eq__(self, other: object) -> bool:
423 if not isinstance(other, EllipticCurvePublicNumbers):
424 return NotImplemented
426 return (
427 self.x == other.x
428 and self.y == other.y
429 and self.curve.name == other.curve.name
430 and self.curve.key_size == other.curve.key_size
431 )
433 def __hash__(self) -> int:
434 return hash((self.x, self.y, self.curve.name, self.curve.key_size))
436 def __repr__(self) -> str:
437 return (
438 "<EllipticCurvePublicNumbers(curve={0.curve.name}, x={0.x}, "
439 "y={0.y}>".format(self)
440 )
443class EllipticCurvePrivateNumbers:
444 def __init__(
445 self, private_value: int, public_numbers: EllipticCurvePublicNumbers
446 ):
447 if not isinstance(private_value, int):
448 raise TypeError("private_value must be an integer.")
450 if not isinstance(public_numbers, EllipticCurvePublicNumbers):
451 raise TypeError(
452 "public_numbers must be an EllipticCurvePublicNumbers "
453 "instance."
454 )
456 self._private_value = private_value
457 self._public_numbers = public_numbers
459 def private_key(
460 self, backend: typing.Any = None
461 ) -> EllipticCurvePrivateKey:
462 from cryptography.hazmat.backends.openssl.backend import (
463 backend as ossl,
464 )
466 return ossl.load_elliptic_curve_private_numbers(self)
468 @property
469 def private_value(self) -> int:
470 return self._private_value
472 @property
473 def public_numbers(self) -> EllipticCurvePublicNumbers:
474 return self._public_numbers
476 def __eq__(self, other: object) -> bool:
477 if not isinstance(other, EllipticCurvePrivateNumbers):
478 return NotImplemented
480 return (
481 self.private_value == other.private_value
482 and self.public_numbers == other.public_numbers
483 )
485 def __hash__(self) -> int:
486 return hash((self.private_value, self.public_numbers))
489class ECDH:
490 pass
493_OID_TO_CURVE = {
494 EllipticCurveOID.SECP192R1: SECP192R1,
495 EllipticCurveOID.SECP224R1: SECP224R1,
496 EllipticCurveOID.SECP256K1: SECP256K1,
497 EllipticCurveOID.SECP256R1: SECP256R1,
498 EllipticCurveOID.SECP384R1: SECP384R1,
499 EllipticCurveOID.SECP521R1: SECP521R1,
500 EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1,
501 EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1,
502 EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1,
503 EllipticCurveOID.SECT163K1: SECT163K1,
504 EllipticCurveOID.SECT163R2: SECT163R2,
505 EllipticCurveOID.SECT233K1: SECT233K1,
506 EllipticCurveOID.SECT233R1: SECT233R1,
507 EllipticCurveOID.SECT283K1: SECT283K1,
508 EllipticCurveOID.SECT283R1: SECT283R1,
509 EllipticCurveOID.SECT409K1: SECT409K1,
510 EllipticCurveOID.SECT409R1: SECT409R1,
511 EllipticCurveOID.SECT571K1: SECT571K1,
512 EllipticCurveOID.SECT571R1: SECT571R1,
513}
516def get_curve_for_oid(oid: ObjectIdentifier) -> typing.Type[EllipticCurve]:
517 try:
518 return _OID_TO_CURVE[oid]
519 except KeyError:
520 raise LookupError(
521 "The provided object identifier has no matching elliptic "
522 "curve class"
523 )