Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/ecdsa/keys.py: 55%
382 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-07 06:31 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-07 06:31 +0000
1"""
2Primary classes for performing signing and verification operations.
3"""
5import binascii
6from hashlib import sha1
7import os
8from six import PY2, b
9from . import ecdsa, eddsa
10from . import der, ssh
11from . import rfc6979
12from . import ellipticcurve
13from .curves import NIST192p, Curve, Ed25519, Ed448
14from .ecdsa import RSZeroError
15from .util import string_to_number, number_to_string, randrange
16from .util import sigencode_string, sigdecode_string, bit_length
17from .util import (
18 oid_ecPublicKey,
19 encoded_oid_ecPublicKey,
20 oid_ecDH,
21 oid_ecMQV,
22 MalformedSignature,
23)
24from ._compat import normalise_bytes
25from .errors import MalformedPointError
26from .ellipticcurve import PointJacobi, CurveEdTw
29__all__ = [
30 "BadSignatureError",
31 "BadDigestError",
32 "VerifyingKey",
33 "SigningKey",
34 "MalformedPointError",
35]
38class BadSignatureError(Exception):
39 """
40 Raised when verification of signature failed.
42 Will be raised irrespective of reason of the failure:
44 * the calculated or provided hash does not match the signature
45 * the signature does not match the curve/public key
46 * the encoding of the signature is malformed
47 * the size of the signature does not match the curve of the VerifyingKey
48 """
50 pass
53class BadDigestError(Exception):
54 """Raised in case the selected hash is too large for the curve."""
56 pass
59def _truncate_and_convert_digest(digest, curve, allow_truncate):
60 """Truncates and converts digest to an integer."""
61 if not allow_truncate:
62 if len(digest) > curve.baselen:
63 raise BadDigestError(
64 "this curve ({0}) is too short "
65 "for the length of your digest ({1})".format(
66 curve.name, 8 * len(digest)
67 )
68 )
69 else:
70 digest = digest[: curve.baselen]
71 number = string_to_number(digest)
72 if allow_truncate:
73 max_length = bit_length(curve.order)
74 # we don't use bit_length(number) as that truncates leading zeros
75 length = len(digest) * 8
77 # See NIST FIPS 186-4:
78 #
79 # When the length of the output of the hash function is greater
80 # than N (i.e., the bit length of q), then the leftmost N bits of
81 # the hash function output block shall be used in any calculation
82 # using the hash function output during the generation or
83 # verification of a digital signature.
84 #
85 # as such, we need to shift-out the low-order bits:
86 number >>= max(0, length - max_length)
88 return number
91class VerifyingKey(object):
92 """
93 Class for handling keys that can verify signatures (public keys).
95 :ivar `~ecdsa.curves.Curve` ~.curve: The Curve over which all the
96 cryptographic operations will take place
97 :ivar default_hashfunc: the function that will be used for hashing the
98 data. Should implement the same API as hashlib.sha1
99 :vartype default_hashfunc: callable
100 :ivar pubkey: the actual public key
101 :vartype pubkey: ~ecdsa.ecdsa.Public_key
102 """
104 def __init__(self, _error__please_use_generate=None):
105 """Unsupported, please use one of the classmethods to initialise."""
106 if not _error__please_use_generate:
107 raise TypeError(
108 "Please use VerifyingKey.generate() to construct me"
109 )
110 self.curve = None
111 self.default_hashfunc = None
112 self.pubkey = None
114 def __repr__(self):
115 pub_key = self.to_string("compressed")
116 if self.default_hashfunc:
117 hash_name = self.default_hashfunc().name
118 else:
119 hash_name = "None"
120 return "VerifyingKey.from_string({0!r}, {1!r}, {2})".format(
121 pub_key, self.curve, hash_name
122 )
124 def __eq__(self, other):
125 """Return True if the points are identical, False otherwise."""
126 if isinstance(other, VerifyingKey):
127 return self.curve == other.curve and self.pubkey == other.pubkey
128 return NotImplemented
130 def __ne__(self, other):
131 """Return False if the points are identical, True otherwise."""
132 return not self == other
134 @classmethod
135 def from_public_point(
136 cls, point, curve=NIST192p, hashfunc=sha1, validate_point=True
137 ):
138 """
139 Initialise the object from a Point object.
141 This is a low-level method, generally you will not want to use it.
143 :param point: The point to wrap around, the actual public key
144 :type point: ~ecdsa.ellipticcurve.AbstractPoint
145 :param curve: The curve on which the point needs to reside, defaults
146 to NIST192p
147 :type curve: ~ecdsa.curves.Curve
148 :param hashfunc: The default hash function that will be used for
149 verification, needs to implement the same interface
150 as :py:class:`hashlib.sha1`
151 :type hashfunc: callable
152 :type bool validate_point: whether to check if the point lays on curve
153 should always be used if the public point is not a result
154 of our own calculation
156 :raises MalformedPointError: if the public point does not lay on the
157 curve
159 :return: Initialised VerifyingKey object
160 :rtype: VerifyingKey
161 """
162 self = cls(_error__please_use_generate=True)
163 if isinstance(curve.curve, CurveEdTw):
164 raise ValueError("Method incompatible with Edwards curves")
165 if not isinstance(point, ellipticcurve.PointJacobi):
166 point = ellipticcurve.PointJacobi.from_affine(point)
167 self.curve = curve
168 self.default_hashfunc = hashfunc
169 try:
170 self.pubkey = ecdsa.Public_key(
171 curve.generator, point, validate_point
172 )
173 except ecdsa.InvalidPointError:
174 raise MalformedPointError("Point does not lay on the curve")
175 self.pubkey.order = curve.order
176 return self
178 def precompute(self, lazy=False):
179 """
180 Precompute multiplication tables for faster signature verification.
182 Calling this method will cause the library to precompute the
183 scalar multiplication tables, used in signature verification.
184 While it's an expensive operation (comparable to performing
185 as many signatures as the bit size of the curve, i.e. 256 for NIST256p)
186 it speeds up verification 2 times. You should call this method
187 if you expect to verify hundreds of signatures (or more) using the same
188 VerifyingKey object.
190 Note: You should call this method only once, this method generates a
191 new precomputation table every time it's called.
193 :param bool lazy: whether to calculate the precomputation table now
194 (if set to False) or if it should be delayed to the time of first
195 use (when set to True)
196 """
197 if isinstance(self.curve.curve, CurveEdTw):
198 pt = self.pubkey.point
199 self.pubkey.point = ellipticcurve.PointEdwards(
200 pt.curve(),
201 pt.x(),
202 pt.y(),
203 1,
204 pt.x() * pt.y(),
205 self.curve.order,
206 generator=True,
207 )
208 else:
209 self.pubkey.point = ellipticcurve.PointJacobi.from_affine(
210 self.pubkey.point, True
211 )
212 # as precomputation in now delayed to the time of first use of the
213 # point and we were asked specifically to precompute now, make
214 # sure the precomputation is performed now to preserve the behaviour
215 if not lazy:
216 self.pubkey.point * 2
218 @classmethod
219 def from_string(
220 cls,
221 string,
222 curve=NIST192p,
223 hashfunc=sha1,
224 validate_point=True,
225 valid_encodings=None,
226 ):
227 """
228 Initialise the object from byte encoding of public key.
230 The method does accept and automatically detect the type of point
231 encoding used. It supports the :term:`raw encoding`,
232 :term:`uncompressed`, :term:`compressed`, and :term:`hybrid` encodings.
233 It also works with the native encoding of Ed25519 and Ed448 public
234 keys (technically those are compressed, but encoded differently than
235 in other signature systems).
237 Note, while the method is named "from_string" it's a misnomer from
238 Python 2 days when there were no binary strings. In Python 3 the
239 input needs to be a bytes-like object.
241 :param string: single point encoding of the public key
242 :type string: :term:`bytes-like object`
243 :param curve: the curve on which the public key is expected to lay
244 :type curve: ~ecdsa.curves.Curve
245 :param hashfunc: The default hash function that will be used for
246 verification, needs to implement the same interface as
247 hashlib.sha1. Ignored for EdDSA.
248 :type hashfunc: callable
249 :param validate_point: whether to verify that the point lays on the
250 provided curve or not, defaults to True. Ignored for EdDSA.
251 :type validate_point: bool
252 :param valid_encodings: list of acceptable point encoding formats,
253 supported ones are: :term:`uncompressed`, :term:`compressed`,
254 :term:`hybrid`, and :term:`raw encoding` (specified with ``raw``
255 name). All formats by default (specified with ``None``).
256 Ignored for EdDSA.
257 :type valid_encodings: :term:`set-like object`
259 :raises MalformedPointError: if the public point does not lay on the
260 curve or the encoding is invalid
262 :return: Initialised VerifyingKey object
263 :rtype: VerifyingKey
264 """
265 if isinstance(curve.curve, CurveEdTw):
266 self = cls(_error__please_use_generate=True)
267 self.curve = curve
268 self.default_hashfunc = None # ignored for EdDSA
269 try:
270 self.pubkey = eddsa.PublicKey(curve.generator, string)
271 except ValueError:
272 raise MalformedPointError("Malformed point for the curve")
273 return self
275 point = PointJacobi.from_bytes(
276 curve.curve,
277 string,
278 validate_encoding=validate_point,
279 valid_encodings=valid_encodings,
280 )
281 return cls.from_public_point(point, curve, hashfunc, validate_point)
283 @classmethod
284 def from_pem(
285 cls,
286 string,
287 hashfunc=sha1,
288 valid_encodings=None,
289 valid_curve_encodings=None,
290 ):
291 """
292 Initialise from public key stored in :term:`PEM` format.
294 The PEM header of the key should be ``BEGIN PUBLIC KEY``.
296 See the :func:`~VerifyingKey.from_der()` method for details of the
297 format supported.
299 Note: only a single PEM object decoding is supported in provided
300 string.
302 :param string: text with PEM-encoded public ECDSA key
303 :type string: str
304 :param valid_encodings: list of allowed point encodings.
305 By default :term:`uncompressed`, :term:`compressed`, and
306 :term:`hybrid`. To read malformed files, include
307 :term:`raw encoding` with ``raw`` in the list.
308 :type valid_encodings: :term:`set-like object`
309 :param valid_curve_encodings: list of allowed encoding formats
310 for curve parameters. By default (``None``) all are supported:
311 ``named_curve`` and ``explicit``.
312 :type valid_curve_encodings: :term:`set-like object`
315 :return: Initialised VerifyingKey object
316 :rtype: VerifyingKey
317 """
318 return cls.from_der(
319 der.unpem(string),
320 hashfunc=hashfunc,
321 valid_encodings=valid_encodings,
322 valid_curve_encodings=valid_curve_encodings,
323 )
325 @classmethod
326 def from_der(
327 cls,
328 string,
329 hashfunc=sha1,
330 valid_encodings=None,
331 valid_curve_encodings=None,
332 ):
333 """
334 Initialise the key stored in :term:`DER` format.
336 The expected format of the key is the SubjectPublicKeyInfo structure
337 from RFC5912 (for RSA keys, it's known as the PKCS#1 format)::
339 SubjectPublicKeyInfo {PUBLIC-KEY: IOSet} ::= SEQUENCE {
340 algorithm AlgorithmIdentifier {PUBLIC-KEY, {IOSet}},
341 subjectPublicKey BIT STRING
342 }
344 Note: only public EC keys are supported by this method. The
345 SubjectPublicKeyInfo.algorithm.algorithm field must specify
346 id-ecPublicKey (see RFC3279).
348 Only the named curve encoding is supported, thus the
349 SubjectPublicKeyInfo.algorithm.parameters field needs to be an
350 object identifier. A sequence in that field indicates an explicit
351 parameter curve encoding, this format is not supported. A NULL object
352 in that field indicates an "implicitlyCA" encoding, where the curve
353 parameters come from CA certificate, those, again, are not supported.
355 :param string: binary string with the DER encoding of public ECDSA key
356 :type string: bytes-like object
357 :param valid_encodings: list of allowed point encodings.
358 By default :term:`uncompressed`, :term:`compressed`, and
359 :term:`hybrid`. To read malformed files, include
360 :term:`raw encoding` with ``raw`` in the list.
361 :type valid_encodings: :term:`set-like object`
362 :param valid_curve_encodings: list of allowed encoding formats
363 for curve parameters. By default (``None``) all are supported:
364 ``named_curve`` and ``explicit``.
365 :type valid_curve_encodings: :term:`set-like object`
367 :return: Initialised VerifyingKey object
368 :rtype: VerifyingKey
369 """
370 if valid_encodings is None:
371 valid_encodings = set(["uncompressed", "compressed", "hybrid"])
372 string = normalise_bytes(string)
373 # [[oid_ecPublicKey,oid_curve], point_str_bitstring]
374 s1, empty = der.remove_sequence(string)
375 if empty != b"":
376 raise der.UnexpectedDER(
377 "trailing junk after DER pubkey: %s" % binascii.hexlify(empty)
378 )
379 s2, point_str_bitstring = der.remove_sequence(s1)
380 # s2 = oid_ecPublicKey,oid_curve
381 oid_pk, rest = der.remove_object(s2)
382 if oid_pk in (Ed25519.oid, Ed448.oid):
383 if oid_pk == Ed25519.oid:
384 curve = Ed25519
385 else:
386 assert oid_pk == Ed448.oid
387 curve = Ed448
388 point_str, empty = der.remove_bitstring(point_str_bitstring, 0)
389 if empty:
390 raise der.UnexpectedDER("trailing junk after public key")
391 return cls.from_string(point_str, curve, None)
392 if not oid_pk == oid_ecPublicKey:
393 raise der.UnexpectedDER(
394 "Unexpected object identifier in DER "
395 "encoding: {0!r}".format(oid_pk)
396 )
397 curve = Curve.from_der(rest, valid_curve_encodings)
398 point_str, empty = der.remove_bitstring(point_str_bitstring, 0)
399 if empty != b"":
400 raise der.UnexpectedDER(
401 "trailing junk after pubkey pointstring: %s"
402 % binascii.hexlify(empty)
403 )
404 # raw encoding of point is invalid in DER files
405 if len(point_str) == curve.verifying_key_length:
406 raise der.UnexpectedDER("Malformed encoding of public point")
407 return cls.from_string(
408 point_str,
409 curve,
410 hashfunc=hashfunc,
411 valid_encodings=valid_encodings,
412 )
414 @classmethod
415 def from_public_key_recovery(
416 cls,
417 signature,
418 data,
419 curve,
420 hashfunc=sha1,
421 sigdecode=sigdecode_string,
422 allow_truncate=True,
423 ):
424 """
425 Return keys that can be used as verifiers of the provided signature.
427 Tries to recover the public key that can be used to verify the
428 signature, usually returns two keys like that.
430 :param signature: the byte string with the encoded signature
431 :type signature: bytes-like object
432 :param data: the data to be hashed for signature verification
433 :type data: bytes-like object
434 :param curve: the curve over which the signature was performed
435 :type curve: ~ecdsa.curves.Curve
436 :param hashfunc: The default hash function that will be used for
437 verification, needs to implement the same interface as hashlib.sha1
438 :type hashfunc: callable
439 :param sigdecode: Callable to define the way the signature needs to
440 be decoded to an object, needs to handle `signature` as the
441 first parameter, the curve order (an int) as the second and return
442 a tuple with two integers, "r" as the first one and "s" as the
443 second one. See :func:`ecdsa.util.sigdecode_string` and
444 :func:`ecdsa.util.sigdecode_der` for examples.
445 :param bool allow_truncate: if True, the provided hashfunc can generate
446 values larger than the bit size of the order of the curve, the
447 extra bits (at the end of the digest) will be truncated.
448 :type sigdecode: callable
450 :return: Initialised VerifyingKey objects
451 :rtype: list of VerifyingKey
452 """
453 if isinstance(curve.curve, CurveEdTw):
454 raise ValueError("Method unsupported for Edwards curves")
455 data = normalise_bytes(data)
456 digest = hashfunc(data).digest()
457 return cls.from_public_key_recovery_with_digest(
458 signature,
459 digest,
460 curve,
461 hashfunc=hashfunc,
462 sigdecode=sigdecode,
463 allow_truncate=allow_truncate,
464 )
466 @classmethod
467 def from_public_key_recovery_with_digest(
468 cls,
469 signature,
470 digest,
471 curve,
472 hashfunc=sha1,
473 sigdecode=sigdecode_string,
474 allow_truncate=False,
475 ):
476 """
477 Return keys that can be used as verifiers of the provided signature.
479 Tries to recover the public key that can be used to verify the
480 signature, usually returns two keys like that.
482 :param signature: the byte string with the encoded signature
483 :type signature: bytes-like object
484 :param digest: the hash value of the message signed by the signature
485 :type digest: bytes-like object
486 :param curve: the curve over which the signature was performed
487 :type curve: ~ecdsa.curves.Curve
488 :param hashfunc: The default hash function that will be used for
489 verification, needs to implement the same interface as hashlib.sha1
490 :type hashfunc: callable
491 :param sigdecode: Callable to define the way the signature needs to
492 be decoded to an object, needs to handle `signature` as the
493 first parameter, the curve order (an int) as the second and return
494 a tuple with two integers, "r" as the first one and "s" as the
495 second one. See :func:`ecdsa.util.sigdecode_string` and
496 :func:`ecdsa.util.sigdecode_der` for examples.
497 :type sigdecode: callable
498 :param bool allow_truncate: if True, the provided hashfunc can generate
499 values larger than the bit size of the order of the curve (and
500 the length of provided `digest`), the extra bits (at the end of the
501 digest) will be truncated.
503 :return: Initialised VerifyingKey object
504 :rtype: VerifyingKey
505 """
506 if isinstance(curve.curve, CurveEdTw):
507 raise ValueError("Method unsupported for Edwards curves")
508 generator = curve.generator
509 r, s = sigdecode(signature, generator.order())
510 sig = ecdsa.Signature(r, s)
512 digest = normalise_bytes(digest)
513 digest_as_number = _truncate_and_convert_digest(
514 digest, curve, allow_truncate
515 )
516 pks = sig.recover_public_keys(digest_as_number, generator)
518 # Transforms the ecdsa.Public_key object into a VerifyingKey
519 verifying_keys = [
520 cls.from_public_point(pk.point, curve, hashfunc) for pk in pks
521 ]
522 return verifying_keys
524 def to_string(self, encoding="raw"):
525 """
526 Convert the public key to a byte string.
528 The method by default uses the :term:`raw encoding` (specified
529 by `encoding="raw"`. It can also output keys in :term:`uncompressed`,
530 :term:`compressed` and :term:`hybrid` formats.
532 Remember that the curve identification is not part of the encoding
533 so to decode the point using :func:`~VerifyingKey.from_string`, curve
534 needs to be specified.
536 Note: while the method is called "to_string", it's a misnomer from
537 Python 2 days when character strings and byte strings shared type.
538 On Python 3 the returned type will be `bytes`.
540 :return: :term:`raw encoding` of the public key (public point) on the
541 curve
542 :rtype: bytes
543 """
544 assert encoding in ("raw", "uncompressed", "compressed", "hybrid")
545 return self.pubkey.point.to_bytes(encoding)
547 def to_pem(
548 self, point_encoding="uncompressed", curve_parameters_encoding=None
549 ):
550 """
551 Convert the public key to the :term:`PEM` format.
553 The PEM header of the key will be ``BEGIN PUBLIC KEY``.
555 The format of the key is described in the
556 :func:`~VerifyingKey.from_der()` method.
557 This method supports only "named curve" encoding of keys.
559 :param str point_encoding: specification of the encoding format
560 of public keys. "uncompressed" is most portable, "compressed" is
561 smallest. "hybrid" is uncommon and unsupported by most
562 implementations, it is as big as "uncompressed".
563 :param str curve_parameters_encoding: the encoding for curve parameters
564 to use, by default tries to use ``named_curve`` encoding,
565 if that is not possible, falls back to ``explicit`` encoding.
567 :return: portable encoding of the public key
568 :rtype: bytes
570 .. warning:: The PEM is encoded to US-ASCII, it needs to be
571 re-encoded if the system is incompatible (e.g. uses UTF-16)
572 """
573 return der.topem(
574 self.to_der(point_encoding, curve_parameters_encoding),
575 "PUBLIC KEY",
576 )
578 def to_der(
579 self, point_encoding="uncompressed", curve_parameters_encoding=None
580 ):
581 """
582 Convert the public key to the :term:`DER` format.
584 The format of the key is described in the
585 :func:`~VerifyingKey.from_der()` method.
586 This method supports only "named curve" encoding of keys.
588 :param str point_encoding: specification of the encoding format
589 of public keys. "uncompressed" is most portable, "compressed" is
590 smallest. "hybrid" is uncommon and unsupported by most
591 implementations, it is as big as "uncompressed".
592 :param str curve_parameters_encoding: the encoding for curve parameters
593 to use, by default tries to use ``named_curve`` encoding,
594 if that is not possible, falls back to ``explicit`` encoding.
596 :return: DER encoding of the public key
597 :rtype: bytes
598 """
599 if point_encoding == "raw":
600 raise ValueError("raw point_encoding not allowed in DER")
601 point_str = self.to_string(point_encoding)
602 if isinstance(self.curve.curve, CurveEdTw):
603 return der.encode_sequence(
604 der.encode_sequence(der.encode_oid(*self.curve.oid)),
605 der.encode_bitstring(bytes(point_str), 0),
606 )
607 return der.encode_sequence(
608 der.encode_sequence(
609 encoded_oid_ecPublicKey,
610 self.curve.to_der(curve_parameters_encoding, point_encoding),
611 ),
612 # 0 is the number of unused bits in the
613 # bit string
614 der.encode_bitstring(point_str, 0),
615 )
617 def to_ssh(self):
618 """
619 Convert the public key to the SSH format.
621 :return: SSH encoding of the public key
622 :rtype: bytes
623 """
624 return ssh.serialize_public(
625 self.curve.name,
626 self.to_string(),
627 )
629 def verify(
630 self,
631 signature,
632 data,
633 hashfunc=None,
634 sigdecode=sigdecode_string,
635 allow_truncate=True,
636 ):
637 """
638 Verify a signature made over provided data.
640 Will hash `data` to verify the signature.
642 By default expects signature in :term:`raw encoding`. Can also be used
643 to verify signatures in ASN.1 DER encoding by using
644 :func:`ecdsa.util.sigdecode_der`
645 as the `sigdecode` parameter.
647 :param signature: encoding of the signature
648 :type signature: sigdecode method dependent
649 :param data: data signed by the `signature`, will be hashed using
650 `hashfunc`, if specified, or default hash function
651 :type data: :term:`bytes-like object`
652 :param hashfunc: The default hash function that will be used for
653 verification, needs to implement the same interface as hashlib.sha1
654 :type hashfunc: callable
655 :param sigdecode: Callable to define the way the signature needs to
656 be decoded to an object, needs to handle `signature` as the
657 first parameter, the curve order (an int) as the second and return
658 a tuple with two integers, "r" as the first one and "s" as the
659 second one. See :func:`ecdsa.util.sigdecode_string` and
660 :func:`ecdsa.util.sigdecode_der` for examples.
661 :type sigdecode: callable
662 :param bool allow_truncate: if True, the provided digest can have
663 bigger bit-size than the order of the curve, the extra bits (at
664 the end of the digest) will be truncated. Use it when verifying
665 SHA-384 output using NIST256p or in similar situations. Defaults to
666 True.
668 :raises BadSignatureError: if the signature is invalid or malformed
670 :return: True if the verification was successful
671 :rtype: bool
672 """
673 # signature doesn't have to be a bytes-like-object so don't normalise
674 # it, the decoders will do that
675 data = normalise_bytes(data)
676 if isinstance(self.curve.curve, CurveEdTw):
677 signature = normalise_bytes(signature)
678 try:
679 return self.pubkey.verify(data, signature)
680 except (ValueError, MalformedPointError) as e:
681 raise BadSignatureError("Signature verification failed", e)
683 hashfunc = hashfunc or self.default_hashfunc
684 digest = hashfunc(data).digest()
685 return self.verify_digest(signature, digest, sigdecode, allow_truncate)
687 def verify_digest(
688 self,
689 signature,
690 digest,
691 sigdecode=sigdecode_string,
692 allow_truncate=False,
693 ):
694 """
695 Verify a signature made over provided hash value.
697 By default expects signature in :term:`raw encoding`. Can also be used
698 to verify signatures in ASN.1 DER encoding by using
699 :func:`ecdsa.util.sigdecode_der`
700 as the `sigdecode` parameter.
702 :param signature: encoding of the signature
703 :type signature: sigdecode method dependent
704 :param digest: raw hash value that the signature authenticates.
705 :type digest: :term:`bytes-like object`
706 :param sigdecode: Callable to define the way the signature needs to
707 be decoded to an object, needs to handle `signature` as the
708 first parameter, the curve order (an int) as the second and return
709 a tuple with two integers, "r" as the first one and "s" as the
710 second one. See :func:`ecdsa.util.sigdecode_string` and
711 :func:`ecdsa.util.sigdecode_der` for examples.
712 :type sigdecode: callable
713 :param bool allow_truncate: if True, the provided digest can have
714 bigger bit-size than the order of the curve, the extra bits (at
715 the end of the digest) will be truncated. Use it when verifying
716 SHA-384 output using NIST256p or in similar situations.
718 :raises BadSignatureError: if the signature is invalid or malformed
719 :raises BadDigestError: if the provided digest is too big for the curve
720 associated with this VerifyingKey and allow_truncate was not set
722 :return: True if the verification was successful
723 :rtype: bool
724 """
725 # signature doesn't have to be a bytes-like-object so don't normalise
726 # it, the decoders will do that
727 digest = normalise_bytes(digest)
728 number = _truncate_and_convert_digest(
729 digest,
730 self.curve,
731 allow_truncate,
732 )
734 try:
735 r, s = sigdecode(signature, self.pubkey.order)
736 except (der.UnexpectedDER, MalformedSignature) as e:
737 raise BadSignatureError("Malformed formatting of signature", e)
738 sig = ecdsa.Signature(r, s)
739 if self.pubkey.verifies(number, sig):
740 return True
741 raise BadSignatureError("Signature verification failed")
744class SigningKey(object):
745 """
746 Class for handling keys that can create signatures (private keys).
748 :ivar `~ecdsa.curves.Curve` curve: The Curve over which all the
749 cryptographic operations will take place
750 :ivar default_hashfunc: the function that will be used for hashing the
751 data. Should implement the same API as :py:class:`hashlib.sha1`
752 :ivar int baselen: the length of a :term:`raw encoding` of private key
753 :ivar `~ecdsa.keys.VerifyingKey` verifying_key: the public key
754 associated with this private key
755 :ivar `~ecdsa.ecdsa.Private_key` privkey: the actual private key
756 """
758 def __init__(self, _error__please_use_generate=None):
759 """Unsupported, please use one of the classmethods to initialise."""
760 if not _error__please_use_generate:
761 raise TypeError("Please use SigningKey.generate() to construct me")
762 self.curve = None
763 self.default_hashfunc = None
764 self.baselen = None
765 self.verifying_key = None
766 self.privkey = None
768 def __eq__(self, other):
769 """Return True if the points are identical, False otherwise."""
770 if isinstance(other, SigningKey):
771 return (
772 self.curve == other.curve
773 and self.verifying_key == other.verifying_key
774 and self.privkey == other.privkey
775 )
776 return NotImplemented
778 def __ne__(self, other):
779 """Return False if the points are identical, True otherwise."""
780 return not self == other
782 @classmethod
783 def _twisted_edwards_keygen(cls, curve, entropy):
784 """Generate a private key on a Twisted Edwards curve."""
785 if not entropy:
786 entropy = os.urandom
787 random = entropy(curve.baselen)
788 private_key = eddsa.PrivateKey(curve.generator, random)
789 public_key = private_key.public_key()
791 verifying_key = VerifyingKey.from_string(
792 public_key.public_key(), curve
793 )
795 self = cls(_error__please_use_generate=True)
796 self.curve = curve
797 self.default_hashfunc = None
798 self.baselen = curve.baselen
799 self.privkey = private_key
800 self.verifying_key = verifying_key
801 return self
803 @classmethod
804 def _weierstrass_keygen(cls, curve, entropy, hashfunc):
805 """Generate a private key on a Weierstrass curve."""
806 secexp = randrange(curve.order, entropy)
807 return cls.from_secret_exponent(secexp, curve, hashfunc)
809 @classmethod
810 def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):
811 """
812 Generate a random private key.
814 :param curve: The curve on which the point needs to reside, defaults
815 to NIST192p
816 :type curve: ~ecdsa.curves.Curve
817 :param entropy: Source of randomness for generating the private keys,
818 should provide cryptographically secure random numbers if the keys
819 need to be secure. Uses os.urandom() by default.
820 :type entropy: callable
821 :param hashfunc: The default hash function that will be used for
822 signing, needs to implement the same interface
823 as hashlib.sha1
824 :type hashfunc: callable
826 :return: Initialised SigningKey object
827 :rtype: SigningKey
828 """
829 if isinstance(curve.curve, CurveEdTw):
830 return cls._twisted_edwards_keygen(curve, entropy)
831 return cls._weierstrass_keygen(curve, entropy, hashfunc)
833 @classmethod
834 def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1):
835 """
836 Create a private key from a random integer.
838 Note: it's a low level method, it's recommended to use the
839 :func:`~SigningKey.generate` method to create private keys.
841 :param int secexp: secret multiplier (the actual private key in ECDSA).
842 Needs to be an integer between 1 and the curve order.
843 :param curve: The curve on which the point needs to reside
844 :type curve: ~ecdsa.curves.Curve
845 :param hashfunc: The default hash function that will be used for
846 signing, needs to implement the same interface
847 as hashlib.sha1
848 :type hashfunc: callable
850 :raises MalformedPointError: when the provided secexp is too large
851 or too small for the curve selected
852 :raises RuntimeError: if the generation of public key from private
853 key failed
855 :return: Initialised SigningKey object
856 :rtype: SigningKey
857 """
858 if isinstance(curve.curve, CurveEdTw):
859 raise ValueError(
860 "Edwards keys don't support setting the secret scalar "
861 "(exponent) directly"
862 )
863 self = cls(_error__please_use_generate=True)
864 self.curve = curve
865 self.default_hashfunc = hashfunc
866 self.baselen = curve.baselen
867 n = curve.order
868 if not 1 <= secexp < n:
869 raise MalformedPointError(
870 "Invalid value for secexp, expected integer "
871 "between 1 and {0}".format(n)
872 )
873 pubkey_point = curve.generator * secexp
874 if hasattr(pubkey_point, "scale"):
875 pubkey_point = pubkey_point.scale()
876 self.verifying_key = VerifyingKey.from_public_point(
877 pubkey_point, curve, hashfunc, False
878 )
879 pubkey = self.verifying_key.pubkey
880 self.privkey = ecdsa.Private_key(pubkey, secexp)
881 self.privkey.order = n
882 return self
884 @classmethod
885 def from_string(cls, string, curve=NIST192p, hashfunc=sha1):
886 """
887 Decode the private key from :term:`raw encoding`.
889 Note: the name of this method is a misnomer coming from days of
890 Python 2, when binary strings and character strings shared a type.
891 In Python 3, the expected type is `bytes`.
893 :param string: the raw encoding of the private key
894 :type string: :term:`bytes-like object`
895 :param curve: The curve on which the point needs to reside
896 :type curve: ~ecdsa.curves.Curve
897 :param hashfunc: The default hash function that will be used for
898 signing, needs to implement the same interface
899 as hashlib.sha1
900 :type hashfunc: callable
902 :raises MalformedPointError: if the length of encoding doesn't match
903 the provided curve or the encoded values is too large
904 :raises RuntimeError: if the generation of public key from private
905 key failed
907 :return: Initialised SigningKey object
908 :rtype: SigningKey
909 """
910 string = normalise_bytes(string)
912 if len(string) != curve.baselen:
913 raise MalformedPointError(
914 "Invalid length of private key, received {0}, "
915 "expected {1}".format(len(string), curve.baselen)
916 )
917 if isinstance(curve.curve, CurveEdTw):
918 self = cls(_error__please_use_generate=True)
919 self.curve = curve
920 self.default_hashfunc = None # Ignored for EdDSA
921 self.baselen = curve.baselen
922 self.privkey = eddsa.PrivateKey(curve.generator, string)
923 self.verifying_key = VerifyingKey.from_string(
924 self.privkey.public_key().public_key(), curve
925 )
926 return self
927 secexp = string_to_number(string)
928 return cls.from_secret_exponent(secexp, curve, hashfunc)
930 @classmethod
931 def from_pem(cls, string, hashfunc=sha1, valid_curve_encodings=None):
932 """
933 Initialise from key stored in :term:`PEM` format.
935 The PEM formats supported are the un-encrypted RFC5915
936 (the ssleay format) supported by OpenSSL, and the more common
937 un-encrypted RFC5958 (the PKCS #8 format).
939 The legacy format files have the header with the string
940 ``BEGIN EC PRIVATE KEY``.
941 PKCS#8 files have the header ``BEGIN PRIVATE KEY``.
942 Encrypted files (ones that include the string
943 ``Proc-Type: 4,ENCRYPTED``
944 right after the PEM header) are not supported.
946 See :func:`~SigningKey.from_der` for ASN.1 syntax of the objects in
947 this files.
949 :param string: text with PEM-encoded private ECDSA key
950 :type string: str
951 :param valid_curve_encodings: list of allowed encoding formats
952 for curve parameters. By default (``None``) all are supported:
953 ``named_curve`` and ``explicit``.
954 :type valid_curve_encodings: :term:`set-like object`
957 :raises MalformedPointError: if the length of encoding doesn't match
958 the provided curve or the encoded values is too large
959 :raises RuntimeError: if the generation of public key from private
960 key failed
961 :raises UnexpectedDER: if the encoding of the PEM file is incorrect
963 :return: Initialised SigningKey object
964 :rtype: SigningKey
965 """
966 if not PY2 and isinstance(string, str): # pragma: no branch
967 string = string.encode()
969 # The privkey pem may have multiple sections, commonly it also has
970 # "EC PARAMETERS", we need just "EC PRIVATE KEY". PKCS#8 should not
971 # have the "EC PARAMETERS" section; it's just "PRIVATE KEY".
972 private_key_index = string.find(b"-----BEGIN EC PRIVATE KEY-----")
973 if private_key_index == -1:
974 private_key_index = string.index(b"-----BEGIN PRIVATE KEY-----")
976 return cls.from_der(
977 der.unpem(string[private_key_index:]),
978 hashfunc,
979 valid_curve_encodings,
980 )
982 @classmethod
983 def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):
984 """
985 Initialise from key stored in :term:`DER` format.
987 The DER formats supported are the un-encrypted RFC5915
988 (the ssleay format) supported by OpenSSL, and the more common
989 un-encrypted RFC5958 (the PKCS #8 format).
991 Both formats contain an ASN.1 object following the syntax specified
992 in RFC5915::
994 ECPrivateKey ::= SEQUENCE {
995 version INTEGER { ecPrivkeyVer1(1) }} (ecPrivkeyVer1),
996 privateKey OCTET STRING,
997 parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
998 publicKey [1] BIT STRING OPTIONAL
999 }
1001 `publicKey` field is ignored completely (errors, if any, in it will
1002 be undetected).
1004 Two formats are supported for the `parameters` field: the named
1005 curve and the explicit encoding of curve parameters.
1006 In the legacy ssleay format, this implementation requires the optional
1007 `parameters` field to get the curve name. In PKCS #8 format, the curve
1008 is part of the PrivateKeyAlgorithmIdentifier.
1010 The PKCS #8 format includes an ECPrivateKey object as the `privateKey`
1011 field within a larger structure::
1013 OneAsymmetricKey ::= SEQUENCE {
1014 version Version,
1015 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1016 privateKey PrivateKey,
1017 attributes [0] Attributes OPTIONAL,
1018 ...,
1019 [[2: publicKey [1] PublicKey OPTIONAL ]],
1020 ...
1021 }
1023 The `attributes` and `publicKey` fields are completely ignored; errors
1024 in them will not be detected.
1026 :param string: binary string with DER-encoded private ECDSA key
1027 :type string: :term:`bytes-like object`
1028 :param valid_curve_encodings: list of allowed encoding formats
1029 for curve parameters. By default (``None``) all are supported:
1030 ``named_curve`` and ``explicit``.
1031 Ignored for EdDSA.
1032 :type valid_curve_encodings: :term:`set-like object`
1034 :raises MalformedPointError: if the length of encoding doesn't match
1035 the provided curve or the encoded values is too large
1036 :raises RuntimeError: if the generation of public key from private
1037 key failed
1038 :raises UnexpectedDER: if the encoding of the DER file is incorrect
1040 :return: Initialised SigningKey object
1041 :rtype: SigningKey
1042 """
1043 s = normalise_bytes(string)
1044 curve = None
1046 s, empty = der.remove_sequence(s)
1047 if empty != b(""):
1048 raise der.UnexpectedDER(
1049 "trailing junk after DER privkey: %s" % binascii.hexlify(empty)
1050 )
1052 version, s = der.remove_integer(s)
1054 # At this point, PKCS #8 has a sequence containing the algorithm
1055 # identifier and the curve identifier. The ssleay format instead has
1056 # an octet string containing the key data, so this is how we can
1057 # distinguish the two formats.
1058 if der.is_sequence(s):
1059 if version not in (0, 1):
1060 raise der.UnexpectedDER(
1061 "expected version '0' or '1' at start of privkey, got %d"
1062 % version
1063 )
1065 sequence, s = der.remove_sequence(s)
1066 algorithm_oid, algorithm_identifier = der.remove_object(sequence)
1068 if algorithm_oid in (Ed25519.oid, Ed448.oid):
1069 if algorithm_identifier:
1070 raise der.UnexpectedDER(
1071 "Non NULL parameters for a EdDSA key"
1072 )
1073 key_str_der, s = der.remove_octet_string(s)
1075 # As RFC5958 describe, there are may be optional Attributes
1076 # and Publickey. Don't raise error if something after
1077 # Privatekey
1079 # TODO parse attributes or validate publickey
1080 # if s:
1081 # raise der.UnexpectedDER(
1082 # "trailing junk inside the privateKey"
1083 # )
1084 key_str, s = der.remove_octet_string(key_str_der)
1085 if s:
1086 raise der.UnexpectedDER(
1087 "trailing junk after the encoded private key"
1088 )
1090 if algorithm_oid == Ed25519.oid:
1091 curve = Ed25519
1092 else:
1093 assert algorithm_oid == Ed448.oid
1094 curve = Ed448
1096 return cls.from_string(key_str, curve, None)
1098 if algorithm_oid not in (oid_ecPublicKey, oid_ecDH, oid_ecMQV):
1099 raise der.UnexpectedDER(
1100 "unexpected algorithm identifier '%s'" % (algorithm_oid,)
1101 )
1103 curve = Curve.from_der(algorithm_identifier, valid_curve_encodings)
1105 if empty != b"":
1106 raise der.UnexpectedDER(
1107 "unexpected data after algorithm identifier: %s"
1108 % binascii.hexlify(empty)
1109 )
1111 # Up next is an octet string containing an ECPrivateKey. Ignore
1112 # the optional "attributes" and "publicKey" fields that come after.
1113 s, _ = der.remove_octet_string(s)
1115 # Unpack the ECPrivateKey to get to the key data octet string,
1116 # and rejoin the ssleay parsing path.
1117 s, empty = der.remove_sequence(s)
1118 if empty != b(""):
1119 raise der.UnexpectedDER(
1120 "trailing junk after DER privkey: %s"
1121 % binascii.hexlify(empty)
1122 )
1124 version, s = der.remove_integer(s)
1126 # The version of the ECPrivateKey must be 1.
1127 if version != 1:
1128 raise der.UnexpectedDER(
1129 "expected version '1' at start of DER privkey, got %d"
1130 % version
1131 )
1133 privkey_str, s = der.remove_octet_string(s)
1135 if not curve:
1136 tag, curve_oid_str, s = der.remove_constructed(s)
1137 if tag != 0:
1138 raise der.UnexpectedDER(
1139 "expected tag 0 in DER privkey, got %d" % tag
1140 )
1141 curve = Curve.from_der(curve_oid_str, valid_curve_encodings)
1143 # we don't actually care about the following fields
1144 #
1145 # tag, pubkey_bitstring, s = der.remove_constructed(s)
1146 # if tag != 1:
1147 # raise der.UnexpectedDER("expected tag 1 in DER privkey, got %d"
1148 # % tag)
1149 # pubkey_str = der.remove_bitstring(pubkey_bitstring, 0)
1150 # if empty != "":
1151 # raise der.UnexpectedDER("trailing junk after DER privkey "
1152 # "pubkeystr: %s"
1153 # % binascii.hexlify(empty))
1155 # our from_string method likes fixed-length privkey strings
1156 if len(privkey_str) < curve.baselen:
1157 privkey_str = (
1158 b("\x00") * (curve.baselen - len(privkey_str)) + privkey_str
1159 )
1160 return cls.from_string(privkey_str, curve, hashfunc)
1162 def to_string(self):
1163 """
1164 Convert the private key to :term:`raw encoding`.
1166 Note: while the method is named "to_string", its name comes from
1167 Python 2 days, when binary and character strings used the same type.
1168 The type used in Python 3 is `bytes`.
1170 :return: raw encoding of private key
1171 :rtype: bytes
1172 """
1173 if isinstance(self.curve.curve, CurveEdTw):
1174 return bytes(self.privkey.private_key)
1175 secexp = self.privkey.secret_multiplier
1176 s = number_to_string(secexp, self.privkey.order)
1177 return s
1179 def to_pem(
1180 self,
1181 point_encoding="uncompressed",
1182 format="ssleay",
1183 curve_parameters_encoding=None,
1184 ):
1185 """
1186 Convert the private key to the :term:`PEM` format.
1188 See :func:`~SigningKey.from_pem` method for format description.
1190 Only the named curve format is supported.
1191 The public key will be included in generated string.
1193 The PEM header will specify ``BEGIN EC PRIVATE KEY`` or
1194 ``BEGIN PRIVATE KEY``, depending on the desired format.
1196 :param str point_encoding: format to use for encoding public point
1197 :param str format: either ``ssleay`` (default) or ``pkcs8``
1198 :param str curve_parameters_encoding: format of encoded curve
1199 parameters, default depends on the curve, if the curve has
1200 an associated OID, ``named_curve`` format will be used,
1201 if no OID is associated with the curve, the fallback of
1202 ``explicit`` parameters will be used.
1204 :return: PEM encoded private key
1205 :rtype: bytes
1207 .. warning:: The PEM is encoded to US-ASCII, it needs to be
1208 re-encoded if the system is incompatible (e.g. uses UTF-16)
1209 """
1210 # TODO: "BEGIN ECPARAMETERS"
1211 assert format in ("ssleay", "pkcs8")
1212 header = "EC PRIVATE KEY" if format == "ssleay" else "PRIVATE KEY"
1213 return der.topem(
1214 self.to_der(point_encoding, format, curve_parameters_encoding),
1215 header,
1216 )
1218 def _encode_eddsa(self):
1219 """Create a PKCS#8 encoding of EdDSA keys."""
1220 ec_private_key = der.encode_octet_string(self.to_string())
1221 return der.encode_sequence(
1222 der.encode_integer(0),
1223 der.encode_sequence(der.encode_oid(*self.curve.oid)),
1224 der.encode_octet_string(ec_private_key),
1225 )
1227 def to_der(
1228 self,
1229 point_encoding="uncompressed",
1230 format="ssleay",
1231 curve_parameters_encoding=None,
1232 ):
1233 """
1234 Convert the private key to the :term:`DER` format.
1236 See :func:`~SigningKey.from_der` method for format specification.
1238 Only the named curve format is supported.
1239 The public key will be included in the generated string.
1241 :param str point_encoding: format to use for encoding public point
1242 Ignored for EdDSA
1243 :param str format: either ``ssleay`` (default) or ``pkcs8``.
1244 EdDSA keys require ``pkcs8``.
1245 :param str curve_parameters_encoding: format of encoded curve
1246 parameters, default depends on the curve, if the curve has
1247 an associated OID, ``named_curve`` format will be used,
1248 if no OID is associated with the curve, the fallback of
1249 ``explicit`` parameters will be used.
1250 Ignored for EdDSA.
1252 :return: DER encoded private key
1253 :rtype: bytes
1254 """
1255 # SEQ([int(1), octetstring(privkey),cont[0], oid(secp224r1),
1256 # cont[1],bitstring])
1257 if point_encoding == "raw":
1258 raise ValueError("raw encoding not allowed in DER")
1259 assert format in ("ssleay", "pkcs8")
1260 if isinstance(self.curve.curve, CurveEdTw):
1261 if format != "pkcs8":
1262 raise ValueError("Only PKCS#8 format supported for EdDSA keys")
1263 return self._encode_eddsa()
1264 encoded_vk = self.get_verifying_key().to_string(point_encoding)
1265 priv_key_elems = [
1266 der.encode_integer(1),
1267 der.encode_octet_string(self.to_string()),
1268 ]
1269 if format == "ssleay":
1270 priv_key_elems.append(
1271 der.encode_constructed(
1272 0, self.curve.to_der(curve_parameters_encoding)
1273 )
1274 )
1275 # the 0 in encode_bitstring specifies the number of unused bits
1276 # in the `encoded_vk` string
1277 priv_key_elems.append(
1278 der.encode_constructed(1, der.encode_bitstring(encoded_vk, 0))
1279 )
1280 ec_private_key = der.encode_sequence(*priv_key_elems)
1282 if format == "ssleay":
1283 return ec_private_key
1284 else:
1285 return der.encode_sequence(
1286 # version = 1 means the public key is not present in the
1287 # top-level structure.
1288 der.encode_integer(1),
1289 der.encode_sequence(
1290 der.encode_oid(*oid_ecPublicKey),
1291 self.curve.to_der(curve_parameters_encoding),
1292 ),
1293 der.encode_octet_string(ec_private_key),
1294 )
1296 def to_ssh(self):
1297 """
1298 Convert the private key to the SSH format.
1300 :return: SSH encoded private key
1301 :rtype: bytes
1302 """
1303 return ssh.serialize_private(
1304 self.curve.name,
1305 self.verifying_key.to_string(),
1306 self.to_string(),
1307 )
1309 def get_verifying_key(self):
1310 """
1311 Return the VerifyingKey associated with this private key.
1313 Equivalent to reading the `verifying_key` field of an instance.
1315 :return: a public key that can be used to verify the signatures made
1316 with this SigningKey
1317 :rtype: VerifyingKey
1318 """
1319 return self.verifying_key
1321 def sign_deterministic(
1322 self,
1323 data,
1324 hashfunc=None,
1325 sigencode=sigencode_string,
1326 extra_entropy=b"",
1327 ):
1328 """
1329 Create signature over data.
1331 For Weierstrass curves it uses the deterministic RFC6979 algorithm.
1332 For Edwards curves it uses the standard EdDSA algorithm.
1334 For ECDSA the data will be hashed using the `hashfunc` function before
1335 signing.
1336 For EdDSA the data will be hashed with the hash associated with the
1337 curve (SHA-512 for Ed25519 and SHAKE-256 for Ed448).
1339 This is the recommended method for performing signatures when hashing
1340 of data is necessary.
1342 :param data: data to be hashed and computed signature over
1343 :type data: :term:`bytes-like object`
1344 :param hashfunc: hash function to use for computing the signature,
1345 if unspecified, the default hash function selected during
1346 object initialisation will be used (see
1347 `VerifyingKey.default_hashfunc`). The object needs to implement
1348 the same interface as hashlib.sha1.
1349 Ignored with EdDSA.
1350 :type hashfunc: callable
1351 :param sigencode: function used to encode the signature.
1352 The function needs to accept three parameters: the two integers
1353 that are the signature and the order of the curve over which the
1354 signature was computed. It needs to return an encoded signature.
1355 See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
1356 as examples of such functions.
1357 Ignored with EdDSA.
1358 :type sigencode: callable
1359 :param extra_entropy: additional data that will be fed into the random
1360 number generator used in the RFC6979 process. Entirely optional.
1361 Ignored with EdDSA.
1362 :type extra_entropy: :term:`bytes-like object`
1364 :return: encoded signature over `data`
1365 :rtype: bytes or sigencode function dependent type
1366 """
1367 hashfunc = hashfunc or self.default_hashfunc
1368 data = normalise_bytes(data)
1370 if isinstance(self.curve.curve, CurveEdTw):
1371 return self.privkey.sign(data)
1373 extra_entropy = normalise_bytes(extra_entropy)
1374 digest = hashfunc(data).digest()
1376 return self.sign_digest_deterministic(
1377 digest,
1378 hashfunc=hashfunc,
1379 sigencode=sigencode,
1380 extra_entropy=extra_entropy,
1381 allow_truncate=True,
1382 )
1384 def sign_digest_deterministic(
1385 self,
1386 digest,
1387 hashfunc=None,
1388 sigencode=sigencode_string,
1389 extra_entropy=b"",
1390 allow_truncate=False,
1391 ):
1392 """
1393 Create signature for digest using the deterministic RFC6979 algorithm.
1395 `digest` should be the output of cryptographically secure hash function
1396 like SHA256 or SHA-3-256.
1398 This is the recommended method for performing signatures when no
1399 hashing of data is necessary.
1401 :param digest: hash of data that will be signed
1402 :type digest: :term:`bytes-like object`
1403 :param hashfunc: hash function to use for computing the random "k"
1404 value from RFC6979 process,
1405 if unspecified, the default hash function selected during
1406 object initialisation will be used (see
1407 :attr:`.VerifyingKey.default_hashfunc`). The object needs to
1408 implement
1409 the same interface as :func:`~hashlib.sha1` from :py:mod:`hashlib`.
1410 :type hashfunc: callable
1411 :param sigencode: function used to encode the signature.
1412 The function needs to accept three parameters: the two integers
1413 that are the signature and the order of the curve over which the
1414 signature was computed. It needs to return an encoded signature.
1415 See :func:`~ecdsa.util.sigencode_string` and
1416 :func:`~ecdsa.util.sigencode_der`
1417 as examples of such functions.
1418 :type sigencode: callable
1419 :param extra_entropy: additional data that will be fed into the random
1420 number generator used in the RFC6979 process. Entirely optional.
1421 :type extra_entropy: :term:`bytes-like object`
1422 :param bool allow_truncate: if True, the provided digest can have
1423 bigger bit-size than the order of the curve, the extra bits (at
1424 the end of the digest) will be truncated. Use it when signing
1425 SHA-384 output using NIST256p or in similar situations.
1427 :return: encoded signature for the `digest` hash
1428 :rtype: bytes or sigencode function dependent type
1429 """
1430 if isinstance(self.curve.curve, CurveEdTw):
1431 raise ValueError("Method unsupported for Edwards curves")
1432 secexp = self.privkey.secret_multiplier
1433 hashfunc = hashfunc or self.default_hashfunc
1434 digest = normalise_bytes(digest)
1435 extra_entropy = normalise_bytes(extra_entropy)
1437 def simple_r_s(r, s, order):
1438 return r, s, order
1440 retry_gen = 0
1441 while True:
1442 k = rfc6979.generate_k(
1443 self.curve.generator.order(),
1444 secexp,
1445 hashfunc,
1446 digest,
1447 retry_gen=retry_gen,
1448 extra_entropy=extra_entropy,
1449 )
1450 try:
1451 r, s, order = self.sign_digest(
1452 digest,
1453 sigencode=simple_r_s,
1454 k=k,
1455 allow_truncate=allow_truncate,
1456 )
1457 break
1458 except RSZeroError:
1459 retry_gen += 1
1461 return sigencode(r, s, order)
1463 def sign(
1464 self,
1465 data,
1466 entropy=None,
1467 hashfunc=None,
1468 sigencode=sigencode_string,
1469 k=None,
1470 allow_truncate=True,
1471 ):
1472 """
1473 Create signature over data.
1475 Uses the probabilistic ECDSA algorithm for Weierstrass curves
1476 (NIST256p, etc.) and the deterministic EdDSA algorithm for the
1477 Edwards curves (Ed25519, Ed448).
1479 This method uses the standard ECDSA algorithm that requires a
1480 cryptographically secure random number generator.
1482 It's recommended to use the :func:`~SigningKey.sign_deterministic`
1483 method instead of this one.
1485 :param data: data that will be hashed for signing
1486 :type data: :term:`bytes-like object`
1487 :param callable entropy: randomness source, :func:`os.urandom` by
1488 default. Ignored with EdDSA.
1489 :param hashfunc: hash function to use for hashing the provided
1490 ``data``.
1491 If unspecified the default hash function selected during
1492 object initialisation will be used (see
1493 :attr:`.VerifyingKey.default_hashfunc`).
1494 Should behave like :func:`~hashlib.sha1` from :py:mod:`hashlib`.
1495 The output length of the
1496 hash (in bytes) must not be longer than the length of the curve
1497 order (rounded up to the nearest byte), so using SHA256 with
1498 NIST256p is ok, but SHA256 with NIST192p is not. (In the 2**-96ish
1499 unlikely event of a hash output larger than the curve order, the
1500 hash will effectively be wrapped mod n).
1501 If you want to explicitly allow use of large hashes with small
1502 curves set the ``allow_truncate`` to ``True``.
1503 Use ``hashfunc=hashlib.sha1`` to match openssl's
1504 ``-ecdsa-with-SHA1`` mode,
1505 or ``hashfunc=hashlib.sha256`` for openssl-1.0.0's
1506 ``-ecdsa-with-SHA256``.
1507 Ignored for EdDSA
1508 :type hashfunc: callable
1509 :param sigencode: function used to encode the signature.
1510 The function needs to accept three parameters: the two integers
1511 that are the signature and the order of the curve over which the
1512 signature was computed. It needs to return an encoded signature.
1513 See :func:`~ecdsa.util.sigencode_string` and
1514 :func:`~ecdsa.util.sigencode_der`
1515 as examples of such functions.
1516 Ignored for EdDSA
1517 :type sigencode: callable
1518 :param int k: a pre-selected nonce for calculating the signature.
1519 In typical use cases, it should be set to None (the default) to
1520 allow its generation from an entropy source.
1521 Ignored for EdDSA.
1522 :param bool allow_truncate: if ``True``, the provided digest can have
1523 bigger bit-size than the order of the curve, the extra bits (at
1524 the end of the digest) will be truncated. Use it when signing
1525 SHA-384 output using NIST256p or in similar situations. True by
1526 default.
1527 Ignored for EdDSA.
1529 :raises RSZeroError: in the unlikely event when *r* parameter or
1530 *s* parameter of the created signature is equal 0, as that would
1531 leak the key. Caller should try a better entropy source, retry with
1532 different ``k``, or use the
1533 :func:`~SigningKey.sign_deterministic` in such case.
1535 :return: encoded signature of the hash of `data`
1536 :rtype: bytes or sigencode function dependent type
1537 """
1538 hashfunc = hashfunc or self.default_hashfunc
1539 data = normalise_bytes(data)
1540 if isinstance(self.curve.curve, CurveEdTw):
1541 return self.sign_deterministic(data)
1542 h = hashfunc(data).digest()
1543 return self.sign_digest(h, entropy, sigencode, k, allow_truncate)
1545 def sign_digest(
1546 self,
1547 digest,
1548 entropy=None,
1549 sigencode=sigencode_string,
1550 k=None,
1551 allow_truncate=False,
1552 ):
1553 """
1554 Create signature over digest using the probabilistic ECDSA algorithm.
1556 This method uses the standard ECDSA algorithm that requires a
1557 cryptographically secure random number generator.
1559 This method does not hash the input.
1561 It's recommended to use the
1562 :func:`~SigningKey.sign_digest_deterministic` method
1563 instead of this one.
1565 :param digest: hash value that will be signed
1566 :type digest: :term:`bytes-like object`
1567 :param callable entropy: randomness source, os.urandom by default
1568 :param sigencode: function used to encode the signature.
1569 The function needs to accept three parameters: the two integers
1570 that are the signature and the order of the curve over which the
1571 signature was computed. It needs to return an encoded signature.
1572 See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
1573 as examples of such functions.
1574 :type sigencode: callable
1575 :param int k: a pre-selected nonce for calculating the signature.
1576 In typical use cases, it should be set to None (the default) to
1577 allow its generation from an entropy source.
1578 :param bool allow_truncate: if True, the provided digest can have
1579 bigger bit-size than the order of the curve, the extra bits (at
1580 the end of the digest) will be truncated. Use it when signing
1581 SHA-384 output using NIST256p or in similar situations.
1583 :raises RSZeroError: in the unlikely event when "r" parameter or
1584 "s" parameter of the created signature is equal 0, as that would
1585 leak the key. Caller should try a better entropy source, retry with
1586 different 'k', or use the
1587 :func:`~SigningKey.sign_digest_deterministic` in such case.
1589 :return: encoded signature for the `digest` hash
1590 :rtype: bytes or sigencode function dependent type
1591 """
1592 if isinstance(self.curve.curve, CurveEdTw):
1593 raise ValueError("Method unsupported for Edwards curves")
1594 digest = normalise_bytes(digest)
1595 number = _truncate_and_convert_digest(
1596 digest,
1597 self.curve,
1598 allow_truncate,
1599 )
1600 r, s = self.sign_number(number, entropy, k)
1601 return sigencode(r, s, self.privkey.order)
1603 def sign_number(self, number, entropy=None, k=None):
1604 """
1605 Sign an integer directly.
1607 Note, this is a low level method, usually you will want to use
1608 :func:`~SigningKey.sign_deterministic` or
1609 :func:`~SigningKey.sign_digest_deterministic`.
1611 :param int number: number to sign using the probabilistic ECDSA
1612 algorithm.
1613 :param callable entropy: entropy source, os.urandom by default
1614 :param int k: pre-selected nonce for signature operation. If unset
1615 it will be selected at random using the entropy source.
1617 :raises RSZeroError: in the unlikely event when "r" parameter or
1618 "s" parameter of the created signature is equal 0, as that would
1619 leak the key. Caller should try a better entropy source, retry with
1620 different 'k', or use the
1621 :func:`~SigningKey.sign_digest_deterministic` in such case.
1623 :return: the "r" and "s" parameters of the signature
1624 :rtype: tuple of ints
1625 """
1626 if isinstance(self.curve.curve, CurveEdTw):
1627 raise ValueError("Method unsupported for Edwards curves")
1628 order = self.privkey.order
1630 if k is not None:
1631 _k = k
1632 else:
1633 _k = randrange(order, entropy)
1635 assert 1 <= _k < order
1636 sig = self.privkey.sign(number, _k)
1637 return sig.r, sig.s