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