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 logging 35import typing 36import warnings 37 38import rsa.prime 39import rsa.pem 40import rsa.common 41import rsa.randnum 42import rsa.core 43 44 45log = logging.getLogger(__name__) 46DEFAULT_EXPONENT = 65537 47 48 49class AbstractKey: 50 """Abstract superclass for private and public keys.""" 51 52 __slots__ = ('n', 'e', 'blindfac', 'blindfac_inverse') 53 54 def __init__(self, n: int, e: int) -> None: 55 self.n = n 56 self.e = e 57 58 # These will be computed properly on the first call to blind(). 59 self.blindfac = self.blindfac_inverse = -1 60 61 @classmethod 62 def _load_pkcs1_pem(cls, keyfile: bytes) -> 'AbstractKey': 63 """Loads a key in PKCS#1 PEM format, implement in a subclass. 64 65 :param keyfile: contents of a PEM-encoded file that contains 66 the public key. 67 :type keyfile: bytes 68 69 :return: the loaded key 70 :rtype: AbstractKey 71 """ 72 73 @classmethod 74 def _load_pkcs1_der(cls, keyfile: bytes) -> 'AbstractKey': 75 """Loads a key in PKCS#1 PEM format, implement in a subclass. 76 77 :param keyfile: contents of a DER-encoded file that contains 78 the public key. 79 :type keyfile: bytes 80 81 :return: the loaded key 82 :rtype: AbstractKey 83 """ 84 85 def _save_pkcs1_pem(self) -> bytes: 86 """Saves the key in PKCS#1 PEM format, implement in a subclass. 87 88 :returns: the PEM-encoded key. 89 :rtype: bytes 90 """ 91 92 def _save_pkcs1_der(self) -> bytes: 93 """Saves the key in PKCS#1 DER format, implement in a subclass. 94 95 :returns: the DER-encoded key. 96 :rtype: bytes 97 """ 98 99 @classmethod 100 def load_pkcs1(cls, keyfile: bytes, format: str = 'PEM') -> 'AbstractKey': 101 """Loads a key in PKCS#1 DER or PEM format. 102 103 :param keyfile: contents of a DER- or PEM-encoded file that contains 104 the key. 105 :type keyfile: bytes 106 :param format: the format of the file to load; 'PEM' or 'DER' 107 :type format: str 108 109 :return: the loaded key 110 :rtype: AbstractKey 111 """ 112 113 methods = { 114 'PEM': cls._load_pkcs1_pem, 115 'DER': cls._load_pkcs1_der, 116 } 117 118 method = cls._assert_format_exists(format, methods) 119 return method(keyfile) 120 121 @staticmethod 122 def _assert_format_exists(file_format: str, methods: typing.Mapping[str, typing.Callable]) \ 123 -> typing.Callable: 124 """Checks whether the given file format exists in 'methods'. 125 """ 126 127 try: 128 return methods[file_format] 129 except KeyError: 130 formats = ', '.join(sorted(methods.keys())) 131 raise ValueError('Unsupported format: %r, try one of %s' % (file_format, 132 formats)) 133 134 def save_pkcs1(self, format: str = 'PEM') -> bytes: 135 """Saves the key in PKCS#1 DER or PEM format. 136 137 :param format: the format to save; 'PEM' or 'DER' 138 :type format: str 139 :returns: the DER- or PEM-encoded key. 140 :rtype: bytes 141 """ 142 143 methods = { 144 'PEM': self._save_pkcs1_pem, 145 'DER': self._save_pkcs1_der, 146 } 147 148 method = self._assert_format_exists(format, methods) 149 return method() 150 151 def blind(self, message: int) -> int: 152 """Performs blinding on the message using random number 'r'. 153 154 :param message: the message, as integer, to blind. 155 :type message: int 156 :param r: the random number to blind with. 157 :type r: int 158 :return: the blinded message. 159 :rtype: int 160 161 The blinding is such that message = unblind(decrypt(blind(encrypt(message))). 162 163 See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29 164 """ 165 self._update_blinding_factor() 166 return (message * pow(self.blindfac, self.e, self.n)) % self.n 167 168 def unblind(self, blinded: int) -> int: 169 """Performs blinding on the message using random number 'r'. 170 171 :param blinded: the blinded message, as integer, to unblind. 172 :param r: the random number to unblind with. 173 :return: the original message. 174 175 The blinding is such that message = unblind(decrypt(blind(encrypt(message))). 176 177 See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29 178 """ 179 180 return (self.blindfac_inverse * blinded) % self.n 181 182 def _initial_blinding_factor(self) -> int: 183 for _ in range(1000): 184 blind_r = rsa.randnum.randint(self.n - 1) 185 if rsa.prime.are_relatively_prime(self.n, blind_r): 186 return blind_r 187 raise RuntimeError('unable to find blinding factor') 188 189 def _update_blinding_factor(self): 190 if self.blindfac < 0: 191 # Compute initial blinding factor, which is rather slow to do. 192 self.blindfac = self._initial_blinding_factor() 193 self.blindfac_inverse = rsa.common.inverse(self.blindfac, self.n) 194 else: 195 # Reuse previous blinding factor as per section 9 of 'A Timing 196 # Attack against RSA with the Chinese Remainder Theorem' by Werner 197 # Schindler. 198 # See https://tls.mbed.org/public/WSchindler-RSA_Timing_Attack.pdf 199 self.blindfac = pow(self.blindfac, 2, self.n) 200 self.blindfac_inverse = pow(self.blindfac_inverse, 2, self.n) 201 202class PublicKey(AbstractKey): 203 """Represents a public RSA key. 204 205 This key is also known as the 'encryption key'. It contains the 'n' and 'e' 206 values. 207 208 Supports attributes as well as dictionary-like access. Attribute access is 209 faster, though. 210 211 >>> PublicKey(5, 3) 212 PublicKey(5, 3) 213 214 >>> key = PublicKey(5, 3) 215 >>> key.n 216 5 217 >>> key['n'] 218 5 219 >>> key.e 220 3 221 >>> key['e'] 222 3 223 224 """ 225 226 __slots__ = ('n', 'e') 227 228 def __getitem__(self, key: str) -> int: 229 return getattr(self, key) 230 231 def __repr__(self) -> str: 232 return 'PublicKey(%i, %i)' % (self.n, self.e) 233 234 def __getstate__(self) -> typing.Tuple[int, int]: 235 """Returns the key as tuple for pickling.""" 236 return self.n, self.e 237 238 def __setstate__(self, state: typing.Tuple[int, int]) -> None: 239 """Sets the key from tuple.""" 240 self.n, self.e = state 241 242 def __eq__(self, other: typing.Any) -> bool: 243 if other is None: 244 return False 245 246 if not isinstance(other, PublicKey): 247 return False 248 249 return self.n == other.n and self.e == other.e 250 251 def __ne__(self, other: typing.Any) -> bool: 252 return not (self == other) 253 254 def __hash__(self) -> int: 255 return hash((self.n, self.e)) 256 257 @classmethod 258 def _load_pkcs1_der(cls, keyfile: bytes) -> 'PublicKey': 259 """Loads a key in PKCS#1 DER format. 260 261 :param keyfile: contents of a DER-encoded file that contains the public 262 key. 263 :return: a PublicKey object 264 265 First let's construct a DER encoded key: 266 267 >>> import base64 268 >>> b64der = 'MAwCBQCNGmYtAgMBAAE=' 269 >>> der = base64.standard_b64decode(b64der) 270 271 This loads the file: 272 273 >>> PublicKey._load_pkcs1_der(der) 274 PublicKey(2367317549, 65537) 275 276 """ 277 278 from pyasn1.codec.der import decoder 279 from rsa.asn1 import AsnPubKey 280 281 (priv, _) = decoder.decode(keyfile, asn1Spec=AsnPubKey()) 282 return cls(n=int(priv['modulus']), e=int(priv['publicExponent'])) 283 284 def _save_pkcs1_der(self) -> bytes: 285 """Saves the public key in PKCS#1 DER format. 286 287 :returns: the DER-encoded public key. 288 :rtype: bytes 289 """ 290 291 from pyasn1.codec.der import encoder 292 from rsa.asn1 import AsnPubKey 293 294 # Create the ASN object 295 asn_key = AsnPubKey() 296 asn_key.setComponentByName('modulus', self.n) 297 asn_key.setComponentByName('publicExponent', self.e) 298 299 return encoder.encode(asn_key) 300 301 @classmethod 302 def _load_pkcs1_pem(cls, keyfile: bytes) -> 'PublicKey': 303 """Loads a PKCS#1 PEM-encoded public key file. 304 305 The contents of the file before the "-----BEGIN RSA PUBLIC KEY-----" and 306 after the "-----END RSA PUBLIC KEY-----" lines is ignored. 307 308 :param keyfile: contents of a PEM-encoded file that contains the public 309 key. 310 :return: a PublicKey object 311 """ 312 313 der = rsa.pem.load_pem(keyfile, 'RSA PUBLIC KEY') 314 return cls._load_pkcs1_der(der) 315 316 def _save_pkcs1_pem(self) -> bytes: 317 """Saves a PKCS#1 PEM-encoded public key file. 318 319 :return: contents of a PEM-encoded file that contains the public key. 320 :rtype: bytes 321 """ 322 323 der = self._save_pkcs1_der() 324 return rsa.pem.save_pem(der, 'RSA PUBLIC KEY') 325 326 @classmethod 327 def load_pkcs1_openssl_pem(cls, keyfile: bytes) -> 'PublicKey': 328 """Loads a PKCS#1.5 PEM-encoded public key file from OpenSSL. 329 330 These files can be recognised in that they start with BEGIN PUBLIC KEY 331 rather than BEGIN RSA PUBLIC KEY. 332 333 The contents of the file before the "-----BEGIN PUBLIC KEY-----" and 334 after the "-----END PUBLIC KEY-----" lines is ignored. 335 336 :param keyfile: contents of a PEM-encoded file that contains the public 337 key, from OpenSSL. 338 :type keyfile: bytes 339 :return: a PublicKey object 340 """ 341 342 der = rsa.pem.load_pem(keyfile, 'PUBLIC KEY') 343 return cls.load_pkcs1_openssl_der(der) 344 345 @classmethod 346 def load_pkcs1_openssl_der(cls, keyfile: bytes) -> 'PublicKey': 347 """Loads a PKCS#1 DER-encoded public key file from OpenSSL. 348 349 :param keyfile: contents of a DER-encoded file that contains the public 350 key, from OpenSSL. 351 :return: a PublicKey object 352 """ 353 354 from rsa.asn1 import OpenSSLPubKey 355 from pyasn1.codec.der import decoder 356 from pyasn1.type import univ 357 358 (keyinfo, _) = decoder.decode(keyfile, asn1Spec=OpenSSLPubKey()) 359 360 if keyinfo['header']['oid'] != univ.ObjectIdentifier('1.2.840.113549.1.1.1'): 361 raise TypeError("This is not a DER-encoded OpenSSL-compatible public key") 362 363 return cls._load_pkcs1_der(keyinfo['key'][1:]) 364 365 366class PrivateKey(AbstractKey): 367 """Represents a private RSA key. 368 369 This key is also known as the 'decryption key'. It contains the 'n', 'e', 370 'd', 'p', 'q' and other values. 371 372 Supports attributes as well as dictionary-like access. Attribute access is 373 faster, though. 374 375 >>> PrivateKey(3247, 65537, 833, 191, 17) 376 PrivateKey(3247, 65537, 833, 191, 17) 377 378 exp1, exp2 and coef will be calculated: 379 380 >>> pk = PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) 381 >>> pk.exp1 382 55063 383 >>> pk.exp2 384 10095 385 >>> pk.coef 386 50797 387 388 """ 389 390 __slots__ = ('n', 'e', 'd', 'p', 'q', 'exp1', 'exp2', 'coef') 391 392 def __init__(self, n: int, e: int, d: int, p: int, q: int) -> None: 393 AbstractKey.__init__(self, n, e) 394 self.d = d 395 self.p = p 396 self.q = q 397 398 # Calculate exponents and coefficient. 399 self.exp1 = int(d % (p - 1)) 400 self.exp2 = int(d % (q - 1)) 401 self.coef = rsa.common.inverse(q, p) 402 403 def __getitem__(self, key: str) -> int: 404 return getattr(self, key) 405 406 def __repr__(self) -> str: 407 return 'PrivateKey(%i, %i, %i, %i, %i)' % (self.n, self.e, self.d, self.p, self.q) 408 409 def __getstate__(self) -> typing.Tuple[int, int, int, int, int, int, int, int]: 410 """Returns the key as tuple for pickling.""" 411 return self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef 412 413 def __setstate__(self, state: typing.Tuple[int, int, int, int, int, int, int, int]) -> None: 414 """Sets the key from tuple.""" 415 self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef = state 416 417 def __eq__(self, other: typing.Any) -> bool: 418 if other is None: 419 return False 420 421 if not isinstance(other, PrivateKey): 422 return False 423 424 return (self.n == other.n and 425 self.e == other.e and 426 self.d == other.d and 427 self.p == other.p and 428 self.q == other.q and 429 self.exp1 == other.exp1 and 430 self.exp2 == other.exp2 and 431 self.coef == other.coef) 432 433 def __ne__(self, other: typing.Any) -> bool: 434 return not (self == other) 435 436 def __hash__(self) -> int: 437 return hash((self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef)) 438 439 def blinded_decrypt(self, encrypted: int) -> int: 440 """Decrypts the message using blinding to prevent side-channel attacks. 441 442 :param encrypted: the encrypted message 443 :type encrypted: int 444 445 :returns: the decrypted message 446 :rtype: int 447 """ 448 449 blinded = self.blind(encrypted) # blind before decrypting 450 decrypted = rsa.core.decrypt_int(blinded, self.d, self.n) 451 return self.unblind(decrypted) 452 453 def blinded_encrypt(self, message: int) -> int: 454 """Encrypts the message using blinding to prevent side-channel attacks. 455 456 :param message: the message to encrypt 457 :type message: int 458 459 :returns: the encrypted message 460 :rtype: int 461 """ 462 463 blinded = self.blind(message) # blind before encrypting 464 encrypted = rsa.core.encrypt_int(blinded, self.d, self.n) 465 return self.unblind(encrypted) 466 467 @classmethod 468 def _load_pkcs1_der(cls, keyfile: bytes) -> 'PrivateKey': 469 """Loads a key in PKCS#1 DER format. 470 471 :param keyfile: contents of a DER-encoded file that contains the private 472 key. 473 :type keyfile: bytes 474 :return: a PrivateKey object 475 476 First let's construct a DER encoded key: 477 478 >>> import base64 479 >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt' 480 >>> der = base64.standard_b64decode(b64der) 481 482 This loads the file: 483 484 >>> PrivateKey._load_pkcs1_der(der) 485 PrivateKey(3727264081, 65537, 3349121513, 65063, 57287) 486 487 """ 488 489 from pyasn1.codec.der import decoder 490 (priv, _) = decoder.decode(keyfile) 491 492 # ASN.1 contents of DER encoded private key: 493 # 494 # RSAPrivateKey ::= SEQUENCE { 495 # version Version, 496 # modulus INTEGER, -- n 497 # publicExponent INTEGER, -- e 498 # privateExponent INTEGER, -- d 499 # prime1 INTEGER, -- p 500 # prime2 INTEGER, -- q 501 # exponent1 INTEGER, -- d mod (p-1) 502 # exponent2 INTEGER, -- d mod (q-1) 503 # coefficient INTEGER, -- (inverse of q) mod p 504 # otherPrimeInfos OtherPrimeInfos OPTIONAL 505 # } 506 507 if priv[0] != 0: 508 raise ValueError('Unable to read this file, version %s != 0' % priv[0]) 509 510 as_ints = map(int, priv[1:6]) 511 key = cls(*as_ints) 512 513 exp1, exp2, coef = map(int, priv[6:9]) 514 515 if (key.exp1, key.exp2, key.coef) != (exp1, exp2, coef): 516 warnings.warn( 517 'You have provided a malformed keyfile. Either the exponents ' 518 'or the coefficient are incorrect. Using the correct values ' 519 'instead.', 520 UserWarning, 521 ) 522 523 return key 524 525 def _save_pkcs1_der(self) -> bytes: 526 """Saves the private key in PKCS#1 DER format. 527 528 :returns: the DER-encoded private key. 529 :rtype: bytes 530 """ 531 532 from pyasn1.type import univ, namedtype 533 from pyasn1.codec.der import encoder 534 535 class AsnPrivKey(univ.Sequence): 536 componentType = namedtype.NamedTypes( 537 namedtype.NamedType('version', univ.Integer()), 538 namedtype.NamedType('modulus', univ.Integer()), 539 namedtype.NamedType('publicExponent', univ.Integer()), 540 namedtype.NamedType('privateExponent', univ.Integer()), 541 namedtype.NamedType('prime1', univ.Integer()), 542 namedtype.NamedType('prime2', univ.Integer()), 543 namedtype.NamedType('exponent1', univ.Integer()), 544 namedtype.NamedType('exponent2', univ.Integer()), 545 namedtype.NamedType('coefficient', univ.Integer()), 546 ) 547 548 # Create the ASN object 549 asn_key = AsnPrivKey() 550 asn_key.setComponentByName('version', 0) 551 asn_key.setComponentByName('modulus', self.n) 552 asn_key.setComponentByName('publicExponent', self.e) 553 asn_key.setComponentByName('privateExponent', self.d) 554 asn_key.setComponentByName('prime1', self.p) 555 asn_key.setComponentByName('prime2', self.q) 556 asn_key.setComponentByName('exponent1', self.exp1) 557 asn_key.setComponentByName('exponent2', self.exp2) 558 asn_key.setComponentByName('coefficient', self.coef) 559 560 return encoder.encode(asn_key) 561 562 @classmethod 563 def _load_pkcs1_pem(cls, keyfile: bytes) -> 'PrivateKey': 564 """Loads a PKCS#1 PEM-encoded private key file. 565 566 The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and 567 after the "-----END RSA PRIVATE KEY-----" lines is ignored. 568 569 :param keyfile: contents of a PEM-encoded file that contains the private 570 key. 571 :type keyfile: bytes 572 :return: a PrivateKey object 573 """ 574 575 der = rsa.pem.load_pem(keyfile, b'RSA PRIVATE KEY') 576 return cls._load_pkcs1_der(der) 577 578 def _save_pkcs1_pem(self) -> bytes: 579 """Saves a PKCS#1 PEM-encoded private key file. 580 581 :return: contents of a PEM-encoded file that contains the private key. 582 :rtype: bytes 583 """ 584 585 der = self._save_pkcs1_der() 586 return rsa.pem.save_pem(der, b'RSA PRIVATE KEY') 587 588 589def find_p_q(nbits: int, 590 getprime_func: typing.Callable[[int], int] = rsa.prime.getprime, 591 accurate: bool = True) -> typing.Tuple[int, int]: 592 """Returns a tuple of two different primes of nbits bits each. 593 594 The resulting p * q has exacty 2 * nbits bits, and the returned p and q 595 will not be equal. 596 597 :param nbits: the number of bits in each of p and q. 598 :param getprime_func: the getprime function, defaults to 599 :py:func:`rsa.prime.getprime`. 600 601 *Introduced in Python-RSA 3.1* 602 603 :param accurate: whether to enable accurate mode or not. 604 :returns: (p, q), where p > q 605 606 >>> (p, q) = find_p_q(128) 607 >>> from rsa import common 608 >>> common.bit_size(p * q) 609 256 610 611 When not in accurate mode, the number of bits can be slightly less 612 613 >>> (p, q) = find_p_q(128, accurate=False) 614 >>> from rsa import common 615 >>> common.bit_size(p * q) <= 256 616 True 617 >>> common.bit_size(p * q) > 240 618 True 619 620 """ 621 622 total_bits = nbits * 2 623 624 # Make sure that p and q aren't too close or the factoring programs can 625 # factor n. 626 shift = nbits // 16 627 pbits = nbits + shift 628 qbits = nbits - shift 629 630 # Choose the two initial primes 631 log.debug('find_p_q(%i): Finding p', nbits) 632 p = getprime_func(pbits) 633 log.debug('find_p_q(%i): Finding q', nbits) 634 q = getprime_func(qbits) 635 636 def is_acceptable(p: int, q: int) -> bool: 637 """Returns True iff p and q are acceptable: 638 639 - p and q differ 640 - (p * q) has the right nr of bits (when accurate=True) 641 """ 642 643 if p == q: 644 return False 645 646 if not accurate: 647 return True 648 649 # Make sure we have just the right amount of bits 650 found_size = rsa.common.bit_size(p * q) 651 return total_bits == found_size 652 653 # Keep choosing other primes until they match our requirements. 654 change_p = False 655 while not is_acceptable(p, q): 656 # Change p on one iteration and q on the other 657 if change_p: 658 p = getprime_func(pbits) 659 else: 660 q = getprime_func(qbits) 661 662 change_p = not change_p 663 664 # We want p > q as described on 665 # http://www.di-mgt.com.au/rsa_alg.html#crt 666 return max(p, q), min(p, q) 667 668 669def calculate_keys_custom_exponent(p: int, q: int, exponent: int) -> typing.Tuple[int, int]: 670 """Calculates an encryption and a decryption key given p, q and an exponent, 671 and returns them as a tuple (e, d) 672 673 :param p: the first large prime 674 :param q: the second large prime 675 :param exponent: the exponent for the key; only change this if you know 676 what you're doing, as the exponent influences how difficult your 677 private key can be cracked. A very common choice for e is 65537. 678 :type exponent: int 679 680 """ 681 682 phi_n = (p - 1) * (q - 1) 683 684 try: 685 d = rsa.common.inverse(exponent, phi_n) 686 except rsa.common.NotRelativePrimeError as ex: 687 raise rsa.common.NotRelativePrimeError( 688 exponent, phi_n, ex.d, 689 msg="e (%d) and phi_n (%d) are not relatively prime (divider=%i)" % 690 (exponent, phi_n, ex.d)) 691 692 if (exponent * d) % phi_n != 1: 693 raise ValueError("e (%d) and d (%d) are not mult. inv. modulo " 694 "phi_n (%d)" % (exponent, d, phi_n)) 695 696 return exponent, d 697 698 699def calculate_keys(p: int, q: int) -> typing.Tuple[int, int]: 700 """Calculates an encryption and a decryption key given p and q, and 701 returns them as a tuple (e, d) 702 703 :param p: the first large prime 704 :param q: the second large prime 705 706 :return: tuple (e, d) with the encryption and decryption exponents. 707 """ 708 709 return calculate_keys_custom_exponent(p, q, DEFAULT_EXPONENT) 710 711 712def gen_keys(nbits: int, 713 getprime_func: typing.Callable[[int], int], 714 accurate: bool = True, 715 exponent: int = DEFAULT_EXPONENT) -> typing.Tuple[int, int, int, int]: 716 """Generate RSA keys of nbits bits. Returns (p, q, e, d). 717 718 Note: this can take a long time, depending on the key size. 719 720 :param nbits: the total number of bits in ``p`` and ``q``. Both ``p`` and 721 ``q`` will use ``nbits/2`` bits. 722 :param getprime_func: either :py:func:`rsa.prime.getprime` or a function 723 with similar signature. 724 :param exponent: the exponent for the key; only change this if you know 725 what you're doing, as the exponent influences how difficult your 726 private key can be cracked. A very common choice for e is 65537. 727 :type exponent: int 728 """ 729 730 # Regenerate p and q values, until calculate_keys doesn't raise a 731 # ValueError. 732 while True: 733 (p, q) = find_p_q(nbits // 2, getprime_func, accurate) 734 try: 735 (e, d) = calculate_keys_custom_exponent(p, q, exponent=exponent) 736 break 737 except ValueError: 738 pass 739 740 return p, q, e, d 741 742 743def newkeys(nbits: int, 744 accurate: bool = True, 745 poolsize: int = 1, 746 exponent: int = DEFAULT_EXPONENT) -> typing.Tuple[PublicKey, PrivateKey]: 747 """Generates public and private keys, and returns them as (pub, priv). 748 749 The public key is also known as the 'encryption key', and is a 750 :py:class:`rsa.PublicKey` object. The private key is also known as the 751 'decryption key' and is a :py:class:`rsa.PrivateKey` object. 752 753 :param nbits: the number of bits required to store ``n = p*q``. 754 :param accurate: when True, ``n`` will have exactly the number of bits you 755 asked for. However, this makes key generation much slower. When False, 756 `n`` may have slightly less bits. 757 :param poolsize: the number of processes to use to generate the prime 758 numbers. If set to a number > 1, a parallel algorithm will be used. 759 This requires Python 2.6 or newer. 760 :param exponent: the exponent for the key; only change this if you know 761 what you're doing, as the exponent influences how difficult your 762 private key can be cracked. A very common choice for e is 65537. 763 :type exponent: int 764 765 :returns: a tuple (:py:class:`rsa.PublicKey`, :py:class:`rsa.PrivateKey`) 766 767 The ``poolsize`` parameter was added in *Python-RSA 3.1* and requires 768 Python 2.6 or newer. 769 770 """ 771 772 if nbits < 16: 773 raise ValueError('Key too small') 774 775 if poolsize < 1: 776 raise ValueError('Pool size (%i) should be >= 1' % poolsize) 777 778 # Determine which getprime function to use 779 if poolsize > 1: 780 from rsa import parallel 781 782 def getprime_func(nbits: int) -> int: 783 return parallel.getprime(nbits, poolsize=poolsize) 784 else: 785 getprime_func = rsa.prime.getprime 786 787 # Generate the key components 788 (p, q, e, d) = gen_keys(nbits, getprime_func, accurate=accurate, exponent=exponent) 789 790 # Create the key objects 791 n = p * q 792 793 return ( 794 PublicKey(n, e), 795 PrivateKey(n, e, d, p, q) 796 ) 797 798 799__all__ = ['PublicKey', 'PrivateKey', 'newkeys'] 800 801if __name__ == '__main__': 802 import doctest 803 804 try: 805 for count in range(100): 806 (failures, tests) = doctest.testmod() 807 if failures: 808 break 809 810 if (count % 10 == 0 and count) or count == 1: 811 print('%i times' % count) 812 except KeyboardInterrupt: 813 print('Aborted') 814 else: 815 print('Doctests done') 816