Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/ecdsa/keys.py: 55%
378 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 07:19 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 07:19 +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
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 verify(
618 self,
619 signature,
620 data,
621 hashfunc=None,
622 sigdecode=sigdecode_string,
623 allow_truncate=True,
624 ):
625 """
626 Verify a signature made over provided data.
628 Will hash `data` to verify the signature.
630 By default expects signature in :term:`raw encoding`. Can also be used
631 to verify signatures in ASN.1 DER encoding by using
632 :func:`ecdsa.util.sigdecode_der`
633 as the `sigdecode` parameter.
635 :param signature: encoding of the signature
636 :type signature: sigdecode method dependent
637 :param data: data signed by the `signature`, will be hashed using
638 `hashfunc`, if specified, or default hash function
639 :type data: :term:`bytes-like object`
640 :param hashfunc: The default hash function that will be used for
641 verification, needs to implement the same interface as hashlib.sha1
642 :type hashfunc: callable
643 :param sigdecode: Callable to define the way the signature needs to
644 be decoded to an object, needs to handle `signature` as the
645 first parameter, the curve order (an int) as the second and return
646 a tuple with two integers, "r" as the first one and "s" as the
647 second one. See :func:`ecdsa.util.sigdecode_string` and
648 :func:`ecdsa.util.sigdecode_der` for examples.
649 :type sigdecode: callable
650 :param bool allow_truncate: if True, the provided digest can have
651 bigger bit-size than the order of the curve, the extra bits (at
652 the end of the digest) will be truncated. Use it when verifying
653 SHA-384 output using NIST256p or in similar situations. Defaults to
654 True.
656 :raises BadSignatureError: if the signature is invalid or malformed
658 :return: True if the verification was successful
659 :rtype: bool
660 """
661 # signature doesn't have to be a bytes-like-object so don't normalise
662 # it, the decoders will do that
663 data = normalise_bytes(data)
664 if isinstance(self.curve.curve, CurveEdTw):
665 signature = normalise_bytes(signature)
666 try:
667 return self.pubkey.verify(data, signature)
668 except (ValueError, MalformedPointError) as e:
669 raise BadSignatureError("Signature verification failed", e)
671 hashfunc = hashfunc or self.default_hashfunc
672 digest = hashfunc(data).digest()
673 return self.verify_digest(signature, digest, sigdecode, allow_truncate)
675 def verify_digest(
676 self,
677 signature,
678 digest,
679 sigdecode=sigdecode_string,
680 allow_truncate=False,
681 ):
682 """
683 Verify a signature made over provided hash value.
685 By default expects signature in :term:`raw encoding`. Can also be used
686 to verify signatures in ASN.1 DER encoding by using
687 :func:`ecdsa.util.sigdecode_der`
688 as the `sigdecode` parameter.
690 :param signature: encoding of the signature
691 :type signature: sigdecode method dependent
692 :param digest: raw hash value that the signature authenticates.
693 :type digest: :term:`bytes-like object`
694 :param sigdecode: Callable to define the way the signature needs to
695 be decoded to an object, needs to handle `signature` as the
696 first parameter, the curve order (an int) as the second and return
697 a tuple with two integers, "r" as the first one and "s" as the
698 second one. See :func:`ecdsa.util.sigdecode_string` and
699 :func:`ecdsa.util.sigdecode_der` for examples.
700 :type sigdecode: callable
701 :param bool allow_truncate: if True, the provided digest can have
702 bigger bit-size than the order of the curve, the extra bits (at
703 the end of the digest) will be truncated. Use it when verifying
704 SHA-384 output using NIST256p or in similar situations.
706 :raises BadSignatureError: if the signature is invalid or malformed
707 :raises BadDigestError: if the provided digest is too big for the curve
708 associated with this VerifyingKey and allow_truncate was not set
710 :return: True if the verification was successful
711 :rtype: bool
712 """
713 # signature doesn't have to be a bytes-like-object so don't normalise
714 # it, the decoders will do that
715 digest = normalise_bytes(digest)
716 number = _truncate_and_convert_digest(
717 digest,
718 self.curve,
719 allow_truncate,
720 )
722 try:
723 r, s = sigdecode(signature, self.pubkey.order)
724 except (der.UnexpectedDER, MalformedSignature) as e:
725 raise BadSignatureError("Malformed formatting of signature", e)
726 sig = ecdsa.Signature(r, s)
727 if self.pubkey.verifies(number, sig):
728 return True
729 raise BadSignatureError("Signature verification failed")
732class SigningKey(object):
733 """
734 Class for handling keys that can create signatures (private keys).
736 :ivar `~ecdsa.curves.Curve` curve: The Curve over which all the
737 cryptographic operations will take place
738 :ivar default_hashfunc: the function that will be used for hashing the
739 data. Should implement the same API as :py:class:`hashlib.sha1`
740 :ivar int baselen: the length of a :term:`raw encoding` of private key
741 :ivar `~ecdsa.keys.VerifyingKey` verifying_key: the public key
742 associated with this private key
743 :ivar `~ecdsa.ecdsa.Private_key` privkey: the actual private key
744 """
746 def __init__(self, _error__please_use_generate=None):
747 """Unsupported, please use one of the classmethods to initialise."""
748 if not _error__please_use_generate:
749 raise TypeError("Please use SigningKey.generate() to construct me")
750 self.curve = None
751 self.default_hashfunc = None
752 self.baselen = None
753 self.verifying_key = None
754 self.privkey = None
756 def __eq__(self, other):
757 """Return True if the points are identical, False otherwise."""
758 if isinstance(other, SigningKey):
759 return (
760 self.curve == other.curve
761 and self.verifying_key == other.verifying_key
762 and self.privkey == other.privkey
763 )
764 return NotImplemented
766 def __ne__(self, other):
767 """Return False if the points are identical, True otherwise."""
768 return not self == other
770 @classmethod
771 def _twisted_edwards_keygen(cls, curve, entropy):
772 """Generate a private key on a Twisted Edwards curve."""
773 if not entropy:
774 entropy = os.urandom
775 random = entropy(curve.baselen)
776 private_key = eddsa.PrivateKey(curve.generator, random)
777 public_key = private_key.public_key()
779 verifying_key = VerifyingKey.from_string(
780 public_key.public_key(), curve
781 )
783 self = cls(_error__please_use_generate=True)
784 self.curve = curve
785 self.default_hashfunc = None
786 self.baselen = curve.baselen
787 self.privkey = private_key
788 self.verifying_key = verifying_key
789 return self
791 @classmethod
792 def _weierstrass_keygen(cls, curve, entropy, hashfunc):
793 """Generate a private key on a Weierstrass curve."""
794 secexp = randrange(curve.order, entropy)
795 return cls.from_secret_exponent(secexp, curve, hashfunc)
797 @classmethod
798 def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):
799 """
800 Generate a random private key.
802 :param curve: The curve on which the point needs to reside, defaults
803 to NIST192p
804 :type curve: ~ecdsa.curves.Curve
805 :param entropy: Source of randomness for generating the private keys,
806 should provide cryptographically secure random numbers if the keys
807 need to be secure. Uses os.urandom() by default.
808 :type entropy: callable
809 :param hashfunc: The default hash function that will be used for
810 signing, needs to implement the same interface
811 as hashlib.sha1
812 :type hashfunc: callable
814 :return: Initialised SigningKey object
815 :rtype: SigningKey
816 """
817 if isinstance(curve.curve, CurveEdTw):
818 return cls._twisted_edwards_keygen(curve, entropy)
819 return cls._weierstrass_keygen(curve, entropy, hashfunc)
821 @classmethod
822 def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1):
823 """
824 Create a private key from a random integer.
826 Note: it's a low level method, it's recommended to use the
827 :func:`~SigningKey.generate` method to create private keys.
829 :param int secexp: secret multiplier (the actual private key in ECDSA).
830 Needs to be an integer between 1 and the curve order.
831 :param curve: The curve on which the point needs to reside
832 :type curve: ~ecdsa.curves.Curve
833 :param hashfunc: The default hash function that will be used for
834 signing, needs to implement the same interface
835 as hashlib.sha1
836 :type hashfunc: callable
838 :raises MalformedPointError: when the provided secexp is too large
839 or too small for the curve selected
840 :raises RuntimeError: if the generation of public key from private
841 key failed
843 :return: Initialised SigningKey object
844 :rtype: SigningKey
845 """
846 if isinstance(curve.curve, CurveEdTw):
847 raise ValueError(
848 "Edwards keys don't support setting the secret scalar "
849 "(exponent) directly"
850 )
851 self = cls(_error__please_use_generate=True)
852 self.curve = curve
853 self.default_hashfunc = hashfunc
854 self.baselen = curve.baselen
855 n = curve.order
856 if not 1 <= secexp < n:
857 raise MalformedPointError(
858 "Invalid value for secexp, expected integer "
859 "between 1 and {0}".format(n)
860 )
861 pubkey_point = curve.generator * secexp
862 if hasattr(pubkey_point, "scale"):
863 pubkey_point = pubkey_point.scale()
864 self.verifying_key = VerifyingKey.from_public_point(
865 pubkey_point, curve, hashfunc, False
866 )
867 pubkey = self.verifying_key.pubkey
868 self.privkey = ecdsa.Private_key(pubkey, secexp)
869 self.privkey.order = n
870 return self
872 @classmethod
873 def from_string(cls, string, curve=NIST192p, hashfunc=sha1):
874 """
875 Decode the private key from :term:`raw encoding`.
877 Note: the name of this method is a misnomer coming from days of
878 Python 2, when binary strings and character strings shared a type.
879 In Python 3, the expected type is `bytes`.
881 :param string: the raw encoding of the private key
882 :type string: :term:`bytes-like object`
883 :param curve: The curve on which the point needs to reside
884 :type curve: ~ecdsa.curves.Curve
885 :param hashfunc: The default hash function that will be used for
886 signing, needs to implement the same interface
887 as hashlib.sha1
888 :type hashfunc: callable
890 :raises MalformedPointError: if the length of encoding doesn't match
891 the provided curve or the encoded values is too large
892 :raises RuntimeError: if the generation of public key from private
893 key failed
895 :return: Initialised SigningKey object
896 :rtype: SigningKey
897 """
898 string = normalise_bytes(string)
900 if len(string) != curve.baselen:
901 raise MalformedPointError(
902 "Invalid length of private key, received {0}, "
903 "expected {1}".format(len(string), curve.baselen)
904 )
905 if isinstance(curve.curve, CurveEdTw):
906 self = cls(_error__please_use_generate=True)
907 self.curve = curve
908 self.default_hashfunc = None # Ignored for EdDSA
909 self.baselen = curve.baselen
910 self.privkey = eddsa.PrivateKey(curve.generator, string)
911 self.verifying_key = VerifyingKey.from_string(
912 self.privkey.public_key().public_key(), curve
913 )
914 return self
915 secexp = string_to_number(string)
916 return cls.from_secret_exponent(secexp, curve, hashfunc)
918 @classmethod
919 def from_pem(cls, string, hashfunc=sha1, valid_curve_encodings=None):
920 """
921 Initialise from key stored in :term:`PEM` format.
923 The PEM formats supported are the un-encrypted RFC5915
924 (the ssleay format) supported by OpenSSL, and the more common
925 un-encrypted RFC5958 (the PKCS #8 format).
927 The legacy format files have the header with the string
928 ``BEGIN EC PRIVATE KEY``.
929 PKCS#8 files have the header ``BEGIN PRIVATE KEY``.
930 Encrypted files (ones that include the string
931 ``Proc-Type: 4,ENCRYPTED``
932 right after the PEM header) are not supported.
934 See :func:`~SigningKey.from_der` for ASN.1 syntax of the objects in
935 this files.
937 :param string: text with PEM-encoded private ECDSA key
938 :type string: str
939 :param valid_curve_encodings: list of allowed encoding formats
940 for curve parameters. By default (``None``) all are supported:
941 ``named_curve`` and ``explicit``.
942 :type valid_curve_encodings: :term:`set-like object`
945 :raises MalformedPointError: if the length of encoding doesn't match
946 the provided curve or the encoded values is too large
947 :raises RuntimeError: if the generation of public key from private
948 key failed
949 :raises UnexpectedDER: if the encoding of the PEM file is incorrect
951 :return: Initialised SigningKey object
952 :rtype: SigningKey
953 """
954 if not PY2 and isinstance(string, str): # pragma: no branch
955 string = string.encode()
957 # The privkey pem may have multiple sections, commonly it also has
958 # "EC PARAMETERS", we need just "EC PRIVATE KEY". PKCS#8 should not
959 # have the "EC PARAMETERS" section; it's just "PRIVATE KEY".
960 private_key_index = string.find(b"-----BEGIN EC PRIVATE KEY-----")
961 if private_key_index == -1:
962 private_key_index = string.index(b"-----BEGIN PRIVATE KEY-----")
964 return cls.from_der(
965 der.unpem(string[private_key_index:]),
966 hashfunc,
967 valid_curve_encodings,
968 )
970 @classmethod
971 def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):
972 """
973 Initialise from key stored in :term:`DER` format.
975 The DER formats supported are the un-encrypted RFC5915
976 (the ssleay format) supported by OpenSSL, and the more common
977 un-encrypted RFC5958 (the PKCS #8 format).
979 Both formats contain an ASN.1 object following the syntax specified
980 in RFC5915::
982 ECPrivateKey ::= SEQUENCE {
983 version INTEGER { ecPrivkeyVer1(1) }} (ecPrivkeyVer1),
984 privateKey OCTET STRING,
985 parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
986 publicKey [1] BIT STRING OPTIONAL
987 }
989 `publicKey` field is ignored completely (errors, if any, in it will
990 be undetected).
992 Two formats are supported for the `parameters` field: the named
993 curve and the explicit encoding of curve parameters.
994 In the legacy ssleay format, this implementation requires the optional
995 `parameters` field to get the curve name. In PKCS #8 format, the curve
996 is part of the PrivateKeyAlgorithmIdentifier.
998 The PKCS #8 format includes an ECPrivateKey object as the `privateKey`
999 field within a larger structure::
1001 OneAsymmetricKey ::= SEQUENCE {
1002 version Version,
1003 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1004 privateKey PrivateKey,
1005 attributes [0] Attributes OPTIONAL,
1006 ...,
1007 [[2: publicKey [1] PublicKey OPTIONAL ]],
1008 ...
1009 }
1011 The `attributes` and `publicKey` fields are completely ignored; errors
1012 in them will not be detected.
1014 :param string: binary string with DER-encoded private ECDSA key
1015 :type string: :term:`bytes-like object`
1016 :param valid_curve_encodings: list of allowed encoding formats
1017 for curve parameters. By default (``None``) all are supported:
1018 ``named_curve`` and ``explicit``.
1019 Ignored for EdDSA.
1020 :type valid_curve_encodings: :term:`set-like object`
1022 :raises MalformedPointError: if the length of encoding doesn't match
1023 the provided curve or the encoded values is too large
1024 :raises RuntimeError: if the generation of public key from private
1025 key failed
1026 :raises UnexpectedDER: if the encoding of the DER file is incorrect
1028 :return: Initialised SigningKey object
1029 :rtype: SigningKey
1030 """
1031 s = normalise_bytes(string)
1032 curve = None
1034 s, empty = der.remove_sequence(s)
1035 if empty != b(""):
1036 raise der.UnexpectedDER(
1037 "trailing junk after DER privkey: %s" % binascii.hexlify(empty)
1038 )
1040 version, s = der.remove_integer(s)
1042 # At this point, PKCS #8 has a sequence containing the algorithm
1043 # identifier and the curve identifier. The ssleay format instead has
1044 # an octet string containing the key data, so this is how we can
1045 # distinguish the two formats.
1046 if der.is_sequence(s):
1047 if version not in (0, 1):
1048 raise der.UnexpectedDER(
1049 "expected version '0' or '1' at start of privkey, got %d"
1050 % version
1051 )
1053 sequence, s = der.remove_sequence(s)
1054 algorithm_oid, algorithm_identifier = der.remove_object(sequence)
1056 if algorithm_oid in (Ed25519.oid, Ed448.oid):
1057 if algorithm_identifier:
1058 raise der.UnexpectedDER(
1059 "Non NULL parameters for a EdDSA key"
1060 )
1061 key_str_der, s = der.remove_octet_string(s)
1063 # As RFC5958 describe, there are may be optional Attributes
1064 # and Publickey. Don't raise error if something after
1065 # Privatekey
1067 # TODO parse attributes or validate publickey
1068 # if s:
1069 # raise der.UnexpectedDER(
1070 # "trailing junk inside the privateKey"
1071 # )
1072 key_str, s = der.remove_octet_string(key_str_der)
1073 if s:
1074 raise der.UnexpectedDER(
1075 "trailing junk after the encoded private key"
1076 )
1078 if algorithm_oid == Ed25519.oid:
1079 curve = Ed25519
1080 else:
1081 assert algorithm_oid == Ed448.oid
1082 curve = Ed448
1084 return cls.from_string(key_str, curve, None)
1086 if algorithm_oid not in (oid_ecPublicKey, oid_ecDH, oid_ecMQV):
1087 raise der.UnexpectedDER(
1088 "unexpected algorithm identifier '%s'" % (algorithm_oid,)
1089 )
1091 curve = Curve.from_der(algorithm_identifier, valid_curve_encodings)
1093 if empty != b"":
1094 raise der.UnexpectedDER(
1095 "unexpected data after algorithm identifier: %s"
1096 % binascii.hexlify(empty)
1097 )
1099 # Up next is an octet string containing an ECPrivateKey. Ignore
1100 # the optional "attributes" and "publicKey" fields that come after.
1101 s, _ = der.remove_octet_string(s)
1103 # Unpack the ECPrivateKey to get to the key data octet string,
1104 # and rejoin the ssleay parsing path.
1105 s, empty = der.remove_sequence(s)
1106 if empty != b(""):
1107 raise der.UnexpectedDER(
1108 "trailing junk after DER privkey: %s"
1109 % binascii.hexlify(empty)
1110 )
1112 version, s = der.remove_integer(s)
1114 # The version of the ECPrivateKey must be 1.
1115 if version != 1:
1116 raise der.UnexpectedDER(
1117 "expected version '1' at start of DER privkey, got %d"
1118 % version
1119 )
1121 privkey_str, s = der.remove_octet_string(s)
1123 if not curve:
1124 tag, curve_oid_str, s = der.remove_constructed(s)
1125 if tag != 0:
1126 raise der.UnexpectedDER(
1127 "expected tag 0 in DER privkey, got %d" % tag
1128 )
1129 curve = Curve.from_der(curve_oid_str, valid_curve_encodings)
1131 # we don't actually care about the following fields
1132 #
1133 # tag, pubkey_bitstring, s = der.remove_constructed(s)
1134 # if tag != 1:
1135 # raise der.UnexpectedDER("expected tag 1 in DER privkey, got %d"
1136 # % tag)
1137 # pubkey_str = der.remove_bitstring(pubkey_bitstring, 0)
1138 # if empty != "":
1139 # raise der.UnexpectedDER("trailing junk after DER privkey "
1140 # "pubkeystr: %s"
1141 # % binascii.hexlify(empty))
1143 # our from_string method likes fixed-length privkey strings
1144 if len(privkey_str) < curve.baselen:
1145 privkey_str = (
1146 b("\x00") * (curve.baselen - len(privkey_str)) + privkey_str
1147 )
1148 return cls.from_string(privkey_str, curve, hashfunc)
1150 def to_string(self):
1151 """
1152 Convert the private key to :term:`raw encoding`.
1154 Note: while the method is named "to_string", its name comes from
1155 Python 2 days, when binary and character strings used the same type.
1156 The type used in Python 3 is `bytes`.
1158 :return: raw encoding of private key
1159 :rtype: bytes
1160 """
1161 if isinstance(self.curve.curve, CurveEdTw):
1162 return bytes(self.privkey.private_key)
1163 secexp = self.privkey.secret_multiplier
1164 s = number_to_string(secexp, self.privkey.order)
1165 return s
1167 def to_pem(
1168 self,
1169 point_encoding="uncompressed",
1170 format="ssleay",
1171 curve_parameters_encoding=None,
1172 ):
1173 """
1174 Convert the private key to the :term:`PEM` format.
1176 See :func:`~SigningKey.from_pem` method for format description.
1178 Only the named curve format is supported.
1179 The public key will be included in generated string.
1181 The PEM header will specify ``BEGIN EC PRIVATE KEY`` or
1182 ``BEGIN PRIVATE KEY``, depending on the desired format.
1184 :param str point_encoding: format to use for encoding public point
1185 :param str format: either ``ssleay`` (default) or ``pkcs8``
1186 :param str curve_parameters_encoding: format of encoded curve
1187 parameters, default depends on the curve, if the curve has
1188 an associated OID, ``named_curve`` format will be used,
1189 if no OID is associated with the curve, the fallback of
1190 ``explicit`` parameters will be used.
1192 :return: PEM encoded private key
1193 :rtype: bytes
1195 .. warning:: The PEM is encoded to US-ASCII, it needs to be
1196 re-encoded if the system is incompatible (e.g. uses UTF-16)
1197 """
1198 # TODO: "BEGIN ECPARAMETERS"
1199 assert format in ("ssleay", "pkcs8")
1200 header = "EC PRIVATE KEY" if format == "ssleay" else "PRIVATE KEY"
1201 return der.topem(
1202 self.to_der(point_encoding, format, curve_parameters_encoding),
1203 header,
1204 )
1206 def _encode_eddsa(self):
1207 """Create a PKCS#8 encoding of EdDSA keys."""
1208 ec_private_key = der.encode_octet_string(self.to_string())
1209 return der.encode_sequence(
1210 der.encode_integer(0),
1211 der.encode_sequence(der.encode_oid(*self.curve.oid)),
1212 der.encode_octet_string(ec_private_key),
1213 )
1215 def to_der(
1216 self,
1217 point_encoding="uncompressed",
1218 format="ssleay",
1219 curve_parameters_encoding=None,
1220 ):
1221 """
1222 Convert the private key to the :term:`DER` format.
1224 See :func:`~SigningKey.from_der` method for format specification.
1226 Only the named curve format is supported.
1227 The public key will be included in the generated string.
1229 :param str point_encoding: format to use for encoding public point
1230 Ignored for EdDSA
1231 :param str format: either ``ssleay`` (default) or ``pkcs8``.
1232 EdDSA keys require ``pkcs8``.
1233 :param str curve_parameters_encoding: format of encoded curve
1234 parameters, default depends on the curve, if the curve has
1235 an associated OID, ``named_curve`` format will be used,
1236 if no OID is associated with the curve, the fallback of
1237 ``explicit`` parameters will be used.
1238 Ignored for EdDSA.
1240 :return: DER encoded private key
1241 :rtype: bytes
1242 """
1243 # SEQ([int(1), octetstring(privkey),cont[0], oid(secp224r1),
1244 # cont[1],bitstring])
1245 if point_encoding == "raw":
1246 raise ValueError("raw encoding not allowed in DER")
1247 assert format in ("ssleay", "pkcs8")
1248 if isinstance(self.curve.curve, CurveEdTw):
1249 if format != "pkcs8":
1250 raise ValueError("Only PKCS#8 format supported for EdDSA keys")
1251 return self._encode_eddsa()
1252 encoded_vk = self.get_verifying_key().to_string(point_encoding)
1253 priv_key_elems = [
1254 der.encode_integer(1),
1255 der.encode_octet_string(self.to_string()),
1256 ]
1257 if format == "ssleay":
1258 priv_key_elems.append(
1259 der.encode_constructed(
1260 0, self.curve.to_der(curve_parameters_encoding)
1261 )
1262 )
1263 # the 0 in encode_bitstring specifies the number of unused bits
1264 # in the `encoded_vk` string
1265 priv_key_elems.append(
1266 der.encode_constructed(1, der.encode_bitstring(encoded_vk, 0))
1267 )
1268 ec_private_key = der.encode_sequence(*priv_key_elems)
1270 if format == "ssleay":
1271 return ec_private_key
1272 else:
1273 return der.encode_sequence(
1274 # version = 1 means the public key is not present in the
1275 # top-level structure.
1276 der.encode_integer(1),
1277 der.encode_sequence(
1278 der.encode_oid(*oid_ecPublicKey),
1279 self.curve.to_der(curve_parameters_encoding),
1280 ),
1281 der.encode_octet_string(ec_private_key),
1282 )
1284 def get_verifying_key(self):
1285 """
1286 Return the VerifyingKey associated with this private key.
1288 Equivalent to reading the `verifying_key` field of an instance.
1290 :return: a public key that can be used to verify the signatures made
1291 with this SigningKey
1292 :rtype: VerifyingKey
1293 """
1294 return self.verifying_key
1296 def sign_deterministic(
1297 self,
1298 data,
1299 hashfunc=None,
1300 sigencode=sigencode_string,
1301 extra_entropy=b"",
1302 ):
1303 """
1304 Create signature over data.
1306 For Weierstrass curves it uses the deterministic RFC6979 algorithm.
1307 For Edwards curves it uses the standard EdDSA algorithm.
1309 For ECDSA the data will be hashed using the `hashfunc` function before
1310 signing.
1311 For EdDSA the data will be hashed with the hash associated with the
1312 curve (SHA-512 for Ed25519 and SHAKE-256 for Ed448).
1314 This is the recommended method for performing signatures when hashing
1315 of data is necessary.
1317 :param data: data to be hashed and computed signature over
1318 :type data: :term:`bytes-like object`
1319 :param hashfunc: hash function to use for computing the signature,
1320 if unspecified, the default hash function selected during
1321 object initialisation will be used (see
1322 `VerifyingKey.default_hashfunc`). The object needs to implement
1323 the same interface as hashlib.sha1.
1324 Ignored with EdDSA.
1325 :type hashfunc: callable
1326 :param sigencode: function used to encode the signature.
1327 The function needs to accept three parameters: the two integers
1328 that are the signature and the order of the curve over which the
1329 signature was computed. It needs to return an encoded signature.
1330 See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
1331 as examples of such functions.
1332 Ignored with EdDSA.
1333 :type sigencode: callable
1334 :param extra_entropy: additional data that will be fed into the random
1335 number generator used in the RFC6979 process. Entirely optional.
1336 Ignored with EdDSA.
1337 :type extra_entropy: :term:`bytes-like object`
1339 :return: encoded signature over `data`
1340 :rtype: bytes or sigencode function dependent type
1341 """
1342 hashfunc = hashfunc or self.default_hashfunc
1343 data = normalise_bytes(data)
1345 if isinstance(self.curve.curve, CurveEdTw):
1346 return self.privkey.sign(data)
1348 extra_entropy = normalise_bytes(extra_entropy)
1349 digest = hashfunc(data).digest()
1351 return self.sign_digest_deterministic(
1352 digest,
1353 hashfunc=hashfunc,
1354 sigencode=sigencode,
1355 extra_entropy=extra_entropy,
1356 allow_truncate=True,
1357 )
1359 def sign_digest_deterministic(
1360 self,
1361 digest,
1362 hashfunc=None,
1363 sigencode=sigencode_string,
1364 extra_entropy=b"",
1365 allow_truncate=False,
1366 ):
1367 """
1368 Create signature for digest using the deterministic RFC6979 algorithm.
1370 `digest` should be the output of cryptographically secure hash function
1371 like SHA256 or SHA-3-256.
1373 This is the recommended method for performing signatures when no
1374 hashing of data is necessary.
1376 :param digest: hash of data that will be signed
1377 :type digest: :term:`bytes-like object`
1378 :param hashfunc: hash function to use for computing the random "k"
1379 value from RFC6979 process,
1380 if unspecified, the default hash function selected during
1381 object initialisation will be used (see
1382 :attr:`.VerifyingKey.default_hashfunc`). The object needs to
1383 implement
1384 the same interface as :func:`~hashlib.sha1` from :py:mod:`hashlib`.
1385 :type hashfunc: callable
1386 :param sigencode: function used to encode the signature.
1387 The function needs to accept three parameters: the two integers
1388 that are the signature and the order of the curve over which the
1389 signature was computed. It needs to return an encoded signature.
1390 See :func:`~ecdsa.util.sigencode_string` and
1391 :func:`~ecdsa.util.sigencode_der`
1392 as examples of such functions.
1393 :type sigencode: callable
1394 :param extra_entropy: additional data that will be fed into the random
1395 number generator used in the RFC6979 process. Entirely optional.
1396 :type extra_entropy: :term:`bytes-like object`
1397 :param bool allow_truncate: if True, the provided digest can have
1398 bigger bit-size than the order of the curve, the extra bits (at
1399 the end of the digest) will be truncated. Use it when signing
1400 SHA-384 output using NIST256p or in similar situations.
1402 :return: encoded signature for the `digest` hash
1403 :rtype: bytes or sigencode function dependent type
1404 """
1405 if isinstance(self.curve.curve, CurveEdTw):
1406 raise ValueError("Method unsupported for Edwards curves")
1407 secexp = self.privkey.secret_multiplier
1408 hashfunc = hashfunc or self.default_hashfunc
1409 digest = normalise_bytes(digest)
1410 extra_entropy = normalise_bytes(extra_entropy)
1412 def simple_r_s(r, s, order):
1413 return r, s, order
1415 retry_gen = 0
1416 while True:
1417 k = rfc6979.generate_k(
1418 self.curve.generator.order(),
1419 secexp,
1420 hashfunc,
1421 digest,
1422 retry_gen=retry_gen,
1423 extra_entropy=extra_entropy,
1424 )
1425 try:
1426 r, s, order = self.sign_digest(
1427 digest,
1428 sigencode=simple_r_s,
1429 k=k,
1430 allow_truncate=allow_truncate,
1431 )
1432 break
1433 except RSZeroError:
1434 retry_gen += 1
1436 return sigencode(r, s, order)
1438 def sign(
1439 self,
1440 data,
1441 entropy=None,
1442 hashfunc=None,
1443 sigencode=sigencode_string,
1444 k=None,
1445 allow_truncate=True,
1446 ):
1447 """
1448 Create signature over data.
1450 Uses the probabilistic ECDSA algorithm for Weierstrass curves
1451 (NIST256p, etc.) and the deterministic EdDSA algorithm for the
1452 Edwards curves (Ed25519, Ed448).
1454 This method uses the standard ECDSA algorithm that requires a
1455 cryptographically secure random number generator.
1457 It's recommended to use the :func:`~SigningKey.sign_deterministic`
1458 method instead of this one.
1460 :param data: data that will be hashed for signing
1461 :type data: :term:`bytes-like object`
1462 :param callable entropy: randomness source, :func:`os.urandom` by
1463 default. Ignored with EdDSA.
1464 :param hashfunc: hash function to use for hashing the provided
1465 ``data``.
1466 If unspecified the default hash function selected during
1467 object initialisation will be used (see
1468 :attr:`.VerifyingKey.default_hashfunc`).
1469 Should behave like :func:`~hashlib.sha1` from :py:mod:`hashlib`.
1470 The output length of the
1471 hash (in bytes) must not be longer than the length of the curve
1472 order (rounded up to the nearest byte), so using SHA256 with
1473 NIST256p is ok, but SHA256 with NIST192p is not. (In the 2**-96ish
1474 unlikely event of a hash output larger than the curve order, the
1475 hash will effectively be wrapped mod n).
1476 If you want to explicitly allow use of large hashes with small
1477 curves set the ``allow_truncate`` to ``True``.
1478 Use ``hashfunc=hashlib.sha1`` to match openssl's
1479 ``-ecdsa-with-SHA1`` mode,
1480 or ``hashfunc=hashlib.sha256`` for openssl-1.0.0's
1481 ``-ecdsa-with-SHA256``.
1482 Ignored for EdDSA
1483 :type hashfunc: callable
1484 :param sigencode: function used to encode the signature.
1485 The function needs to accept three parameters: the two integers
1486 that are the signature and the order of the curve over which the
1487 signature was computed. It needs to return an encoded signature.
1488 See :func:`~ecdsa.util.sigencode_string` and
1489 :func:`~ecdsa.util.sigencode_der`
1490 as examples of such functions.
1491 Ignored for EdDSA
1492 :type sigencode: callable
1493 :param int k: a pre-selected nonce for calculating the signature.
1494 In typical use cases, it should be set to None (the default) to
1495 allow its generation from an entropy source.
1496 Ignored for EdDSA.
1497 :param bool allow_truncate: if ``True``, the provided digest can have
1498 bigger bit-size than the order of the curve, the extra bits (at
1499 the end of the digest) will be truncated. Use it when signing
1500 SHA-384 output using NIST256p or in similar situations. True by
1501 default.
1502 Ignored for EdDSA.
1504 :raises RSZeroError: in the unlikely event when *r* parameter or
1505 *s* parameter of the created signature is equal 0, as that would
1506 leak the key. Caller should try a better entropy source, retry with
1507 different ``k``, or use the
1508 :func:`~SigningKey.sign_deterministic` in such case.
1510 :return: encoded signature of the hash of `data`
1511 :rtype: bytes or sigencode function dependent type
1512 """
1513 hashfunc = hashfunc or self.default_hashfunc
1514 data = normalise_bytes(data)
1515 if isinstance(self.curve.curve, CurveEdTw):
1516 return self.sign_deterministic(data)
1517 h = hashfunc(data).digest()
1518 return self.sign_digest(h, entropy, sigencode, k, allow_truncate)
1520 def sign_digest(
1521 self,
1522 digest,
1523 entropy=None,
1524 sigencode=sigencode_string,
1525 k=None,
1526 allow_truncate=False,
1527 ):
1528 """
1529 Create signature over digest using the probabilistic ECDSA algorithm.
1531 This method uses the standard ECDSA algorithm that requires a
1532 cryptographically secure random number generator.
1534 This method does not hash the input.
1536 It's recommended to use the
1537 :func:`~SigningKey.sign_digest_deterministic` method
1538 instead of this one.
1540 :param digest: hash value that will be signed
1541 :type digest: :term:`bytes-like object`
1542 :param callable entropy: randomness source, os.urandom by default
1543 :param sigencode: function used to encode the signature.
1544 The function needs to accept three parameters: the two integers
1545 that are the signature and the order of the curve over which the
1546 signature was computed. It needs to return an encoded signature.
1547 See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
1548 as examples of such functions.
1549 :type sigencode: callable
1550 :param int k: a pre-selected nonce for calculating the signature.
1551 In typical use cases, it should be set to None (the default) to
1552 allow its generation from an entropy source.
1553 :param bool allow_truncate: if True, the provided digest can have
1554 bigger bit-size than the order of the curve, the extra bits (at
1555 the end of the digest) will be truncated. Use it when signing
1556 SHA-384 output using NIST256p or in similar situations.
1558 :raises RSZeroError: in the unlikely event when "r" parameter or
1559 "s" parameter of the created signature is equal 0, as that would
1560 leak the key. Caller should try a better entropy source, retry with
1561 different 'k', or use the
1562 :func:`~SigningKey.sign_digest_deterministic` in such case.
1564 :return: encoded signature for the `digest` hash
1565 :rtype: bytes or sigencode function dependent type
1566 """
1567 if isinstance(self.curve.curve, CurveEdTw):
1568 raise ValueError("Method unsupported for Edwards curves")
1569 digest = normalise_bytes(digest)
1570 number = _truncate_and_convert_digest(
1571 digest,
1572 self.curve,
1573 allow_truncate,
1574 )
1575 r, s = self.sign_number(number, entropy, k)
1576 return sigencode(r, s, self.privkey.order)
1578 def sign_number(self, number, entropy=None, k=None):
1579 """
1580 Sign an integer directly.
1582 Note, this is a low level method, usually you will want to use
1583 :func:`~SigningKey.sign_deterministic` or
1584 :func:`~SigningKey.sign_digest_deterministic`.
1586 :param int number: number to sign using the probabilistic ECDSA
1587 algorithm.
1588 :param callable entropy: entropy source, os.urandom by default
1589 :param int k: pre-selected nonce for signature operation. If unset
1590 it will be selected at random using the entropy source.
1592 :raises RSZeroError: in the unlikely event when "r" parameter or
1593 "s" parameter of the created signature is equal 0, as that would
1594 leak the key. Caller should try a better entropy source, retry with
1595 different 'k', or use the
1596 :func:`~SigningKey.sign_digest_deterministic` in such case.
1598 :return: the "r" and "s" parameters of the signature
1599 :rtype: tuple of ints
1600 """
1601 if isinstance(self.curve.curve, CurveEdTw):
1602 raise ValueError("Method unsupported for Edwards curves")
1603 order = self.privkey.order
1605 if k is not None:
1606 _k = k
1607 else:
1608 _k = randrange(order, entropy)
1610 assert 1 <= _k < order
1611 sig = self.privkey.sign(number, _k)
1612 return sig.r, sig.s