Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/ecdsa/keys.py: 55%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2Primary classes for performing signing and verification operations.
3"""
5import binascii
6from hashlib import sha1
7import os
8from six import PY2
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 # Up next is an octet string containing an ECPrivateKey. Ignore
1106 # the optional "attributes" and "publicKey" fields that come after.
1107 s, _ = der.remove_octet_string(s)
1109 # Unpack the ECPrivateKey to get to the key data octet string,
1110 # and rejoin the ssleay parsing path.
1111 s, empty = der.remove_sequence(s)
1112 if empty != b"":
1113 raise der.UnexpectedDER(
1114 "trailing junk after DER privkey: %s"
1115 % binascii.hexlify(empty)
1116 )
1118 version, s = der.remove_integer(s)
1120 # The version of the ECPrivateKey must be 1.
1121 if version != 1:
1122 raise der.UnexpectedDER(
1123 "expected version '1' at start of DER privkey, got %d"
1124 % version
1125 )
1127 privkey_str, s = der.remove_octet_string(s)
1129 if not curve:
1130 tag, curve_oid_str, s = der.remove_constructed(s)
1131 if tag != 0:
1132 raise der.UnexpectedDER(
1133 "expected tag 0 in DER privkey, got %d" % tag
1134 )
1135 curve = Curve.from_der(curve_oid_str, valid_curve_encodings)
1137 # we don't actually care about the following fields
1138 #
1139 # tag, pubkey_bitstring, s = der.remove_constructed(s)
1140 # if tag != 1:
1141 # raise der.UnexpectedDER("expected tag 1 in DER privkey, got %d"
1142 # % tag)
1143 # pubkey_str = der.remove_bitstring(pubkey_bitstring, 0)
1144 # if empty != "":
1145 # raise der.UnexpectedDER("trailing junk after DER privkey "
1146 # "pubkeystr: %s"
1147 # % binascii.hexlify(empty))
1149 # our from_string method likes fixed-length privkey strings
1150 if len(privkey_str) < curve.baselen:
1151 privkey_str = (
1152 b"\x00" * (curve.baselen - len(privkey_str)) + privkey_str
1153 )
1154 return cls.from_string(privkey_str, curve, hashfunc)
1156 def to_string(self):
1157 """
1158 Convert the private key to :term:`raw encoding`.
1160 Note: while the method is named "to_string", its name comes from
1161 Python 2 days, when binary and character strings used the same type.
1162 The type used in Python 3 is `bytes`.
1164 :return: raw encoding of private key
1165 :rtype: bytes
1166 """
1167 if isinstance(self.curve.curve, CurveEdTw):
1168 return bytes(self.privkey.private_key)
1169 secexp = self.privkey.secret_multiplier
1170 s = number_to_string(secexp, self.privkey.order)
1171 return s
1173 def to_pem(
1174 self,
1175 point_encoding="uncompressed",
1176 format="ssleay",
1177 curve_parameters_encoding=None,
1178 ):
1179 """
1180 Convert the private key to the :term:`PEM` format.
1182 See :func:`~SigningKey.from_pem` method for format description.
1184 Only the named curve format is supported.
1185 The public key will be included in generated string.
1187 The PEM header will specify ``BEGIN EC PRIVATE KEY`` or
1188 ``BEGIN PRIVATE KEY``, depending on the desired format.
1190 :param str point_encoding: format to use for encoding public point
1191 :param str format: either ``ssleay`` (default) or ``pkcs8``
1192 :param str curve_parameters_encoding: format of encoded curve
1193 parameters, default depends on the curve, if the curve has
1194 an associated OID, ``named_curve`` format will be used,
1195 if no OID is associated with the curve, the fallback of
1196 ``explicit`` parameters will be used.
1198 :return: PEM encoded private key
1199 :rtype: bytes
1201 .. warning:: The PEM is encoded to US-ASCII, it needs to be
1202 re-encoded if the system is incompatible (e.g. uses UTF-16)
1203 """
1204 # TODO: "BEGIN ECPARAMETERS"
1205 assert format in ("ssleay", "pkcs8")
1206 header = "EC PRIVATE KEY" if format == "ssleay" else "PRIVATE KEY"
1207 return der.topem(
1208 self.to_der(point_encoding, format, curve_parameters_encoding),
1209 header,
1210 )
1212 def _encode_eddsa(self):
1213 """Create a PKCS#8 encoding of EdDSA keys."""
1214 ec_private_key = der.encode_octet_string(self.to_string())
1215 return der.encode_sequence(
1216 der.encode_integer(0),
1217 der.encode_sequence(der.encode_oid(*self.curve.oid)),
1218 der.encode_octet_string(ec_private_key),
1219 )
1221 def to_der(
1222 self,
1223 point_encoding="uncompressed",
1224 format="ssleay",
1225 curve_parameters_encoding=None,
1226 ):
1227 """
1228 Convert the private key to the :term:`DER` format.
1230 See :func:`~SigningKey.from_der` method for format specification.
1232 Only the named curve format is supported.
1233 The public key will be included in the generated string.
1235 :param str point_encoding: format to use for encoding public point
1236 Ignored for EdDSA
1237 :param str format: either ``ssleay`` (default) or ``pkcs8``.
1238 EdDSA keys require ``pkcs8``.
1239 :param str curve_parameters_encoding: format of encoded curve
1240 parameters, default depends on the curve, if the curve has
1241 an associated OID, ``named_curve`` format will be used,
1242 if no OID is associated with the curve, the fallback of
1243 ``explicit`` parameters will be used.
1244 Ignored for EdDSA.
1246 :return: DER encoded private key
1247 :rtype: bytes
1248 """
1249 # SEQ([int(1), octetstring(privkey),cont[0], oid(secp224r1),
1250 # cont[1],bitstring])
1251 if point_encoding == "raw":
1252 raise ValueError("raw encoding not allowed in DER")
1253 assert format in ("ssleay", "pkcs8")
1254 if isinstance(self.curve.curve, CurveEdTw):
1255 if format != "pkcs8":
1256 raise ValueError("Only PKCS#8 format supported for EdDSA keys")
1257 return self._encode_eddsa()
1258 encoded_vk = self.get_verifying_key().to_string(point_encoding)
1259 priv_key_elems = [
1260 der.encode_integer(1),
1261 der.encode_octet_string(self.to_string()),
1262 ]
1263 if format == "ssleay":
1264 priv_key_elems.append(
1265 der.encode_constructed(
1266 0, self.curve.to_der(curve_parameters_encoding)
1267 )
1268 )
1269 # the 0 in encode_bitstring specifies the number of unused bits
1270 # in the `encoded_vk` string
1271 priv_key_elems.append(
1272 der.encode_constructed(1, der.encode_bitstring(encoded_vk, 0))
1273 )
1274 ec_private_key = der.encode_sequence(*priv_key_elems)
1276 if format == "ssleay":
1277 return ec_private_key
1278 else:
1279 return der.encode_sequence(
1280 # version = 1 means the public key is not present in the
1281 # top-level structure.
1282 der.encode_integer(1),
1283 der.encode_sequence(
1284 der.encode_oid(*oid_ecPublicKey),
1285 self.curve.to_der(curve_parameters_encoding),
1286 ),
1287 der.encode_octet_string(ec_private_key),
1288 )
1290 def to_ssh(self):
1291 """
1292 Convert the private key to the SSH format.
1294 :return: SSH encoded private key
1295 :rtype: bytes
1296 """
1297 return ssh.serialize_private(
1298 self.curve.name,
1299 self.verifying_key.to_string(),
1300 self.to_string(),
1301 )
1303 def get_verifying_key(self):
1304 """
1305 Return the VerifyingKey associated with this private key.
1307 Equivalent to reading the `verifying_key` field of an instance.
1309 :return: a public key that can be used to verify the signatures made
1310 with this SigningKey
1311 :rtype: VerifyingKey
1312 """
1313 return self.verifying_key
1315 def sign_deterministic(
1316 self,
1317 data,
1318 hashfunc=None,
1319 sigencode=sigencode_string,
1320 extra_entropy=b"",
1321 ):
1322 """
1323 Create signature over data.
1325 For Weierstrass curves it uses the deterministic RFC6979 algorithm.
1326 For Edwards curves it uses the standard EdDSA algorithm.
1328 For ECDSA the data will be hashed using the `hashfunc` function before
1329 signing.
1330 For EdDSA the data will be hashed with the hash associated with the
1331 curve (SHA-512 for Ed25519 and SHAKE-256 for Ed448).
1333 This is the recommended method for performing signatures when hashing
1334 of data is necessary.
1336 :param data: data to be hashed and computed signature over
1337 :type data: :term:`bytes-like object`
1338 :param hashfunc: hash function to use for computing the signature,
1339 if unspecified, the default hash function selected during
1340 object initialisation will be used (see
1341 `VerifyingKey.default_hashfunc`). The object needs to implement
1342 the same interface as hashlib.sha1.
1343 Ignored with EdDSA.
1344 :type hashfunc: callable
1345 :param sigencode: function used to encode the signature.
1346 The function needs to accept three parameters: the two integers
1347 that are the signature and the order of the curve over which the
1348 signature was computed. It needs to return an encoded signature.
1349 See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
1350 as examples of such functions.
1351 Ignored with EdDSA.
1352 :type sigencode: callable
1353 :param extra_entropy: additional data that will be fed into the random
1354 number generator used in the RFC6979 process. Entirely optional.
1355 Ignored with EdDSA.
1356 :type extra_entropy: :term:`bytes-like object`
1358 :return: encoded signature over `data`
1359 :rtype: bytes or sigencode function dependent type
1360 """
1361 hashfunc = hashfunc or self.default_hashfunc
1362 data = normalise_bytes(data)
1364 if isinstance(self.curve.curve, CurveEdTw):
1365 return self.privkey.sign(data)
1367 extra_entropy = normalise_bytes(extra_entropy)
1368 digest = hashfunc(data).digest()
1370 return self.sign_digest_deterministic(
1371 digest,
1372 hashfunc=hashfunc,
1373 sigencode=sigencode,
1374 extra_entropy=extra_entropy,
1375 allow_truncate=True,
1376 )
1378 def sign_digest_deterministic(
1379 self,
1380 digest,
1381 hashfunc=None,
1382 sigencode=sigencode_string,
1383 extra_entropy=b"",
1384 allow_truncate=False,
1385 ):
1386 """
1387 Create signature for digest using the deterministic RFC6979 algorithm.
1389 `digest` should be the output of cryptographically secure hash function
1390 like SHA256 or SHA-3-256.
1392 This is the recommended method for performing signatures when no
1393 hashing of data is necessary.
1395 :param digest: hash of data that will be signed
1396 :type digest: :term:`bytes-like object`
1397 :param hashfunc: hash function to use for computing the random "k"
1398 value from RFC6979 process,
1399 if unspecified, the default hash function selected during
1400 object initialisation will be used (see
1401 :attr:`.VerifyingKey.default_hashfunc`). The object needs to
1402 implement
1403 the same interface as :func:`~hashlib.sha1` from :py:mod:`hashlib`.
1404 :type hashfunc: callable
1405 :param sigencode: function used to encode the signature.
1406 The function needs to accept three parameters: the two integers
1407 that are the signature and the order of the curve over which the
1408 signature was computed. It needs to return an encoded signature.
1409 See :func:`~ecdsa.util.sigencode_string` and
1410 :func:`~ecdsa.util.sigencode_der`
1411 as examples of such functions.
1412 :type sigencode: callable
1413 :param extra_entropy: additional data that will be fed into the random
1414 number generator used in the RFC6979 process. Entirely optional.
1415 :type extra_entropy: :term:`bytes-like object`
1416 :param bool allow_truncate: if True, the provided digest can have
1417 bigger bit-size than the order of the curve, the extra bits (at
1418 the end of the digest) will be truncated. Use it when signing
1419 SHA-384 output using NIST256p or in similar situations.
1421 :return: encoded signature for the `digest` hash
1422 :rtype: bytes or sigencode function dependent type
1423 """
1424 if isinstance(self.curve.curve, CurveEdTw):
1425 raise ValueError("Method unsupported for Edwards curves")
1426 secexp = self.privkey.secret_multiplier
1427 hashfunc = hashfunc or self.default_hashfunc
1428 digest = normalise_bytes(digest)
1429 extra_entropy = normalise_bytes(extra_entropy)
1431 def simple_r_s(r, s, order):
1432 return r, s, order
1434 retry_gen = 0
1435 while True:
1436 k = rfc6979.generate_k(
1437 self.curve.generator.order(),
1438 secexp,
1439 hashfunc,
1440 digest,
1441 retry_gen=retry_gen,
1442 extra_entropy=extra_entropy,
1443 )
1444 try:
1445 r, s, order = self.sign_digest(
1446 digest,
1447 sigencode=simple_r_s,
1448 k=k,
1449 allow_truncate=allow_truncate,
1450 )
1451 break
1452 except RSZeroError:
1453 retry_gen += 1
1455 return sigencode(r, s, order)
1457 def sign(
1458 self,
1459 data,
1460 entropy=None,
1461 hashfunc=None,
1462 sigencode=sigencode_string,
1463 k=None,
1464 allow_truncate=True,
1465 ):
1466 """
1467 Create signature over data.
1469 Uses the probabilistic ECDSA algorithm for Weierstrass curves
1470 (NIST256p, etc.) and the deterministic EdDSA algorithm for the
1471 Edwards curves (Ed25519, Ed448).
1473 This method uses the standard ECDSA algorithm that requires a
1474 cryptographically secure random number generator.
1476 It's recommended to use the :func:`~SigningKey.sign_deterministic`
1477 method instead of this one.
1479 :param data: data that will be hashed for signing
1480 :type data: :term:`bytes-like object`
1481 :param callable entropy: randomness source, :func:`os.urandom` by
1482 default. Ignored with EdDSA.
1483 :param hashfunc: hash function to use for hashing the provided
1484 ``data``.
1485 If unspecified the default hash function selected during
1486 object initialisation will be used (see
1487 :attr:`.VerifyingKey.default_hashfunc`).
1488 Should behave like :func:`~hashlib.sha1` from :py:mod:`hashlib`.
1489 The output length of the
1490 hash (in bytes) must not be longer than the length of the curve
1491 order (rounded up to the nearest byte), so using SHA256 with
1492 NIST256p is ok, but SHA256 with NIST192p is not. (In the 2**-96ish
1493 unlikely event of a hash output larger than the curve order, the
1494 hash will effectively be wrapped mod n).
1495 If you want to explicitly allow use of large hashes with small
1496 curves set the ``allow_truncate`` to ``True``.
1497 Use ``hashfunc=hashlib.sha1`` to match openssl's
1498 ``-ecdsa-with-SHA1`` mode,
1499 or ``hashfunc=hashlib.sha256`` for openssl-1.0.0's
1500 ``-ecdsa-with-SHA256``.
1501 Ignored for EdDSA
1502 :type hashfunc: callable
1503 :param sigencode: function used to encode the signature.
1504 The function needs to accept three parameters: the two integers
1505 that are the signature and the order of the curve over which the
1506 signature was computed. It needs to return an encoded signature.
1507 See :func:`~ecdsa.util.sigencode_string` and
1508 :func:`~ecdsa.util.sigencode_der`
1509 as examples of such functions.
1510 Ignored for EdDSA
1511 :type sigencode: callable
1512 :param int k: a pre-selected nonce for calculating the signature.
1513 In typical use cases, it should be set to None (the default) to
1514 allow its generation from an entropy source.
1515 Ignored for EdDSA.
1516 :param bool allow_truncate: if ``True``, the provided digest can have
1517 bigger bit-size than the order of the curve, the extra bits (at
1518 the end of the digest) will be truncated. Use it when signing
1519 SHA-384 output using NIST256p or in similar situations. True by
1520 default.
1521 Ignored for EdDSA.
1523 :raises RSZeroError: in the unlikely event when *r* parameter or
1524 *s* parameter of the created signature is equal 0, as that would
1525 leak the key. Caller should try a better entropy source, retry with
1526 different ``k``, or use the
1527 :func:`~SigningKey.sign_deterministic` in such case.
1529 :return: encoded signature of the hash of `data`
1530 :rtype: bytes or sigencode function dependent type
1531 """
1532 hashfunc = hashfunc or self.default_hashfunc
1533 data = normalise_bytes(data)
1534 if isinstance(self.curve.curve, CurveEdTw):
1535 return self.sign_deterministic(data)
1536 h = hashfunc(data).digest()
1537 return self.sign_digest(h, entropy, sigencode, k, allow_truncate)
1539 def sign_digest(
1540 self,
1541 digest,
1542 entropy=None,
1543 sigencode=sigencode_string,
1544 k=None,
1545 allow_truncate=False,
1546 ):
1547 """
1548 Create signature over digest using the probabilistic ECDSA algorithm.
1550 This method uses the standard ECDSA algorithm that requires a
1551 cryptographically secure random number generator.
1553 This method does not hash the input.
1555 It's recommended to use the
1556 :func:`~SigningKey.sign_digest_deterministic` method
1557 instead of this one.
1559 :param digest: hash value that will be signed
1560 :type digest: :term:`bytes-like object`
1561 :param callable entropy: randomness source, os.urandom by default
1562 :param sigencode: function used to encode the signature.
1563 The function needs to accept three parameters: the two integers
1564 that are the signature and the order of the curve over which the
1565 signature was computed. It needs to return an encoded signature.
1566 See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
1567 as examples of such functions.
1568 :type sigencode: callable
1569 :param int k: a pre-selected nonce for calculating the signature.
1570 In typical use cases, it should be set to None (the default) to
1571 allow its generation from an entropy source.
1572 :param bool allow_truncate: if True, the provided digest can have
1573 bigger bit-size than the order of the curve, the extra bits (at
1574 the end of the digest) will be truncated. Use it when signing
1575 SHA-384 output using NIST256p or in similar situations.
1577 :raises RSZeroError: in the unlikely event when "r" parameter or
1578 "s" parameter of the created signature is equal 0, as that would
1579 leak the key. Caller should try a better entropy source, retry with
1580 different 'k', or use the
1581 :func:`~SigningKey.sign_digest_deterministic` in such case.
1583 :return: encoded signature for the `digest` hash
1584 :rtype: bytes or sigencode function dependent type
1585 """
1586 if isinstance(self.curve.curve, CurveEdTw):
1587 raise ValueError("Method unsupported for Edwards curves")
1588 digest = normalise_bytes(digest)
1589 number = _truncate_and_convert_digest(
1590 digest,
1591 self.curve,
1592 allow_truncate,
1593 )
1594 r, s = self.sign_number(number, entropy, k)
1595 return sigencode(r, s, self.privkey.order)
1597 def sign_number(self, number, entropy=None, k=None):
1598 """
1599 Sign an integer directly.
1601 Note, this is a low level method, usually you will want to use
1602 :func:`~SigningKey.sign_deterministic` or
1603 :func:`~SigningKey.sign_digest_deterministic`.
1605 :param int number: number to sign using the probabilistic ECDSA
1606 algorithm.
1607 :param callable entropy: entropy source, os.urandom by default
1608 :param int k: pre-selected nonce for signature operation. If unset
1609 it will be selected at random using the entropy source.
1611 :raises RSZeroError: in the unlikely event when "r" parameter or
1612 "s" parameter of the created signature is equal 0, as that would
1613 leak the key. Caller should try a better entropy source, retry with
1614 different 'k', or use the
1615 :func:`~SigningKey.sign_digest_deterministic` in such case.
1617 :return: the "r" and "s" parameters of the signature
1618 :rtype: tuple of ints
1619 """
1620 if isinstance(self.curve.curve, CurveEdTw):
1621 raise ValueError("Method unsupported for Edwards curves")
1622 order = self.privkey.order
1624 if k is not None:
1625 _k = k
1626 else:
1627 _k = randrange(order, entropy)
1629 assert 1 <= _k < order
1630 sig = self.privkey.sign(number, _k)
1631 return sig.r, sig.s