Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/rsa/key.py: 56%

256 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 07:21 +0000

1# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# https://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15"""RSA key generation code. 

16 

17Create new keys with the newkeys() function. It will give you a PublicKey and a 

18PrivateKey object. 

19 

20Loading and saving keys requires the pyasn1 module. This module is imported as 

21late as possible, such that other functionality will remain working in absence 

22of pyasn1. 

23 

24.. note:: 

25 

26 Storing public and private keys via the `pickle` module is possible. 

27 However, it is insecure to load a key from an untrusted source. 

28 The pickle module is not secure against erroneous or maliciously 

29 constructed data. Never unpickle data received from an untrusted 

30 or unauthenticated source. 

31 

32""" 

33 

34import abc 

35import threading 

36import typing 

37import warnings 

38 

39import rsa.prime 

40import rsa.pem 

41import rsa.common 

42import rsa.randnum 

43import rsa.core 

44 

45 

46DEFAULT_EXPONENT = 65537 

47 

48 

49T = typing.TypeVar("T", bound="AbstractKey") 

50 

51 

52class AbstractKey(metaclass=abc.ABCMeta): 

53 """Abstract superclass for private and public keys.""" 

54 

55 __slots__ = ("n", "e", "blindfac", "blindfac_inverse", "mutex") 

56 

57 def __init__(self, n: int, e: int) -> None: 

58 self.n = n 

59 self.e = e 

60 

61 # These will be computed properly on the first call to blind(). 

62 self.blindfac = self.blindfac_inverse = -1 

63 

64 # Used to protect updates to the blinding factor in multi-threaded 

65 # environments. 

66 self.mutex = threading.Lock() 

67 

68 @classmethod 

69 @abc.abstractmethod 

70 def _load_pkcs1_pem(cls: typing.Type[T], keyfile: bytes) -> T: 

71 """Loads a key in PKCS#1 PEM format, implement in a subclass. 

72 

73 :param keyfile: contents of a PEM-encoded file that contains 

74 the public key. 

75 :type keyfile: bytes 

76 

77 :return: the loaded key 

78 :rtype: AbstractKey 

79 """ 

80 

81 @classmethod 

82 @abc.abstractmethod 

83 def _load_pkcs1_der(cls: typing.Type[T], keyfile: bytes) -> T: 

84 """Loads a key in PKCS#1 PEM format, implement in a subclass. 

85 

86 :param keyfile: contents of a DER-encoded file that contains 

87 the public key. 

88 :type keyfile: bytes 

89 

90 :return: the loaded key 

91 :rtype: AbstractKey 

92 """ 

93 

94 @abc.abstractmethod 

95 def _save_pkcs1_pem(self) -> bytes: 

96 """Saves the key in PKCS#1 PEM format, implement in a subclass. 

97 

98 :returns: the PEM-encoded key. 

99 :rtype: bytes 

100 """ 

101 

102 @abc.abstractmethod 

103 def _save_pkcs1_der(self) -> bytes: 

104 """Saves the key in PKCS#1 DER format, implement in a subclass. 

105 

106 :returns: the DER-encoded key. 

107 :rtype: bytes 

108 """ 

109 

110 @classmethod 

111 def load_pkcs1(cls: typing.Type[T], keyfile: bytes, format: str = "PEM") -> T: 

112 """Loads a key in PKCS#1 DER or PEM format. 

113 

114 :param keyfile: contents of a DER- or PEM-encoded file that contains 

115 the key. 

116 :type keyfile: bytes 

117 :param format: the format of the file to load; 'PEM' or 'DER' 

118 :type format: str 

119 

120 :return: the loaded key 

121 :rtype: AbstractKey 

122 """ 

123 

124 methods = { 

125 "PEM": cls._load_pkcs1_pem, 

126 "DER": cls._load_pkcs1_der, 

127 } 

128 

129 method = cls._assert_format_exists(format, methods) 

130 return method(keyfile) 

131 

132 @staticmethod 

133 def _assert_format_exists( 

134 file_format: str, methods: typing.Mapping[str, typing.Callable] 

135 ) -> typing.Callable: 

136 """Checks whether the given file format exists in 'methods'.""" 

137 

138 try: 

139 return methods[file_format] 

140 except KeyError as ex: 

141 formats = ", ".join(sorted(methods.keys())) 

142 raise ValueError( 

143 "Unsupported format: %r, try one of %s" % (file_format, formats) 

144 ) from ex 

145 

146 def save_pkcs1(self, format: str = "PEM") -> bytes: 

147 """Saves the key in PKCS#1 DER or PEM format. 

