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

382 statements  

1""" 

2Primary classes for performing signing and verification operations. 

3""" 

4 

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 

27 

28 

29__all__ = [ 

30 "BadSignatureError", 

31 "BadDigestError", 

32 "VerifyingKey", 

33 "SigningKey", 

34 "MalformedPointError", 

35] 

36 

37 

38class BadSignatureError(Exception): 

39 """ 

40 Raised when verification of signature failed. 

41 

42 Will be raised irrespective of reason of the failure: 

43 

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 """ 

49 

50 pass 

51 

52 

53class BadDigestError(Exception): 

54 """Raised in case the selected hash is too large for the curve.""" 

55 

56 pass 

57 

58 

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 

76 

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) 

87 

88 return number 

89 

90 

91class VerifyingKey(object): 

92 """ 

93 Class for handling keys that can verify signatures (public keys). 

94 

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 """ 

103 

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 

113 

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 ) 

123 

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 

129 

130 def __ne__(self, other): 

131 """Return False if the points are identical, True otherwise.""" 

132 return not self == other 

133 

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. 

140 

141 This is a low-level method, generally you will not want to use it. 

142 

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 

155 

156 :raises MalformedPointError: if the public point does not lay on the 

157 curve 

158 

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 

177 

178 def precompute(self, lazy=False): 

179 """ 

180 Precompute multiplication tables for faster signature verification. 

181 

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. 

189 

190 Note: You should call this method only once, this method generates a 

191 new precomputation table every time it's called. 

192 

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 

217 

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. 

229 

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). 

236 

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. 

240 

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` 

258 

259 :raises MalformedPointError: if the public point does not lay on the 

260 curve or the encoding is invalid 

261 

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 

274 

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) 

282 

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. 

293 

294 The PEM header of the key should be ``BEGIN PUBLIC KEY``. 

295 

296 See the :func:`~VerifyingKey.from_der()` method for details of the 

297 format supported. 

298 

299 Note: only a single PEM object decoding is supported in provided 

300 string. 

301 

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` 

313 

314 

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 ) 

324 

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. 

335 

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):: 

338 

339 SubjectPublicKeyInfo {PUBLIC-KEY: IOSet} ::= SEQUENCE { 

340 algorithm AlgorithmIdentifier {PUBLIC-KEY, {IOSet}}, 

341 subjectPublicKey BIT STRING 

342 } 

343 

344 Note: only public EC keys are supported by this method. The 

345 SubjectPublicKeyInfo.algorithm.algorithm field must specify 

346 id-ecPublicKey (see RFC3279). 

347 

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. 

354 

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` 

366 

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 ) 

413 

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. 

426 

427 Tries to recover the public key that can be used to verify the 

428 signature, usually returns two keys like that. 

429 

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 

449 

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 ) 

465 

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. 

478 

479 Tries to recover the public key that can be used to verify the 

480 signature, usually returns two keys like that. 

481 

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. 

502 

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) 

511 

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) 

517 

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 

523 

524 def to_string(self, encoding="raw"): 

525 """ 

526 Convert the public key to a byte string. 

527 

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. 

531 

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. 

