You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

859 line
27 KiB

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