148 

149 :param format: the format to save; 'PEM' or 'DER' 

150 :type format: str 

151 :returns: the DER- or PEM-encoded key. 

152 :rtype: bytes 

153 """ 

154 

155 methods = { 

156 "PEM": self._save_pkcs1_pem, 

157 "DER": self._save_pkcs1_der, 

158 } 

159 

160 method = self._assert_format_exists(format, methods) 

161 return method() 

162 

163 def blind(self, message: int) -> typing.Tuple[int, int]: 

164 """Performs blinding on the message. 

165 

166 :param message: the message, as integer, to blind. 

167 :param r: the random number to blind with. 

168 :return: tuple (the blinded message, the inverse of the used blinding factor) 

169 

170 The blinding is such that message = unblind(decrypt(blind(encrypt(message))). 

171 

172 See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29 

173 """ 

174 blindfac, blindfac_inverse = self._update_blinding_factor() 

175 blinded = (message * pow(blindfac, self.e, self.n)) % self.n 

176 return blinded, blindfac_inverse 

177 

178 def unblind(self, blinded: int, blindfac_inverse: int) -> int: 

179 """Performs blinding on the message using random number 'blindfac_inverse'. 

180 

181 :param blinded: the blinded message, as integer, to unblind. 

182 :param blindfac: the factor to unblind with. 

183 :return: the original message. 

184 

185 The blinding is such that message = unblind(decrypt(blind(encrypt(message))). 

186 

187 See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29 

188 """ 

189 return (blindfac_inverse * blinded) % self.n 

190 

191 def _initial_blinding_factor(self) -> int: 

192 for _ in range(1000): 

193 blind_r = rsa.randnum.randint(self.n - 1) 

194 if rsa.prime.are_relatively_prime(self.n, blind_r): 

195 return blind_r 

196 raise RuntimeError("unable to find blinding factor") 

197 

198 def _update_blinding_factor(self) -> typing.Tuple[int, int]: 

199 """Update blinding factors. 

200 

201 Computing a blinding factor is expensive, so instead this function 

202 does this once, then updates the blinding factor as per section 9 

203 of 'A Timing Attack against RSA with the Chinese Remainder Theorem' 

204 by Werner Schindler. 

205 See https://tls.mbed.org/public/WSchindler-RSA_Timing_Attack.pdf 

206 

207 :return: the new blinding factor and its inverse. 

208 """ 

209 

210 with self.mutex: 

211 if self.blindfac < 0: 

212 # Compute initial blinding factor, which is rather slow to do. 

213 self.blindfac = self._initial_blinding_factor() 

214 self.blindfac_inverse = rsa.common.inverse(self.blindfac, self.n) 

215 else: 

216 # Reuse previous blinding factor. 

217 self.blindfac = pow(self.blindfac, 2, self.n) 

218 self.blindfac_inverse = pow(self.blindfac_inverse, 2, self.n) 

219 

220 return self.blindfac, self.blindfac_inverse 

221 

222 

223class PublicKey(AbstractKey): 

224 """Represents a public RSA key. 

225 

226 This key is also known as the 'encryption key'. It contains the 'n' and 'e' 

227 values. 

228 

229 Supports attributes as well as dictionary-like access. Attribute access is 

230 faster, though. 

231 

232 >>> PublicKey(5, 3) 

233 PublicKey(5, 3) 

234 

235 >>> key = PublicKey(5, 3) 

236 >>> key.n 

237 5 

238 >>> key['n'] 

239 5 

240 >>> key.e 

241 3 

242 >>> key['e'] 

243 3 

244 

245 """ 

246 

247 __slots__ = () 

248 

249 def __getitem__(self, key: str) -> int: 

250 return getattr(self, key) 

251 

252 def __repr__(self) -> str: 

253 return "PublicKey(%i, %i)" % (self.n, self.e) 

254 

255 def __getstate__(self) -> typing.Tuple[int, int]: 

256 """Returns the key as tuple for pickling.""" 

257 return self.n, self.e 

258 

259 def __setstate__(self, state: typing.Tuple[int, int]) -> None: 

260 """Sets the key from tuple.""" 

261 self.n, self.e = state 

262 AbstractKey.__init__(self, self.n, self.e) 

263 

264 def __eq__(self, other: typing.Any) -> bool: 

265 if other is None: 

266 return False 

267 

268 if not isinstance(other, PublicKey): 

269 return False 

270 

271 return self.n == other.n and self.e == other.e 

272 

273 def __ne__(self, other: typing.Any) -> bool: 

274 return not (self == other) 

275 

276 def __hash__(self) -> int: 

277 return hash((self.n, self.e)) 

278 

279 @classmethod 

280 def _load_pkcs1_der(cls, keyfile: bytes) -> "PublicKey": 

281 """Loads a key in PKCS#1 DER format. 

282 

283 :param keyfile: contents of a DER-encoded file that contains the public 

284 key. 

285 :return: a PublicKey object 

286 

287 First let's construct a DER encoded key: 

288 

289 >>> import base64 

290 >>> b64der = 'MAwCBQCNGmYtAgMBAAE=' 

291 >>> der = base64.standard_b64decode(b64der) 

292 

293 This loads the file: 

294 

295 >>> PublicKey._load_pkcs1_der(der) 

296 PublicKey(2367317549, 65537) 

297 

298 """ 

299 

300 from pyasn1.codec.der import decoder 

301 from rsa.asn1 import AsnPubKey 

302 

303 (priv, _) = decoder.decode(keyfile, asn1Spec=AsnPubKey()) 

304 return cls(n=int(priv["modulus"]), e=int(priv["publicExponent"])) 

305 

306 def _save_pkcs1_der(self) -> bytes: 

307 """Saves the public key in PKCS#1 DER format. 

308 

309 :returns: the DER-encoded public key. 

310 :rtype: bytes 

311 """ 

312 

313 from pyasn1.codec.der import encoder 

314 from rsa.asn1 import AsnPubKey 

315 

316 # Create the ASN object 

317 asn_key = AsnPubKey() 

318 asn_key.setComponentByName("modulus", self.n) 

319 asn_key.setComponentByName("publicExponent", self.e) 

320 

321 return encoder.encode(asn_key) 

322 

323 @classmethod 

324 def _load_pkcs1_pem(cls, keyfile: bytes) -> "PublicKey": 

325 """Loads a PKCS#1 PEM-encoded public key file. 

326 

327 The contents of the file before the "-----BEGIN RSA PUBLIC KEY-----" and 

328 after the "-----END RSA PUBLIC KEY-----" lines is ignored. 

329 

330 :param keyfile: contents of a PEM-encoded file that contains the public 

331 key. 

332 :return: a PublicKey object 

333 """ 

334 

335 der = rsa.pem.load_pem(keyfile, "RSA PUBLIC KEY") 

336 return cls._load_pkcs1_der(der) 

337 

338 def _save_pkcs1_pem(self) -> bytes: 

339 """Saves a PKCS#1 PEM-encoded public key file. 

340 

341 :return: contents of a PEM-encoded file that contains the public key. 

342 :rtype: bytes 

343 """ 

344 

345 der = self._save_pkcs1_der() 

346 return rsa.pem.save_pem(der, "RSA PUBLIC KEY") 

347 

348 @classmethod 

349 def load_pkcs1_openssl_pem(cls, keyfile: bytes) -> "PublicKey": 

350 """Loads a PKCS#1.5 PEM-encoded public key file from OpenSSL. 

351 

352 These files can be recognised in that they start with BEGIN PUBLIC KEY 

353 rather than BEGIN RSA PUBLIC KEY. 

354 

355 The contents of the file before the "-----BEGIN PUBLIC KEY-----" and 

356 after the "-----END PUBLIC KEY-----" lines is ignored. 

357 

358 :param keyfile: contents of a PEM-encoded file that contains the public 

359 key, from OpenSSL. 

360 :type keyfile: bytes 

361 :return: a PublicKey object 

362 """ 

363 

364 der = rsa.pem.load_pem(keyfile, "PUBLIC KEY") 

365 return cls.load_pkcs1_openssl_der(der) 

366 

367 @classmethod 

368 def load_pkcs1_openssl_der(cls, keyfile: bytes) -> "PublicKey": 

369 """Loads a PKCS#1 DER-encoded public key file from OpenSSL. 

370 

371 :param keyfile: contents of a DER-encoded file that contains the public 

372 key, from OpenSSL. 

373 :return: a PublicKey object 

374 """ 

375 

376 from rsa.asn1 import OpenSSLPubKey 

377 from pyasn1.codec.der import decoder 

378 from pyasn1.type import univ 

379 

380 (keyinfo, _) = decoder.decode(keyfile, asn1Spec=OpenSSLPubKey()) 

381 

382 if keyinfo["header"]["oid"] != univ.ObjectIdentifier("1.2.840.113549.1.1.1"): 

383 raise TypeError("This is not a DER-encoded OpenSSL-compatible public key") 

384 

385 return cls._load_pkcs1_der(keyinfo["key"][1:]) 

386 

387 

388class PrivateKey(AbstractKey): 

389 """Represents a private RSA key. 

390 

391 This key is also known as the 'decryption key'. It contains the 'n', 'e', 

392 'd', 'p', 'q' and other values. 

393 

394 Supports attributes as well as dictionary-like access. Attribute access is 

395 faster, though. 

396 

397 >>> PrivateKey(3247, 65537, 833, 191, 17) 

398 PrivateKey(3247, 65537, 833, 191, 17) 

399 

400 exp1, exp2 and coef will be calculated: 

401 

402 >>> pk = PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) 

403 >>> pk.exp1 

404 55063 

405 >>> pk.exp2 

406 10095 

407 >>> pk.coef 

408 50797 

409 

410 """ 

411 

412 __slots__ = ("d", "p", "q", "exp1", "exp2", "coef") 

413 

414 def __init__(self, n: int, e: int, d: int, p: int, q: int) -> None: 

415 AbstractKey.__init__(self, n, e) 

416 self.d = d 

417 self.p = p 

418 self.q = q 

419 

420 # Calculate exponents and coefficient. 

421 self.exp1 = int(d % (p - 1)) 

422 self.exp2 = int(d % (q - 1)) 

423 self.coef = rsa.common.inverse(q, p) 

424 

425 def __getitem__(self, key: str) -> int: 

426 return getattr(self, key) 

427 

428 def __repr__(self) -> str: 

429 return "PrivateKey(%i, %i, %i, %i, %i)" % ( 

430 self.n, 

431 self.e, 

432 self.d, 

433 self.p, 

434 self.q, 

435 ) 

436 

437 def __getstate__(self) -> typing.Tuple[int, int, int, int, int, int, int, int]: 

438 """Returns the key as tuple for pickling.""" 

439 return self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef 

440 

441 def __setstate__(self, state: typing.Tuple[int, int, int, int, int, int, int, int]) -> None: 

442 """Sets the key from tuple.""" 

443 self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef = state 

444 AbstractKey.__init__(self, self.n, self.e) 

445 

446 def __eq__(self, other: typing.Any) -> bool: 

447 if other is None: 

448 return False 

449 

450 if not isinstance(other, PrivateKey): 

451 return False 

452 

453 return ( 

454 self.n == other.n 

455 and self.e == other.e 

456 and self.d == other.d 

457 and self.p == other.p 

458 and self.q == other.q 

459 and self.exp1 == other.exp1 

460 and self.exp2 == other.exp2 

461 and self.coef == other.coef 

462 ) 

463 

464 def __ne__(self, other: typing.Any) -> bool: 

465 return not (self == other) 

466 

467 def __hash__(self) -> int: 

468 return hash((self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef)) 

469 

470 def blinded_decrypt(self, encrypted: int) -> int: 

471 """Decrypts the message using blinding to prevent side-channel attacks. 

472 

473 :param encrypted: the encrypted message 

474 :type encrypted: int 

475 

476 :returns: the decrypted message 

477 :rtype: int 

478 """ 

479 

480 # Blinding and un-blinding should be using the same factor 

481 blinded, blindfac_inverse = self.blind(encrypted) 

482 

483 # Instead of using the core functionality, use the Chinese Remainder 

484 # Theorem and be 2-4x faster. This the same as: 

485 # 

486 # decrypted = rsa.core.decrypt_int(blinded, self.d, self.n) 

487 s1 = pow(blinded, self.exp1, self.p) 

488 s2 = pow(blinded, self.exp2, self.q) 

489 h = ((s1 - s2) * self.coef) % self.p 

490 decrypted = s2 + self.q * h 

491 

492 return self.unblind(decrypted, blindfac_inverse) 

493 

494 

495 @classmethod 

496 def _load_pkcs1_der(cls, keyfile: bytes) -> "PrivateKey": 

497 """Loads a key in PKCS#1 DER format. 

498 

499 :param keyfile: contents of a DER-encoded file that contains the private 

500 key. 

501 :type keyfile: bytes 

502 :return: a PrivateKey object 

503 

504 First let's construct a DER encoded key: 

505 

506 >>> import base64 

507 >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt' 

508 >>> der = base64.standard_b64decode(b64der) 

509 

510 This loads the file: 

511 

512 >>> PrivateKey._load_pkcs1_der(der) 

513 PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) 