535 

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`. 

539 

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) 

546 

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. 

552 

553 The PEM header of the key will be ``BEGIN PUBLIC KEY``. 

554 

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. 

558 

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. 

566 

567 :return: portable encoding of the public key 

568 :rtype: bytes 

569 

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 ) 

577 

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. 

583 

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. 

587 

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. 

595 

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 ) 

616 

617 def to_ssh(self): 

618 """ 

619 Convert the public key to the SSH format. 

620 

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 ) 

628 

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. 

639 

640 Will hash `data` to verify the signature. 

641 

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. 

646 

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. 

667 

668 :raises BadSignatureError: if the signature is invalid or malformed 

669 

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) 

682 

683 hashfunc = hashfunc or self.default_hashfunc 

684 digest = hashfunc(data).digest() 

685 return self.verify_digest(signature, digest, sigdecode, allow_truncate) 

686 

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. 

696 

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. 

701 

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. 

717 

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 

721 

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 ) 

733 

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") 

742 

743 

744class SigningKey(object): 

745 """ 

746 Class for handling keys that can create signatures (private keys). 

747 

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 """ 

757 

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 

767 

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 

777 

778 def __ne__(self, other): 

779 """Return False if the points are identical, True otherwise.""" 

780 return not self == other 

781 

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() 

790 

791 verifying_key = VerifyingKey.from_string( 

792 public_key.public_key(), curve 

793 ) 

794 

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 

802 

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) 

808 

809 @classmethod 

810 def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1): 

811 """ 

812 Generate a random private key. 

813 

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 

825 

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) 

832 

833 @classmethod 

834 def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1): 

835 """ 

836 Create a private key from a random integer. 

837 

838 Note: it's a low level method, it's recommended to use the 

839 :func:`~SigningKey.generate` method to create private keys. 

840 

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 

849 

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 

854 

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 

883 

884 @classmethod 

885 def from_string(cls, string, curve=NIST192p, hashfunc=sha1): 

886 """ 

887 Decode the private key from :term:`raw encoding`. 

888 

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`. 

892 

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 

901 

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 

906 

907 :return: Initialised SigningKey object 

908 :rtype: SigningKey 

909 """ 

910 string = normalise_bytes(string) 

911 

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) 

929 

930 @classmethod 

931 def from_pem(cls, string, hashfunc=sha1, valid_curve_encodings=None): 

932 """ 

933 Initialise from key stored in :term:`PEM` format. 

934 

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). 

938 

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. 

945 

946 See :func:`~SigningKey.from_der` for ASN.1 syntax of the objects in 

947 this files. 

948 

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` 

955 

956 

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 

962 

963 :return: Initialised SigningKey object 

964 :rtype: SigningKey 

965 """ 

966 if not PY2 and isinstance(string, str): # pragma: no branch 

967 string = string.encode() 

968 

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-----") 

975 

976 return cls.from_der( 

977 der.unpem(string[private_key_index:]), 

978 hashfunc, 

979 valid_curve_encodings, 

980 ) 

981 

982 @classmethod 

983 def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None): 

984 """ 

985 Initialise from key stored in :term:`DER` format. 

986 

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). 

990 

991 Both formats contain an ASN.1 object following the syntax specified 

992 in RFC5915:: 

993 

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 } 

1000 

1001 `publicKey` field is ignored completely (errors, if any, in it will 

1002 be undetected). 

1003 

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. 

1009 

1010 The PKCS #8 format includes an ECPrivateKey object as the `privateKey` 

1011 field within a larger structure:: 

1012 

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 } 

1022 

1023 The `attributes` and `publicKey` fields are completely ignored; errors 

1024 in them will not be detected. 

1025 

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` 

1033 

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 

1039 

1040 :return: Initialised SigningKey object 

1041 :rtype: SigningKey 

1042 """ 

1043 s = normalise_bytes(string) 

1044 curve = None 

1045 

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 ) 

1051 

1052 version, s = der.remove_integer(s) 

1053 

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 ) 

1064 

1065 sequence, s = der.remove_sequence(s) 

1066 algorithm_oid, algorithm_identifier = der.remove_object(sequence) 

1067 

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) 

1074 

1075 # As RFC5958 describe, there are may be optional Attributes 

1076 # and Publickey. Don't raise error if something after 

1077 # Privatekey 

1078 

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 ) 

1089 

1090 if algorithm_oid == Ed25519.oid: 

1091 curve = Ed25519 

1092 else: 

1093 assert algorithm_oid == Ed448.oid 

1094 curve = Ed448 

1095 

1096 return cls.from_string(key_str, curve, None) 

1097 

1098 if algorithm_oid not in (oid_ecPublicKey, oid_ecDH, oid_ecMQV): 

1099 raise der.UnexpectedDER( 

1100 "unexpected algorithm identifier '%s'" % (algorithm_oid,) 

1101 ) 

1102 

1103 curve = Curve.from_der(algorithm_identifier, valid_curve_encodings) 

1104 

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) 

1108 

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 ) 

1117 

1118 version, s = der.remove_integer(s) 

1119 

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 ) 

1126 

1127 privkey_str, s = der.remove_octet_string(s) 

1128 

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) 

1136 

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)) 

1148 

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) 

1155 

1156 def to_string(self): 

1157 """ 

