Hide keyboard shortcuts

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. 

4 

5 

6import abc 

7import typing 

8from math import gcd 

9 

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) 

21 

22 

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 """ 

31 

32 @abc.abstractmethod 

33 def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: 

34 """ 

35 Decrypts the provided ciphertext. 

36 """ 

37 

38 @abc.abstractproperty 

39 def key_size(self) -> int: 

40 """ 

41 The bit length of the public modulus. 

42 """ 

43 

44 @abc.abstractmethod 

45 def public_key(self) -> "RSAPublicKey": 

46 """ 

47 The RSAPublicKey associated with this private key. 

48 """ 

49 

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 """ 

60 

61 @abc.abstractmethod 

62 def private_numbers(self) -> "RSAPrivateNumbers": 

63 """ 

64 Returns an RSAPrivateNumbers. 

65 """ 

66 

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 """ 

77 

78 

79RSAPrivateKeyWithSerialization = RSAPrivateKey 

80 

81 

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 """ 

93 

94 @abc.abstractmethod 

95 def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: 

96 """ 

97 Encrypts the given plaintext. 

98 """ 

99 

100 @abc.abstractproperty 

101 def key_size(self) -> int: 

102 """ 

103 The bit length of the public modulus. 

104 """ 

105 

106 @abc.abstractmethod 

107 def public_numbers(self) -> "RSAPublicNumbers": 

108 """ 

109 Returns an RSAPublicNumbers 

110 """ 

111 

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 """ 

121 

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 """ 

133 

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 """ 

144 

145 

146RSAPublicKeyWithSerialization = RSAPublicKey 

147 

148 

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 ) 

158 

159 _verify_rsa_parameters(public_exponent, key_size) 

160 return backend.generate_rsa_private_key(public_exponent, key_size) 

161 

162 

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 ) 

169 

170 if key_size < 512: 

171 raise ValueError("key_size must be at least 512-bits.") 

172 

173 

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.") 

186 

187 if p >= modulus: 

188 raise ValueError("p must be < modulus.") 

189 

190 if q >= modulus: 

191 raise ValueError("q must be < modulus.") 

192 

193 if dmp1 >= modulus: 

194 raise ValueError("dmp1 must be < modulus.") 

195 

196 if dmq1 >= modulus: 

197 raise ValueError("dmq1 must be < modulus.") 

198 

199 if iqmp >= modulus: 

200 raise ValueError("iqmp must be < modulus.") 

201 

202 if private_exponent >= modulus: 

203 raise ValueError("private_exponent must be < modulus.") 

204 

205 if public_exponent < 3 or public_exponent >= modulus: 

206 raise ValueError("public_exponent must be >= 3 and < modulus.") 

207 

208 if public_exponent & 1 == 0: 

209 raise ValueError("public_exponent must be odd.") 

210 

211 if dmp1 & 1 == 0: 

212 raise ValueError("dmp1 must be odd.") 

213 

214 if dmq1 & 1 == 0: 

215 raise ValueError("dmq1 must be odd.") 

216 

217 if p * q != modulus: 

218 raise ValueError("p*q must equal modulus.") 

219 

220 

221def _check_public_key_components(e: int, n: int) -> None: 

222 if n < 3: 

223 raise ValueError("n must be >= 3.") 

224 

225 if e < 3 or e >= n: 

226 raise ValueError("e must be >= 3 and < n.") 

227 

228 if e & 1 == 0: 

229 raise ValueError("e must be odd.") 

230 

231 

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 

243 

244 

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) 

250 

251 

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) 

258 

259 

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) 

266 

267 

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 

272 

273 

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) 

317 

318 

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 ) 

342 

343 if not isinstance(public_numbers, RSAPublicNumbers): 

344 raise TypeError( 

345 "RSAPrivateNumbers public_numbers must be an RSAPublicNumbers" 

346 " instance." 

347 ) 

348 

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 

356 

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") 

364 

365 def private_key(self, backend=None) -> RSAPrivateKey: 

366 backend = _get_backend(backend) 

367 return backend.load_rsa_private_numbers(self) 

368 

369 def __eq__(self, other): 

370 if not isinstance(other, RSAPrivateNumbers): 

371 return NotImplemented 

372 

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 ) 

382 

383 def __ne__(self, other): 

384 return not self == other 

385 

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 ) 

398 

399 

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.") 

404 

405 self._e = e 

406 self._n = n 

407 

408 e = utils.read_only_property("_e") 

409 n = utils.read_only_property("_n") 

410 

411 def public_key(self, backend=None) -> RSAPublicKey: 

412 backend = _get_backend(backend) 

413 return backend.load_rsa_public_numbers(self) 

414 

415 def __repr__(self): 

416 return "<RSAPublicNumbers(e={0.e}, n={0.n})>".format(self) 

417 

418 def __eq__(self, other): 

419 if not isinstance(other, RSAPublicNumbers): 

420 return NotImplemented 

421 

422 return self.e == other.e and self.n == other.n 

423 

424 def __ne__(self, other): 

425 return not self == other 

426 

427 def __hash__(self): 

428 return hash((self.e, self.n))