514 

515 """ 

516 

517 from pyasn1.codec.der import decoder 

518 

519 (priv, _) = decoder.decode(keyfile) 

520 

521 # ASN.1 contents of DER encoded private key: 

522 # 

523 # RSAPrivateKey ::= SEQUENCE { 

524 # version Version, 

525 # modulus INTEGER, -- n 

526 # publicExponent INTEGER, -- e 

527 # privateExponent INTEGER, -- d 

528 # prime1 INTEGER, -- p 

529 # prime2 INTEGER, -- q 

530 # exponent1 INTEGER, -- d mod (p-1) 

531 # exponent2 INTEGER, -- d mod (q-1) 

532 # coefficient INTEGER, -- (inverse of q) mod p 

533 # otherPrimeInfos OtherPrimeInfos OPTIONAL 

534 # } 

535 

536 if priv[0] != 0: 

537 raise ValueError("Unable to read this file, version %s != 0" % priv[0]) 

538 

539 as_ints = map(int, priv[1:6]) 

540 key = cls(*as_ints) 

541 

542 exp1, exp2, coef = map(int, priv[6:9]) 

543 

544 if (key.exp1, key.exp2, key.coef) != (exp1, exp2, coef): 

545 warnings.warn( 

546 "You have provided a malformed keyfile. Either the exponents " 

547 "or the coefficient are incorrect. Using the correct values " 

548 "instead.", 

549 UserWarning, 

550 ) 

551 

552 return key 

553 

554 def _save_pkcs1_der(self) -> bytes: 

555 """Saves the private key in PKCS#1 DER format. 

