Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py : 42%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
6import abc
7import typing
8from math import gcd
10from cryptography import utils
11from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
12from cryptography.hazmat.backends import _get_backend
13from cryptography.hazmat.backends.interfaces import RSABackend
14from cryptography.hazmat.primitives import _serialization, hashes
15from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding
16from cryptography.hazmat.primitives.asymmetric import (
17 AsymmetricSignatureContext,
18 AsymmetricVerificationContext,
19 utils as asym_utils,
20)
23class RSAPrivateKey(metaclass=abc.ABCMeta):
24 @abc.abstractmethod
25 def signer(
26 self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm
27 ) -> AsymmetricSignatureContext:
28 """
29 Returns an AsymmetricSignatureContext used for signing data.
30 """
32 @abc.abstractmethod
33 def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes:
34 """
35 Decrypts the provided ciphertext.
36 """
38 @abc.abstractproperty
39 def key_size(self) -> int:
40 """
41 The bit length of the public modulus.
42 """
44 @abc.abstractmethod
45 def public_key(self) -> "RSAPublicKey":
46 """
47 The RSAPublicKey associated with this private key.
48 """
50 @abc.abstractmethod
51 def sign(
52 self,
53 data: bytes,
54 padding: AsymmetricPadding,
55 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm],
56 ) -> bytes:
57 """
58 Signs the data.
59 """
61 @abc.abstractmethod
62 def private_numbers(self) -> "RSAPrivateNumbers":
63 """
64 Returns an RSAPrivateNumbers.
65 """
67 @abc.abstractmethod
68 def private_bytes(
69 self,
70 encoding: _serialization.Encoding,
71 format: _serialization.PrivateFormat,
72 encryption_algorithm: _serialization.KeySerializationEncryption,
73 ) -> bytes:
74 """
75 Returns the key serialized as bytes.
76 """
79RSAPrivateKeyWithSerialization = RSAPrivateKey
82class RSAPublicKey(metaclass=abc.ABCMeta):
83 @abc.abstractmethod
84 def verifier(
85 self,
86 signature: bytes,
87 padding: AsymmetricPadding,
88 algorithm: hashes.HashAlgorithm,
89 ) -> AsymmetricVerificationContext:
90 """
91 Returns an AsymmetricVerificationContext used for verifying signatures.
92 """
94 @abc.abstractmethod
95 def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes:
96 """
97 Encrypts the given plaintext.
98 """
100 @abc.abstractproperty
101 def key_size(self) -> int:
102 """
103 The bit length of the public modulus.
104 """
106 @abc.abstractmethod
107 def public_numbers(self) -> "RSAPublicNumbers":
108 """
109 Returns an RSAPublicNumbers
110 """
112 @abc.abstractmethod
113 def public_bytes(
114 self,
115 encoding: _serialization.Encoding,
116 format: _serialization.PublicFormat,
117 ) -> bytes:
118 """
119 Returns the key serialized as bytes.
120 """
122 @abc.abstractmethod
123 def verify(
124 self,
125 signature: bytes,
126 data: bytes,
127 padding: AsymmetricPadding,
128 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm],
129 ) -> None:
130 """
131 Verifies the signature of the data.
132 """
134 @abc.abstractmethod
135 def recover_data_from_signature(
136 self,
137 signature: bytes,
138 padding: AsymmetricPadding,
139 algorithm: typing.Optional[hashes.HashAlgorithm],
140 ) -> bytes:
141 """
142 Recovers the original data from the signature.
143 """
146RSAPublicKeyWithSerialization = RSAPublicKey
149def generate_private_key(
150 public_exponent: int, key_size: int, backend=None
151) -> RSAPrivateKey:
152 backend = _get_backend(backend)
153 if not isinstance(backend, RSABackend):
154 raise UnsupportedAlgorithm(
155 "Backend object does not implement RSABackend.",
156 _Reasons.BACKEND_MISSING_INTERFACE,
157 )
159 _verify_rsa_parameters(public_exponent, key_size)
160 return backend.generate_rsa_private_key(public_exponent, key_size)
163def _verify_rsa_parameters(public_exponent: int, key_size: int) -> None:
164 if public_exponent not in (3, 65537):
165 raise ValueError(
166 "public_exponent must be either 3 (for legacy compatibility) or "
167 "65537. Almost everyone should choose 65537 here!"
168 )
170 if key_size < 512:
171 raise ValueError("key_size must be at least 512-bits.")
174def _check_private_key_components(
175 p: int,
176 q: int,
177 private_exponent: int,
178 dmp1: int,
179 dmq1: int,
180 iqmp: int,
181 public_exponent: int,
182 modulus: int,
183) -> None:
184 if modulus < 3:
185 raise ValueError("modulus must be >= 3.")
187 if p >= modulus:
188 raise ValueError("p must be < modulus.")
190 if q >= modulus:
191 raise ValueError("q must be < modulus.")
193 if dmp1 >= modulus:
194 raise ValueError("dmp1 must be < modulus.")
196 if dmq1 >= modulus:
197 raise ValueError("dmq1 must be < modulus.")
199 if iqmp >= modulus:
200 raise ValueError("iqmp must be < modulus.")
202 if private_exponent >= modulus:
203 raise ValueError("private_exponent must be < modulus.")
205 if public_exponent < 3 or public_exponent >= modulus:
206 raise ValueError("public_exponent must be >= 3 and < modulus.")
208 if public_exponent & 1 == 0:
209 raise ValueError("public_exponent must be odd.")
211 if dmp1 & 1 == 0:
212 raise ValueError("dmp1 must be odd.")
214 if dmq1 & 1 == 0:
215 raise ValueError("dmq1 must be odd.")
217 if p * q != modulus:
218 raise ValueError("p*q must equal modulus.")
221def _check_public_key_components(e: int, n: int) -> None:
222 if n < 3:
223 raise ValueError("n must be >= 3.")
225 if e < 3 or e >= n:
226 raise ValueError("e must be >= 3 and < n.")
228 if e & 1 == 0:
229 raise ValueError("e must be odd.")
232def _modinv(e: int, m: int) -> int:
233 """
234 Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1
235 """
236 x1, x2 = 1, 0
237 a, b = e, m
238 while b > 0:
239 q, r = divmod(a, b)
240 xn = x1 - q * x2
241 a, b, x1, x2 = b, r, x2, xn
242 return x1 % m
245def rsa_crt_iqmp(p: int, q: int) -> int:
246 """
247 Compute the CRT (q ** -1) % p value from RSA primes p and q.
248 """
249 return _modinv(q, p)
252def rsa_crt_dmp1(private_exponent: int, p: int) -> int:
253 """
254 Compute the CRT private_exponent % (p - 1) value from the RSA
255 private_exponent (d) and p.
256 """
257 return private_exponent % (p - 1)
260def rsa_crt_dmq1(private_exponent: int, q: int) -> int:
261 """
262 Compute the CRT private_exponent % (q - 1) value from the RSA
263 private_exponent (d) and q.
264 """
265 return private_exponent % (q - 1)
268# Controls the number of iterations rsa_recover_prime_factors will perform
269# to obtain the prime factors. Each iteration increments by 2 so the actual
270# maximum attempts is half this number.
271_MAX_RECOVERY_ATTEMPTS = 1000
274def rsa_recover_prime_factors(
275 n: int, e: int, d: int
276) -> typing.Tuple[int, int]:
277 """
278 Compute factors p and q from the private exponent d. We assume that n has
279 no more than two factors. This function is adapted from code in PyCrypto.
280 """
281 # See 8.2.2(i) in Handbook of Applied Cryptography.
282 ktot = d * e - 1
283 # The quantity d*e-1 is a multiple of phi(n), even,
284 # and can be represented as t*2^s.
285 t = ktot
286 while t % 2 == 0:
287 t = t // 2
288 # Cycle through all multiplicative inverses in Zn.
289 # The algorithm is non-deterministic, but there is a 50% chance
290 # any candidate a leads to successful factoring.
291 # See "Digitalized Signatures and Public Key Functions as Intractable
292 # as Factorization", M. Rabin, 1979
293 spotted = False
294 a = 2
295 while not spotted and a < _MAX_RECOVERY_ATTEMPTS:
296 k = t
297 # Cycle through all values a^{t*2^i}=a^k
298 while k < ktot:
299 cand = pow(a, k, n)
300 # Check if a^k is a non-trivial root of unity (mod n)
301 if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1:
302 # We have found a number such that (cand-1)(cand+1)=0 (mod n).
303 # Either of the terms divides n.
304 p = gcd(cand + 1, n)
305 spotted = True
306 break
307 k *= 2
308 # This value was not any good... let's try another!
309 a += 2
310 if not spotted:
311 raise ValueError("Unable to compute factors p and q from exponent d.")
312 # Found !
313 q, r = divmod(n, p)
314 assert r == 0
315 p, q = sorted((p, q), reverse=True)
316 return (p, q)
319class RSAPrivateNumbers(object):
320 def __init__(
321 self,
322 p: int,
323 q: int,
324 d: int,
325 dmp1: int,
326 dmq1: int,
327 iqmp: int,
328 public_numbers: "RSAPublicNumbers",
329 ):
330 if (
331 not isinstance(p, int)
332 or not isinstance(q, int)
333 or not isinstance(d, int)
334 or not isinstance(dmp1, int)
335 or not isinstance(dmq1, int)
336 or not isinstance(iqmp, int)
337 ):
338 raise TypeError(
339 "RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must"
340 " all be an integers."
341 )
343 if not isinstance(public_numbers, RSAPublicNumbers):
344 raise TypeError(
345 "RSAPrivateNumbers public_numbers must be an RSAPublicNumbers"
346 " instance."
347 )
349 self._p = p
350 self._q = q
351 self._d = d
352 self._dmp1 = dmp1
353 self._dmq1 = dmq1
354 self._iqmp = iqmp
355 self._public_numbers = public_numbers
357 p = utils.read_only_property("_p")
358 q = utils.read_only_property("_q")
359 d = utils.read_only_property("_d")
360 dmp1 = utils.read_only_property("_dmp1")
361 dmq1 = utils.read_only_property("_dmq1")
362 iqmp = utils.read_only_property("_iqmp")
363 public_numbers = utils.read_only_property("_public_numbers")
365 def private_key(self, backend=None) -> RSAPrivateKey:
366 backend = _get_backend(backend)
367 return backend.load_rsa_private_numbers(self)
369 def __eq__(self, other):
370 if not isinstance(other, RSAPrivateNumbers):
371 return NotImplemented
373 return (
374 self.p == other.p
375 and self.q == other.q
376 and self.d == other.d
377 and self.dmp1 == other.dmp1
378 and self.dmq1 == other.dmq1
379 and self.iqmp == other.iqmp
380 and self.public_numbers == other.public_numbers
381 )
383 def __ne__(self, other):
384 return not self == other
386 def __hash__(self):
387 return hash(
388 (
389 self.p,
390 self.q,
391 self.d,
392 self.dmp1,
393 self.dmq1,
394 self.iqmp,
395 self.public_numbers,
396 )
397 )
400class RSAPublicNumbers(object):
401 def __init__(self, e: int, n: int):
402 if not isinstance(e, int) or not isinstance(n, int):
403 raise TypeError("RSAPublicNumbers arguments must be integers.")
405 self._e = e
406 self._n = n
408 e = utils.read_only_property("_e")
409 n = utils.read_only_property("_n")
411 def public_key(self, backend=None) -> RSAPublicKey:
412 backend = _get_backend(backend)
413 return backend.load_rsa_public_numbers(self)
415 def __repr__(self):
416 return "<RSAPublicNumbers(e={0.e}, n={0.n})>".format(self)
418 def __eq__(self, other):
419 if not isinstance(other, RSAPublicNumbers):
420 return NotImplemented
422 return self.e == other.e and self.n == other.n
424 def __ne__(self, other):
425 return not self == other
427 def __hash__(self):
428 return hash((self.e, self.n))