• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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