556 

557 :returns: the DER-encoded private key. 

558 :rtype: bytes 

559 """ 

560 

561 from pyasn1.type import univ, namedtype 

562 from pyasn1.codec.der import encoder 

563 

564 class AsnPrivKey(univ.Sequence): 

565 componentType = namedtype.NamedTypes( 

566 namedtype.NamedType("version", univ.Integer()), 

567 namedtype.NamedType("modulus", univ.Integer()), 

568 namedtype.NamedType("publicExponent", univ.Integer()), 

569 namedtype.NamedType("privateExponent", univ.Integer()), 

570 namedtype.NamedType("prime1", univ.Integer()), 

571 namedtype.NamedType("prime2", univ.Integer()), 

572 namedtype.NamedType("exponent1", univ.Integer()), 

573 namedtype.NamedType("exponent2", univ.Integer()), 

574 namedtype.NamedType("coefficient", univ.Integer()), 

575 ) 

576 

577 # Create the ASN object 

578 asn_key = AsnPrivKey() 

579 asn_key.setComponentByName("version", 0) 

580 asn_key.setComponentByName("modulus", self.n) 

581 asn_key.setComponentByName("publicExponent", self.e) 

582 asn_key.setComponentByName("privateExponent", self.d) 

583 asn_key.setComponentByName("prime1", self.p) 

584 asn_key.setComponentByName("prime2", self.q) 

585 asn_key.setComponentByName("exponent1", self.exp1) 

586 asn_key.setComponentByName("exponent2", self.exp2) 

587 asn_key.setComponentByName("coefficient", self.coef) 

588 

589 return encoder.encode(asn_key) 

590 

591 @classmethod 

592 def _load_pkcs1_pem(cls, keyfile: bytes) -> "PrivateKey": 

593 """Loads a PKCS#1 PEM-encoded private key file. 

