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
« 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.
15"""RSA key generation code.
17Create new keys with the newkeys() function. It will give you a PublicKey and a
18PrivateKey object.
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.
24.. note::
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.
32"""
34import abc
35import threading
36import typing
37import warnings
39import rsa.prime
40import rsa.pem
41import rsa.common
42import rsa.randnum
43import rsa.core
46DEFAULT_EXPONENT = 65537
49T = typing.TypeVar("T", bound="AbstractKey")
52class AbstractKey(metaclass=abc.ABCMeta):
53 """Abstract superclass for private and public keys."""
55 __slots__ = ("n", "e", "blindfac", "blindfac_inverse", "mutex")
57 def __init__(self, n: int, e: int) -> None:
58 self.n = n
59 self.e = e
61 # These will be computed properly on the first call to blind().
62 self.blindfac = self.blindfac_inverse = -1
64 # Used to protect updates to the blinding factor in multi-threaded
65 # environments.
66 self.mutex = threading.Lock()
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.
73 :param keyfile: contents of a PEM-encoded file that contains
74 the public key.
75 :type keyfile: bytes
77 :return: the loaded key
78 :rtype: AbstractKey
79 """
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.
86 :param keyfile: contents of a DER-encoded file that contains
87 the public key.
88 :type keyfile: bytes
90 :return: the loaded key
91 :rtype: AbstractKey
92 """
94 @abc.abstractmethod
95 def _save_pkcs1_pem(self) -> bytes:
96 """Saves the key in PKCS#1 PEM format, implement in a subclass.
98 :returns: the PEM-encoded key.
99 :rtype: bytes
100 """
102 @abc.abstractmethod
103 def _save_pkcs1_der(self) -> bytes:
104 """Saves the key in PKCS#1 DER format, implement in a subclass.
106 :returns: the DER-encoded key.
107 :rtype: bytes
108 """
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.
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
120 :return: the loaded key
121 :rtype: AbstractKey
122 """
124 methods = {
125 "PEM": cls._load_pkcs1_pem,
126 "DER": cls._load_pkcs1_der,
127 }
129 method = cls._assert_format_exists(format, methods)
130 return method(keyfile)
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'."""
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
146 def save_pkcs1(self, format: str = "PEM") -> bytes:
147 """Saves the key in PKCS#1 DER or PEM format.
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 """
155 methods = {
156 "PEM": self._save_pkcs1_pem,
157 "DER": self._save_pkcs1_der,
158 }
160 method = self._assert_format_exists(format, methods)
161 return method()
163 def blind(self, message: int) -> typing.Tuple[int, int]:
164 """Performs blinding on the message.
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)
170 The blinding is such that message = unblind(decrypt(blind(encrypt(message))).
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
178 def unblind(self, blinded: int, blindfac_inverse: int) -> int:
179 """Performs blinding on the message using random number 'blindfac_inverse'.
181 :param blinded: the blinded message, as integer, to unblind.
182 :param blindfac: the factor to unblind with.
183 :return: the original message.
185 The blinding is such that message = unblind(decrypt(blind(encrypt(message))).
187 See https://en.wikipedia.org/wiki/Blinding_%28cryptography%29
188 """
189 return (blindfac_inverse * blinded) % self.n
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")
198 def _update_blinding_factor(self) -> typing.Tuple[int, int]:
199 """Update blinding factors.
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
207 :return: the new blinding factor and its inverse.
208 """
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)
220 return self.blindfac, self.blindfac_inverse
223class PublicKey(AbstractKey):
224 """Represents a public RSA key.
226 This key is also known as the 'encryption key'. It contains the 'n' and 'e'
227 values.
229 Supports attributes as well as dictionary-like access. Attribute access is
230 faster, though.
232 >>> PublicKey(5, 3)
233 PublicKey(5, 3)
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
245 """
247 __slots__ = ()
249 def __getitem__(self, key: str) -> int:
250 return getattr(self, key)
252 def __repr__(self) -> str:
253 return "PublicKey(%i, %i)" % (self.n, self.e)
255 def __getstate__(self) -> typing.Tuple[int, int]:
256 """Returns the key as tuple for pickling."""
257 return self.n, self.e
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)
264 def __eq__(self, other: typing.Any) -> bool:
265 if other is None:
266 return False
268 if not isinstance(other, PublicKey):
269 return False
271 return self.n == other.n and self.e == other.e
273 def __ne__(self, other: typing.Any) -> bool:
274 return not (self == other)
276 def __hash__(self) -> int:
277 return hash((self.n, self.e))
279 @classmethod
280 def _load_pkcs1_der(cls, keyfile: bytes) -> "PublicKey":
281 """Loads a key in PKCS#1 DER format.
283 :param keyfile: contents of a DER-encoded file that contains the public
284 key.
285 :return: a PublicKey object
287 First let's construct a DER encoded key:
289 >>> import base64
290 >>> b64der = 'MAwCBQCNGmYtAgMBAAE='
291 >>> der = base64.standard_b64decode(b64der)
293 This loads the file:
295 >>> PublicKey._load_pkcs1_der(der)
296 PublicKey(2367317549, 65537)
298 """
300 from pyasn1.codec.der import decoder
301 from rsa.asn1 import AsnPubKey
303 (priv, _) = decoder.decode(keyfile, asn1Spec=AsnPubKey())
304 return cls(n=int(priv["modulus"]), e=int(priv["publicExponent"]))
306 def _save_pkcs1_der(self) -> bytes:
307 """Saves the public key in PKCS#1 DER format.
309 :returns: the DER-encoded public key.
310 :rtype: bytes
311 """
313 from pyasn1.codec.der import encoder
314 from rsa.asn1 import AsnPubKey
316 # Create the ASN object
317 asn_key = AsnPubKey()
318 asn_key.setComponentByName("modulus", self.n)
319 asn_key.setComponentByName("publicExponent", self.e)
321 return encoder.encode(asn_key)
323 @classmethod
324 def _load_pkcs1_pem(cls, keyfile: bytes) -> "PublicKey":
325 """Loads a PKCS#1 PEM-encoded public key file.
327 The contents of the file before the "-----BEGIN RSA PUBLIC KEY-----" and
328 after the "-----END RSA PUBLIC KEY-----" lines is ignored.
330 :param keyfile: contents of a PEM-encoded file that contains the public
331 key.
332 :return: a PublicKey object
333 """
335 der = rsa.pem.load_pem(keyfile, "RSA PUBLIC KEY")
336 return cls._load_pkcs1_der(der)
338 def _save_pkcs1_pem(self) -> bytes:
339 """Saves a PKCS#1 PEM-encoded public key file.
341 :return: contents of a PEM-encoded file that contains the public key.
342 :rtype: bytes
343 """
345 der = self._save_pkcs1_der()
346 return rsa.pem.save_pem(der, "RSA PUBLIC KEY")
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.
352 These files can be recognised in that they start with BEGIN PUBLIC KEY
353 rather than BEGIN RSA PUBLIC KEY.
355 The contents of the file before the "-----BEGIN PUBLIC KEY-----" and
356 after the "-----END PUBLIC KEY-----" lines is ignored.
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 """
364 der = rsa.pem.load_pem(keyfile, "PUBLIC KEY")
365 return cls.load_pkcs1_openssl_der(der)
367 @classmethod
368 def load_pkcs1_openssl_der(cls, keyfile: bytes) -> "PublicKey":
369 """Loads a PKCS#1 DER-encoded public key file from OpenSSL.
371 :param keyfile: contents of a DER-encoded file that contains the public
372 key, from OpenSSL.
373 :return: a PublicKey object
374 """
376 from rsa.asn1 import OpenSSLPubKey
377 from pyasn1.codec.der import decoder
378 from pyasn1.type import univ
380 (keyinfo, _) = decoder.decode(keyfile, asn1Spec=OpenSSLPubKey())
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")
385 return cls._load_pkcs1_der(keyinfo["key"][1:])
388class PrivateKey(AbstractKey):
389 """Represents a private RSA key.
391 This key is also known as the 'decryption key'. It contains the 'n', 'e',
392 'd', 'p', 'q' and other values.
394 Supports attributes as well as dictionary-like access. Attribute access is
395 faster, though.
397 >>> PrivateKey(3247, 65537, 833, 191, 17)
398 PrivateKey(3247, 65537, 833, 191, 17)
400 exp1, exp2 and coef will be calculated:
402 >>> pk = PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
403 >>> pk.exp1
404 55063
405 >>> pk.exp2
406 10095
407 >>> pk.coef
408 50797
410 """
412 __slots__ = ("d", "p", "q", "exp1", "exp2", "coef")
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
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)
425 def __getitem__(self, key: str) -> int:
426 return getattr(self, key)
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 )
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
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)
446 def __eq__(self, other: typing.Any) -> bool:
447 if other is None:
448 return False
450 if not isinstance(other, PrivateKey):
451 return False
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 )
464 def __ne__(self, other: typing.Any) -> bool:
465 return not (self == other)
467 def __hash__(self) -> int:
468 return hash((self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef))
470 def blinded_decrypt(self, encrypted: int) -> int:
471 """Decrypts the message using blinding to prevent side-channel attacks.
473 :param encrypted: the encrypted message
474 :type encrypted: int
476 :returns: the decrypted message
477 :rtype: int
478 """
480 # Blinding and un-blinding should be using the same factor
481 blinded, blindfac_inverse = self.blind(encrypted)
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
492 return self.unblind(decrypted, blindfac_inverse)
495 @classmethod
496 def _load_pkcs1_der(cls, keyfile: bytes) -> "PrivateKey":
497 """Loads a key in PKCS#1 DER format.
499 :param keyfile: contents of a DER-encoded file that contains the private
500 key.
501 :type keyfile: bytes
502 :return: a PrivateKey object
504 First let's construct a DER encoded key:
506 >>> import base64
507 >>> b64der = 'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt'
508 >>> der = base64.standard_b64decode(b64der)
510 This loads the file:
512 >>> PrivateKey._load_pkcs1_der(der)
513 PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
515 """
517 from pyasn1.codec.der import decoder
519 (priv, _) = decoder.decode(keyfile)
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 # }
536 if priv[0] != 0:
537 raise ValueError("Unable to read this file, version %s != 0" % priv[0])
539 as_ints = map(int, priv[1:6])
540 key = cls(*as_ints)
542 exp1, exp2, coef = map(int, priv[6:9])
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 )
552 return key
554 def _save_pkcs1_der(self) -> bytes:
555 """Saves the private key in PKCS#1 DER format.
557 :returns: the DER-encoded private key.
558 :rtype: bytes
559 """
561 from pyasn1.type import univ, namedtype
562 from pyasn1.codec.der import encoder
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 )
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)
589 return encoder.encode(asn_key)
591 @classmethod
592 def _load_pkcs1_pem(cls, keyfile: bytes) -> "PrivateKey":
593 """Loads a PKCS#1 PEM-encoded private key file.
595 The contents of the file before the "-----BEGIN RSA PRIVATE KEY-----" and
596 after the "-----END RSA PRIVATE KEY-----" lines is ignored.
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 """
604 der = rsa.pem.load_pem(keyfile, b"RSA PRIVATE KEY")
605 return cls._load_pkcs1_der(der)
607 def _save_pkcs1_pem(self) -> bytes:
608 """Saves a PKCS#1 PEM-encoded private key file.
610 :return: contents of a PEM-encoded file that contains the private key.
611 :rtype: bytes
612 """
614 der = self._save_pkcs1_der()
615 return rsa.pem.save_pem(der, b"RSA PRIVATE KEY")
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.
625 The resulting p * q has exactly 2 * nbits bits, and the returned p and q
626 will not be equal.
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`.
632 *Introduced in Python-RSA 3.1*
634 :param accurate: whether to enable accurate mode or not.
635 :returns: (p, q), where p > q
637 >>> (p, q) = find_p_q(128)
638 >>> from rsa import common
639 >>> common.bit_size(p * q)
640 256
642 When not in accurate mode, the number of bits can be slightly less
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
651 """
653 total_bits = nbits * 2
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
661 # Choose the two initial primes
662 p = getprime_func(pbits)
663 q = getprime_func(qbits)
665 def is_acceptable(p: int, q: int) -> bool:
666 """Returns True iff p and q are acceptable:
668 - p and q differ
669 - (p * q) has the right nr of bits (when accurate=True)
670 """
672 if p == q:
673 return False
675 if not accurate:
676 return True
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
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)
691 change_p = not change_p
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)
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)
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
709 """
711 phi_n = (p - 1) * (q - 1)
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
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 )
729 return exponent, d
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)
736 :param p: the first large prime
737 :param q: the second large prime
739 :return: tuple (e, d) with the encryption and decryption exponents.
740 """
742 return calculate_keys_custom_exponent(p, q, DEFAULT_EXPONENT)
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).
753 Note: this can take a long time, depending on the key size.
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 """
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
775 return p, q, e, d
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).
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.
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
802 :returns: a tuple (:py:class:`rsa.PublicKey`, :py:class:`rsa.PrivateKey`)
804 The ``poolsize`` parameter was added in *Python-RSA 3.1* and requires
805 Python 2.6 or newer.
807 """
809 if nbits < 16:
810 raise ValueError("Key too small")
812 if poolsize < 1:
813 raise ValueError("Pool size (%i) should be >= 1" % poolsize)
815 # Determine which getprime function to use
816 if poolsize > 1:
817 from rsa import parallel
819 def getprime_func(nbits: int) -> int:
820 return parallel.getprime(nbits, poolsize=poolsize)
822 else:
823 getprime_func = rsa.prime.getprime
825 # Generate the key components
826 (p, q, e, d) = gen_keys(nbits, getprime_func, accurate=accurate, exponent=exponent)
828 # Create the key objects
829 n = p * q
831 return (PublicKey(n, e), PrivateKey(n, e, d, p, q))
834__all__ = ["PublicKey", "PrivateKey", "newkeys"]
836if __name__ == "__main__":
837 import doctest
839 try:
840 for count in range(100):
841 (failures, tests) = doctest.testmod()
842 if failures:
843 break
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")