• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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