594 

595 The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and 

596 after the "-----END RSA PRIVATE KEY-----" lines is ignored. 

597 

598 :param keyfile: contents of a PEM-encoded file that contains the private 

599 key. 

600 :type keyfile: bytes 

601 :return: a PrivateKey object 

602 """ 

603 

604 der = rsa.pem.load_pem(keyfile, b"RSA PRIVATE KEY") 

605 return cls._load_pkcs1_der(der) 

606 

607 def _save_pkcs1_pem(self) -> bytes: 

608 """Saves a PKCS#1 PEM-encoded private key file. 

609 

610 :return: contents of a PEM-encoded file that contains the private key. 

611 :rtype: bytes 

612 """ 

613 

614 der = self._save_pkcs1_der() 

615 return rsa.pem.save_pem(der, b"RSA PRIVATE KEY") 

616 

617 

618def find_p_q( 

619 nbits: int, 

620 getprime_func: typing.Callable[[int], int] = rsa.prime.getprime, 

621 accurate: bool = True, 

622) -> typing.Tuple[int, int]: 

623 """Returns a tuple of two different primes of nbits bits each. 

624 

625 The resulting p * q has exactly 2 * nbits bits, and the returned p and q 

626 will not be equal. 

627 

628 :param nbits: the number of bits in each of p and q. 