1158 Convert the private key to :term:`raw encoding`. 

1159 

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`. 

1163 

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 

1172 

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. 

1181 

1182 See :func:`~SigningKey.from_pem` method for format description. 

1183 

1184 Only the named curve format is supported. 

1185 The public key will be included in generated string. 

1186 

1187 The PEM header will specify ``BEGIN EC PRIVATE KEY`` or 

1188 ``BEGIN PRIVATE KEY``, depending on the desired format. 

1189 

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. 

1197 

1198 :return: PEM encoded private key 

1199 :rtype: bytes 

1200 

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 ) 

1211 

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 ) 

1220 

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. 

1229 

1230 See :func:`~SigningKey.from_der` method for format specification. 

1231 

1232 Only the named curve format is supported. 

1233 The public key will be included in the generated string. 

1234 

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. 

1245 

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) 

1275 

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 ) 

1289 

1290 def to_ssh(self): 

1291 """ 

1292 Convert the private key to the SSH format. 

1293 

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 ) 

1302 

1303 def get_verifying_key(self): 

1304 """ 

1305 Return the VerifyingKey associated with this private key. 

1306 

1307 Equivalent to reading the `verifying_key` field of an instance. 

1308 

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 

1314 

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. 

1324 

1325 For Weierstrass curves it uses the deterministic RFC6979 algorithm. 

1326 For Edwards curves it uses the standard EdDSA algorithm. 

1327 

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). 

1332 

1333 This is the recommended method for performing signatures when hashing 

1334 of data is necessary. 

1335 

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` 

1357 

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) 

1363 

1364 if isinstance(self.curve.curve, CurveEdTw): 

1365 return self.privkey.sign(data) 

1366 

1367 extra_entropy = normalise_bytes(extra_entropy) 

1368 digest = hashfunc(data).digest() 

1369 

1370 return self.sign_digest_deterministic( 

1371 digest, 

1372 hashfunc=hashfunc, 

1373 sigencode=sigencode, 

1374 extra_entropy=extra_entropy, 

1375 allow_truncate=True, 

1376 ) 

1377 

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. 

1388 

1389 `digest` should be the output of cryptographically secure hash function 

1390 like SHA256 or SHA-3-256. 

1391 

1392 This is the recommended method for performing signatures when no 

1393 hashing of data is necessary. 

1394 

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. 

1420 

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) 

1430 

1431 def simple_r_s(r, s, order): 

1432 return r, s, order 

1433 

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 

1454 

1455 return sigencode(r, s, order) 

1456 

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. 

1468 

1469 Uses the probabilistic ECDSA algorithm for Weierstrass curves 

1470 (NIST256p, etc.) and the deterministic EdDSA algorithm for the 

1471 Edwards curves (Ed25519, Ed448). 

1472 

1473 This method uses the standard ECDSA algorithm that requires a 

1474 cryptographically secure random number generator. 

1475 

1476 It's recommended to use the :func:`~SigningKey.sign_deterministic` 

1477 method instead of this one. 

1478 

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. 

1522 

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. 

1528 

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) 

1538 

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. 

1549 

1550 This method uses the standard ECDSA algorithm that requires a 

1551 cryptographically secure random number generator. 

1552 

1553 This method does not hash the input. 

1554 

1555 It's recommended to use the 

1556 :func:`~SigningKey.sign_digest_deterministic` method 

1557 instead of this one. 

1558 

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. 

1576 

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. 

1582 

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) 

1596 

1597 def sign_number(self, number, entropy=None, k=None): 

1598 """ 

1599 Sign an integer directly. 

1600 

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`. 

1604 

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. 

1610 

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. 

1616 

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 

1623 

1624 if k is not None: 

1625 _k = k 

1626 else: 

1627 _k = randrange(order, entropy) 

1628 

1629 assert 1 <= _k < order 

1630 sig = self.privkey.sign(number, _k) 

1631 return sig.r, sig.s