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