629 :param getprime_func: the getprime function, defaults to 

630 :py:func:`rsa.prime.getprime`. 

631 

632 *Introduced in Python-RSA 3.1* 

633 

634 :param accurate: whether to enable accurate mode or not. 

635 :returns: (p, q), where p > q 

636 

637 >>> (p, q) = find_p_q(128) 

638 >>> from rsa import common 

639 >>> common.bit_size(p * q) 

640 256 

641 

642 When not in accurate mode, the number of bits can be slightly less 

643 

644 >>> (p, q) = find_p_q(128, accurate=False) 

645 >>> from rsa import common 

646 >>> common.bit_size(p * q) <= 256 

647 True 

648 >>> common.bit_size(p * q) > 240 

649 True 

650 

651 """ 

652 

653 total_bits = nbits * 2 

654 

655 # Make sure that p and q aren't too close or the factoring programs can 

656 # factor n. 

657 shift = nbits // 16 

658 pbits = nbits + shift 

659 qbits = nbits - shift 

660 

661 # Choose the two initial primes 

662 p = getprime_func(pbits) 

663 q = getprime_func(qbits) 

664 

665 def is_acceptable(p: int, q: int) -> bool: 

666 """Returns True iff p and q are acceptable: 

667 

668 - p and q differ 

669 - (p * q) has the right nr of bits (when accurate=True) 

670 """ 

671 

672 if p == q: 

673 return False 

674 

675 if not accurate: 

676 return True 

677 

678 # Make sure we have just the right amount of bits 

679 found_size = rsa.common.bit_size(p * q) 

680 return total_bits == found_size 

681 

682 # Keep choosing other primes until they match our requirements. 

683 change_p = False 

684 while not is_acceptable(p, q): 

685 # Change p on one iteration and q on the other 

686 if change_p: 

687 p = getprime_func(pbits) 

688 else: 

689 q = getprime_func(qbits) 

690 

691 change_p = not change_p 

692 

693 # We want p > q as described on 

694 # http://www.di-mgt.com.au/rsa_alg.html#crt 

695 return max(p, q), min(p, q) 

696 

697 

698def calculate_keys_custom_exponent(p: int, q: int, exponent: int) -> typing.Tuple[int, int]: 

699 """Calculates an encryption and a decryption key given p, q and an exponent, 

700 and returns them as a tuple (e, d) 

701 

702 :param p: the first large prime 

703 :param q: the second large prime 

704 :param exponent: the exponent for the key; only change this if you know 

705 what you're doing, as the exponent influences how difficult your 

706 private key can be cracked. A very common choice for e is 65537. 

707 :type exponent: int 

708 

709 """ 

710 

711 phi_n = (p - 1) * (q - 1) 

712 

713 try: 

714 d = rsa.common.inverse(exponent, phi_n) 

715 except rsa.common.NotRelativePrimeError as ex: 

716 raise rsa.common.NotRelativePrimeError( 

717 exponent, 

718 phi_n, 

719 ex.d, 

720 msg="e (%d) and phi_n (%d) are not relatively prime (divider=%i)" 

721 % (exponent, phi_n, ex.d), 

722 ) from ex 

723 

724 if (exponent * d) % phi_n != 1: 

725 raise ValueError( 

726 "e (%d) and d (%d) are not mult. inv. modulo " "phi_n (%d)" % (exponent, d, phi_n) 

727 ) 

728 

729 return exponent, d 

730 

731 

732def calculate_keys(p: int, q: int) -> typing.Tuple[int, int]: 

733 """Calculates an encryption and a decryption key given p and q, and 

734 returns them as a tuple (e, d) 

735 

736 :param p: the first large prime 

737 :param q: the second large prime 

738 

739 :return: tuple (e, d) with the encryption and decryption exponents. 

740 """ 

741 

742 return calculate_keys_custom_exponent(p, q, DEFAULT_EXPONENT) 

743 

744 

745def gen_keys( 

746 nbits: int, 

747 getprime_func: typing.Callable[[int], int], 

748 accurate: bool = True, 

749 exponent: int = DEFAULT_EXPONENT, 

750) -> typing.Tuple[int, int, int, int]: 

751 """Generate RSA keys of nbits bits. Returns (p, q, e, d). 

752 

753 Note: this can take a long time, depending on the key size. 

754 

755 :param nbits: the total number of bits in ``p`` and ``q``. Both ``p`` and 

756 ``q`` will use ``nbits/2`` bits. 

757 :param getprime_func: either :py:func:`rsa.prime.getprime` or a function 

758 with similar signature. 

759 :param exponent: the exponent for the key; only change this if you know 

760 what you're doing, as the exponent influences how difficult your 

761 private key can be cracked. A very common choice for e is 65537. 

762 :type exponent: int 

763 """ 

764 

765 # Regenerate p and q values, until calculate_keys doesn't raise a 

766 # ValueError. 

767 while True: 

768 (p, q) = find_p_q(nbits // 2, getprime_func, accurate) 

769 try: 

770 (e, d) = calculate_keys_custom_exponent(p, q, exponent=exponent) 

771 break 

772 except ValueError: 

773 pass 

774 

775 return p, q, e, d 

776 

777 

778def newkeys( 

779 nbits: int, 

780 accurate: bool = True, 

781 poolsize: int = 1, 

782 exponent: int = DEFAULT_EXPONENT, 

783) -> typing.Tuple[PublicKey, PrivateKey]: 

784 """Generates public and private keys, and returns them as (pub, priv). 

785 

786 The public key is also known as the 'encryption key', and is a 

787 :py:class:`rsa.PublicKey` object. The private key is also known as the 

788 'decryption key' and is a :py:class:`rsa.PrivateKey` object. 

789 

790 :param nbits: the number of bits required to store ``n = p*q``. 

791 :param accurate: when True, ``n`` will have exactly the number of bits you 

792 asked for. However, this makes key generation much slower. When False, 

793 `n`` may have slightly less bits. 

794 :param poolsize: the number of processes to use to generate the prime 

795 numbers. If set to a number > 1, a parallel algorithm will be used. 

796 This requires Python 2.6 or newer. 

797 :param exponent: the exponent for the key; only change this if you know 

798 what you're doing, as the exponent influences how difficult your 

799 private key can be cracked. A very common choice for e is 65537. 

800 :type exponent: int 

801 

802 :returns: a tuple (:py:class:`rsa.PublicKey`, :py:class:`rsa.PrivateKey`) 

803 

804 The ``poolsize`` parameter was added in *Python-RSA 3.1* and requires 

805 Python 2.6 or newer. 

806 

807 """ 

808 

809 if nbits < 16: 

810 raise ValueError("Key too small") 

811 

812 if poolsize < 1: 

813 raise ValueError("Pool size (%i) should be >= 1" % poolsize) 

814 

815 # Determine which getprime function to use 

816 if poolsize > 1: 

817 from rsa import parallel 

818 

819 def getprime_func(nbits: int) -> int: 

820 return parallel.getprime(nbits, poolsize=poolsize) 

821 

822 else: 

823 getprime_func = rsa.prime.getprime 

824 

825 # Generate the key components 

826 (p, q, e, d) = gen_keys(nbits, getprime_func, accurate=accurate, exponent=exponent) 

827 

828 # Create the key objects 

829 n = p * q 

830 

831 return (PublicKey(n, e), PrivateKey(n, e, d, p, q)) 

832 

833 

834__all__ = ["PublicKey", "PrivateKey", "newkeys"] 

835 

836if __name__ == "__main__": 

837 import doctest 

838 

839 try: 

840 for count in range(100): 

841 (failures, tests) = doctest.testmod() 

842 if failures: 

843 break 

844 

845 if (count % 10 == 0 and count) or count == 1: 

846 print("%i times" % count) 

847 except KeyboardInterrupt: 

848 print("Aborted") 

849 else: 

850 print("Doctests done")