Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/rsa.py: 17%

257 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:36 +0000

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 

5import threading 

6import typing 

7 

8from cryptography.exceptions import ( 

9 InvalidSignature, 

10 UnsupportedAlgorithm, 

11 _Reasons, 

12) 

13from cryptography.hazmat.backends.openssl.utils import ( 

14 _calculate_digest_and_algorithm, 

15) 

16from cryptography.hazmat.primitives import hashes, serialization 

17from cryptography.hazmat.primitives.asymmetric import utils as asym_utils 

18from cryptography.hazmat.primitives.asymmetric.padding import ( 

19 MGF1, 

20 OAEP, 

21 PSS, 

22 AsymmetricPadding, 

23 PKCS1v15, 

24 _Auto, 

25 _DigestLength, 

26 _MaxLength, 

27 calculate_max_pss_salt_length, 

28) 

29from cryptography.hazmat.primitives.asymmetric.rsa import ( 

30 RSAPrivateKey, 

31 RSAPrivateNumbers, 

32 RSAPublicKey, 

33 RSAPublicNumbers, 

34) 

35 

36if typing.TYPE_CHECKING: 

37 from cryptography.hazmat.backends.openssl.backend import Backend 

38 

39 

40def _get_rsa_pss_salt_length( 

41 backend: "Backend", 

42 pss: PSS, 

43 key: typing.Union[RSAPrivateKey, RSAPublicKey], 

44 hash_algorithm: hashes.HashAlgorithm, 

45) -> int: 

46 salt = pss._salt_length 

47 

48 if isinstance(salt, _MaxLength): 

49 return calculate_max_pss_salt_length(key, hash_algorithm) 

50 elif isinstance(salt, _DigestLength): 

51 return hash_algorithm.digest_size 

52 elif isinstance(salt, _Auto): 

53 if isinstance(key, RSAPrivateKey): 

54 raise ValueError( 

55 "PSS salt length can only be set to AUTO when verifying" 

56 ) 

57 return backend._lib.RSA_PSS_SALTLEN_AUTO 

58 else: 

59 return salt 

60 

61 

62def _enc_dec_rsa( 

63 backend: "Backend", 

64 key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], 

65 data: bytes, 

66 padding: AsymmetricPadding, 

67) -> bytes: 

68 if not isinstance(padding, AsymmetricPadding): 

69 raise TypeError("Padding must be an instance of AsymmetricPadding.") 

70 

71 if isinstance(padding, PKCS1v15): 

72 padding_enum = backend._lib.RSA_PKCS1_PADDING 

73 elif isinstance(padding, OAEP): 

74 padding_enum = backend._lib.RSA_PKCS1_OAEP_PADDING 

75 

76 if not isinstance(padding._mgf, MGF1): 

77 raise UnsupportedAlgorithm( 

78 "Only MGF1 is supported by this backend.", 

79 _Reasons.UNSUPPORTED_MGF, 

80 ) 

81 

82 if not backend.rsa_padding_supported(padding): 

83 raise UnsupportedAlgorithm( 

84 "This combination of padding and hash algorithm is not " 

85 "supported by this backend.", 

86 _Reasons.UNSUPPORTED_PADDING, 

87 ) 

88 

89 else: 

90 raise UnsupportedAlgorithm( 

91 f"{padding.name} is not supported by this backend.", 

92 _Reasons.UNSUPPORTED_PADDING, 

93 ) 

94 

95 return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding) 

96 

97 

98def _enc_dec_rsa_pkey_ctx( 

99 backend: "Backend", 

100 key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], 

101 data: bytes, 

102 padding_enum: int, 

103 padding: AsymmetricPadding, 

104) -> bytes: 

105 init: typing.Callable[[typing.Any], int] 

106 crypt: typing.Callable[[typing.Any, typing.Any, int, bytes, int], int] 

107 if isinstance(key, _RSAPublicKey): 

108 init = backend._lib.EVP_PKEY_encrypt_init 

109 crypt = backend._lib.EVP_PKEY_encrypt 

110 else: 

111 init = backend._lib.EVP_PKEY_decrypt_init 

112 crypt = backend._lib.EVP_PKEY_decrypt 

113 

114 pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) 

115 backend.openssl_assert(pkey_ctx != backend._ffi.NULL) 

116 pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) 

117 res = init(pkey_ctx) 

118 backend.openssl_assert(res == 1) 

119 res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) 

120 backend.openssl_assert(res > 0) 

121 buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey) 

122 backend.openssl_assert(buf_size > 0) 

123 if isinstance(padding, OAEP): 

124 mgf1_md = backend._evp_md_non_null_from_algorithm( 

125 padding._mgf._algorithm 

126 ) 

127 res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) 

128 backend.openssl_assert(res > 0) 

129 oaep_md = backend._evp_md_non_null_from_algorithm(padding._algorithm) 

130 res = backend._lib.EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, oaep_md) 

131 backend.openssl_assert(res > 0) 

132 

133 if ( 

134 isinstance(padding, OAEP) 

135 and padding._label is not None 

136 and len(padding._label) > 0 

137 ): 

138 # set0_rsa_oaep_label takes ownership of the char * so we need to 

139 # copy it into some new memory 

140 labelptr = backend._lib.OPENSSL_malloc(len(padding._label)) 

141 backend.openssl_assert(labelptr != backend._ffi.NULL) 

142 backend._ffi.memmove(labelptr, padding._label, len(padding._label)) 

143 res = backend._lib.EVP_PKEY_CTX_set0_rsa_oaep_label( 

144 pkey_ctx, labelptr, len(padding._label) 

145 ) 

146 backend.openssl_assert(res == 1) 

147 

148 outlen = backend._ffi.new("size_t *", buf_size) 

149 buf = backend._ffi.new("unsigned char[]", buf_size) 

150 # Everything from this line onwards is written with the goal of being as 

151 # constant-time as is practical given the constraints of Python and our 

152 # API. See Bleichenbacher's '98 attack on RSA, and its many many variants. 

153 # As such, you should not attempt to change this (particularly to "clean it 

154 # up") without understanding why it was written this way (see 

155 # Chesterton's Fence), and without measuring to verify you have not 

156 # introduced observable time differences. 

157 res = crypt(pkey_ctx, buf, outlen, data, len(data)) 

158 resbuf = backend._ffi.buffer(buf)[: outlen[0]] 

159 backend._lib.ERR_clear_error() 

160 if res <= 0: 

161 raise ValueError("Encryption/decryption failed.") 

162 return resbuf 

163 

164 

165def _rsa_sig_determine_padding( 

166 backend: "Backend", 

167 key: typing.Union["_RSAPrivateKey", "_RSAPublicKey"], 

168 padding: AsymmetricPadding, 

169 algorithm: typing.Optional[hashes.HashAlgorithm], 

170) -> int: 

171 if not isinstance(padding, AsymmetricPadding): 

172 raise TypeError("Expected provider of AsymmetricPadding.") 

173 

174 pkey_size = backend._lib.EVP_PKEY_size(key._evp_pkey) 

175 backend.openssl_assert(pkey_size > 0) 

176 

177 if isinstance(padding, PKCS1v15): 

178 # Hash algorithm is ignored for PKCS1v15-padding, may be None. 

179 padding_enum = backend._lib.RSA_PKCS1_PADDING 

180 elif isinstance(padding, PSS): 

181 if not isinstance(padding._mgf, MGF1): 

182 raise UnsupportedAlgorithm( 

183 "Only MGF1 is supported by this backend.", 

184 _Reasons.UNSUPPORTED_MGF, 

185 ) 

186 

187 # PSS padding requires a hash algorithm 

188 if not isinstance(algorithm, hashes.HashAlgorithm): 

189 raise TypeError("Expected instance of hashes.HashAlgorithm.") 

190 

191 # Size of key in bytes - 2 is the maximum 

192 # PSS signature length (salt length is checked later) 

193 if pkey_size - algorithm.digest_size - 2 < 0: 

194 raise ValueError( 

195 "Digest too large for key size. Use a larger " 

196 "key or different digest." 

197 ) 

198 

199 padding_enum = backend._lib.RSA_PKCS1_PSS_PADDING 

200 else: 

201 raise UnsupportedAlgorithm( 

202 f"{padding.name} is not supported by this backend.", 

203 _Reasons.UNSUPPORTED_PADDING, 

204 ) 

205 

206 return padding_enum 

207 

208 

209# Hash algorithm can be absent (None) to initialize the context without setting 

210# any message digest algorithm. This is currently only valid for the PKCS1v15 

211# padding type, where it means that the signature data is encoded/decoded 

212# as provided, without being wrapped in a DigestInfo structure. 

213def _rsa_sig_setup( 

214 backend: "Backend", 

215 padding: AsymmetricPadding, 

216 algorithm: typing.Optional[hashes.HashAlgorithm], 

217 key: typing.Union["_RSAPublicKey", "_RSAPrivateKey"], 

218 init_func: typing.Callable[[typing.Any], int], 

219): 

220 padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm) 

221 pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) 

222 backend.openssl_assert(pkey_ctx != backend._ffi.NULL) 

223 pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) 

224 res = init_func(pkey_ctx) 

225 if res != 1: 

226 errors = backend._consume_errors() 

227 raise ValueError("Unable to sign/verify with this key", errors) 

228 

229 if algorithm is not None: 

230 evp_md = backend._evp_md_non_null_from_algorithm(algorithm) 

231 res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) 

232 if res <= 0: 

233 backend._consume_errors() 

234 raise UnsupportedAlgorithm( 

235 "{} is not supported by this backend for RSA signing.".format( 

236 algorithm.name 

237 ), 

238 _Reasons.UNSUPPORTED_HASH, 

239 ) 

240 res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) 

241 if res <= 0: 

242 backend._consume_errors() 

243 raise UnsupportedAlgorithm( 

244 "{} is not supported for the RSA signature operation.".format( 

245 padding.name 

246 ), 

247 _Reasons.UNSUPPORTED_PADDING, 

248 ) 

249 if isinstance(padding, PSS): 

250 assert isinstance(algorithm, hashes.HashAlgorithm) 

251 res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen( 

252 pkey_ctx, 

253 _get_rsa_pss_salt_length(backend, padding, key, algorithm), 

254 ) 

255 backend.openssl_assert(res > 0) 

256 

257 mgf1_md = backend._evp_md_non_null_from_algorithm( 

258 padding._mgf._algorithm 

259 ) 

260 res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md) 

261 backend.openssl_assert(res > 0) 

262 

263 return pkey_ctx 

264 

265 

266def _rsa_sig_sign( 

267 backend: "Backend", 

268 padding: AsymmetricPadding, 

269 algorithm: hashes.HashAlgorithm, 

270 private_key: "_RSAPrivateKey", 

271 data: bytes, 

272) -> bytes: 

273 pkey_ctx = _rsa_sig_setup( 

274 backend, 

275 padding, 

276 algorithm, 

277 private_key, 

278 backend._lib.EVP_PKEY_sign_init, 

279 ) 

280 buflen = backend._ffi.new("size_t *") 

281 res = backend._lib.EVP_PKEY_sign( 

282 pkey_ctx, backend._ffi.NULL, buflen, data, len(data) 

283 ) 

284 backend.openssl_assert(res == 1) 

285 buf = backend._ffi.new("unsigned char[]", buflen[0]) 

286 res = backend._lib.EVP_PKEY_sign(pkey_ctx, buf, buflen, data, len(data)) 

287 if res != 1: 

288 errors = backend._consume_errors() 

289 raise ValueError( 

290 "Digest or salt length too long for key size. Use a larger key " 

291 "or shorter salt length if you are specifying a PSS salt", 

292 errors, 

293 ) 

294 

295 return backend._ffi.buffer(buf)[:] 

296 

297 

298def _rsa_sig_verify( 

299 backend: "Backend", 

300 padding: AsymmetricPadding, 

301 algorithm: hashes.HashAlgorithm, 

302 public_key: "_RSAPublicKey", 

303 signature: bytes, 

304 data: bytes, 

305) -> None: 

306 pkey_ctx = _rsa_sig_setup( 

307 backend, 

308 padding, 

309 algorithm, 

310 public_key, 

311 backend._lib.EVP_PKEY_verify_init, 

312 ) 

313 res = backend._lib.EVP_PKEY_verify( 

314 pkey_ctx, signature, len(signature), data, len(data) 

315 ) 

316 # The previous call can return negative numbers in the event of an 

317 # error. This is not a signature failure but we need to fail if it 

318 # occurs. 

319 backend.openssl_assert(res >= 0) 

320 if res == 0: 

321 backend._consume_errors() 

322 raise InvalidSignature 

323 

324 

325def _rsa_sig_recover( 

326 backend: "Backend", 

327 padding: AsymmetricPadding, 

328 algorithm: typing.Optional[hashes.HashAlgorithm], 

329 public_key: "_RSAPublicKey", 

330 signature: bytes, 

331) -> bytes: 

332 pkey_ctx = _rsa_sig_setup( 

333 backend, 

334 padding, 

335 algorithm, 

336 public_key, 

337 backend._lib.EVP_PKEY_verify_recover_init, 

338 ) 

339 

340 # Attempt to keep the rest of the code in this function as constant/time 

341 # as possible. See the comment in _enc_dec_rsa_pkey_ctx. Note that the 

342 # buflen parameter is used even though its value may be undefined in the 

343 # error case. Due to the tolerant nature of Python slicing this does not 

344 # trigger any exceptions. 

345 maxlen = backend._lib.EVP_PKEY_size(public_key._evp_pkey) 

346 backend.openssl_assert(maxlen > 0) 

347 buf = backend._ffi.new("unsigned char[]", maxlen) 

348 buflen = backend._ffi.new("size_t *", maxlen) 

349 res = backend._lib.EVP_PKEY_verify_recover( 

350 pkey_ctx, buf, buflen, signature, len(signature) 

351 ) 

352 resbuf = backend._ffi.buffer(buf)[: buflen[0]] 

353 backend._lib.ERR_clear_error() 

354 # Assume that all parameter errors are handled during the setup phase and 

355 # any error here is due to invalid signature. 

356 if res != 1: 

357 raise InvalidSignature 

358 return resbuf 

359 

360 

361class _RSAPrivateKey(RSAPrivateKey): 

362 _evp_pkey: object 

363 _rsa_cdata: object 

364 _key_size: int 

365 

366 def __init__( 

367 self, 

368 backend: "Backend", 

369 rsa_cdata, 

370 evp_pkey, 

371 *, 

372 unsafe_skip_rsa_key_validation: bool, 

373 ): 

374 res: int 

375 # RSA_check_key is slower in OpenSSL 3.0.0 due to improved 

376 # primality checking. In normal use this is unlikely to be a problem 

377 # since users don't load new keys constantly, but for TESTING we've 

378 # added an init arg that allows skipping the checks. You should not 

379 # use this in production code unless you understand the consequences. 

380 if not unsafe_skip_rsa_key_validation: 

381 res = backend._lib.RSA_check_key(rsa_cdata) 

382 if res != 1: 

383 errors = backend._consume_errors() 

384 raise ValueError("Invalid private key", errors) 

385 # 2 is prime and passes an RSA key check, so we also check 

386 # if p and q are odd just to be safe. 

387 p = backend._ffi.new("BIGNUM **") 

388 q = backend._ffi.new("BIGNUM **") 

389 backend._lib.RSA_get0_factors(rsa_cdata, p, q) 

390 backend.openssl_assert(p[0] != backend._ffi.NULL) 

391 backend.openssl_assert(q[0] != backend._ffi.NULL) 

392 p_odd = backend._lib.BN_is_odd(p[0]) 

393 q_odd = backend._lib.BN_is_odd(q[0]) 

394 if p_odd != 1 or q_odd != 1: 

395 errors = backend._consume_errors() 

396 raise ValueError("Invalid private key", errors) 

397 

398 self._backend = backend 

399 self._rsa_cdata = rsa_cdata 

400 self._evp_pkey = evp_pkey 

401 # Used for lazy blinding 

402 self._blinded = False 

403 self._blinding_lock = threading.Lock() 

404 

405 n = self._backend._ffi.new("BIGNUM **") 

406 self._backend._lib.RSA_get0_key( 

407 self._rsa_cdata, 

408 n, 

409 self._backend._ffi.NULL, 

410 self._backend._ffi.NULL, 

411 ) 

412 self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) 

413 self._key_size = self._backend._lib.BN_num_bits(n[0]) 

414 

415 def _enable_blinding(self) -> None: 

416 # If you call blind on an already blinded RSA key OpenSSL will turn 

417 # it off and back on, which is a performance hit we want to avoid. 

418 if not self._blinded: 

419 with self._blinding_lock: 

420 self._non_threadsafe_enable_blinding() 

421 

422 def _non_threadsafe_enable_blinding(self) -> None: 

423 # This is only a separate function to allow for testing to cover both 

424 # branches. It should never be invoked except through _enable_blinding. 

425 # Check if it's not True again in case another thread raced past the 

426 # first non-locked check. 

427 if not self._blinded: 

428 res = self._backend._lib.RSA_blinding_on( 

429 self._rsa_cdata, self._backend._ffi.NULL 

430 ) 

431 self._backend.openssl_assert(res == 1) 

432 self._blinded = True 

433 

434 @property 

435 def key_size(self) -> int: 

436 return self._key_size 

437 

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

439 self._enable_blinding() 

440 key_size_bytes = (self.key_size + 7) // 8 

441 if key_size_bytes != len(ciphertext): 

442 raise ValueError("Ciphertext length must be equal to key size.") 

443 

444 return _enc_dec_rsa(self._backend, self, ciphertext, padding) 

445 

446 def public_key(self) -> RSAPublicKey: 

447 ctx = self._backend._lib.RSAPublicKey_dup(self._rsa_cdata) 

448 self._backend.openssl_assert(ctx != self._backend._ffi.NULL) 

449 ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free) 

450 evp_pkey = self._backend._rsa_cdata_to_evp_pkey(ctx) 

451 return _RSAPublicKey(self._backend, ctx, evp_pkey) 

452 

453 def private_numbers(self) -> RSAPrivateNumbers: 

454 n = self._backend._ffi.new("BIGNUM **") 

455 e = self._backend._ffi.new("BIGNUM **") 

456 d = self._backend._ffi.new("BIGNUM **") 

457 p = self._backend._ffi.new("BIGNUM **") 

458 q = self._backend._ffi.new("BIGNUM **") 

459 dmp1 = self._backend._ffi.new("BIGNUM **") 

460 dmq1 = self._backend._ffi.new("BIGNUM **") 

461 iqmp = self._backend._ffi.new("BIGNUM **") 

462 self._backend._lib.RSA_get0_key(self._rsa_cdata, n, e, d) 

463 self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) 

464 self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) 

465 self._backend.openssl_assert(d[0] != self._backend._ffi.NULL) 

466 self._backend._lib.RSA_get0_factors(self._rsa_cdata, p, q) 

467 self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) 

468 self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) 

469 self._backend._lib.RSA_get0_crt_params( 

470 self._rsa_cdata, dmp1, dmq1, iqmp 

471 ) 

472 self._backend.openssl_assert(dmp1[0] != self._backend._ffi.NULL) 

473 self._backend.openssl_assert(dmq1[0] != self._backend._ffi.NULL) 

474 self._backend.openssl_assert(iqmp[0] != self._backend._ffi.NULL) 

475 return RSAPrivateNumbers( 

476 p=self._backend._bn_to_int(p[0]), 

477 q=self._backend._bn_to_int(q[0]), 

478 d=self._backend._bn_to_int(d[0]), 

479 dmp1=self._backend._bn_to_int(dmp1[0]), 

480 dmq1=self._backend._bn_to_int(dmq1[0]), 

481 iqmp=self._backend._bn_to_int(iqmp[0]), 

482 public_numbers=RSAPublicNumbers( 

483 e=self._backend._bn_to_int(e[0]), 

484 n=self._backend._bn_to_int(n[0]), 

485 ), 

486 ) 

487 

488 def private_bytes( 

489 self, 

490 encoding: serialization.Encoding, 

491 format: serialization.PrivateFormat, 

492 encryption_algorithm: serialization.KeySerializationEncryption, 

493 ) -> bytes: 

494 return self._backend._private_key_bytes( 

495 encoding, 

496 format, 

497 encryption_algorithm, 

498 self, 

499 self._evp_pkey, 

500 self._rsa_cdata, 

501 ) 

502 

503 def sign( 

504 self, 

505 data: bytes, 

506 padding: AsymmetricPadding, 

507 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], 

508 ) -> bytes: 

509 self._enable_blinding() 

510 data, algorithm = _calculate_digest_and_algorithm(data, algorithm) 

511 return _rsa_sig_sign(self._backend, padding, algorithm, self, data) 

512 

513 

514class _RSAPublicKey(RSAPublicKey): 

515 _evp_pkey: object 

516 _rsa_cdata: object 

517 _key_size: int 

518 

519 def __init__(self, backend: "Backend", rsa_cdata, evp_pkey): 

520 self._backend = backend 

521 self._rsa_cdata = rsa_cdata 

522 self._evp_pkey = evp_pkey 

523 

524 n = self._backend._ffi.new("BIGNUM **") 

525 self._backend._lib.RSA_get0_key( 

526 self._rsa_cdata, 

527 n, 

528 self._backend._ffi.NULL, 

529 self._backend._ffi.NULL, 

530 ) 

531 self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) 

532 self._key_size = self._backend._lib.BN_num_bits(n[0]) 

533 

534 @property 

535 def key_size(self) -> int: 

536 return self._key_size 

537 

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

539 return _enc_dec_rsa(self._backend, self, plaintext, padding) 

540 

541 def public_numbers(self) -> RSAPublicNumbers: 

542 n = self._backend._ffi.new("BIGNUM **") 

543 e = self._backend._ffi.new("BIGNUM **") 

544 self._backend._lib.RSA_get0_key( 

545 self._rsa_cdata, n, e, self._backend._ffi.NULL 

546 ) 

547 self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) 

548 self._backend.openssl_assert(e[0] != self._backend._ffi.NULL) 

549 return RSAPublicNumbers( 

550 e=self._backend._bn_to_int(e[0]), 

551 n=self._backend._bn_to_int(n[0]), 

552 ) 

553 

554 def public_bytes( 

555 self, 

556 encoding: serialization.Encoding, 

557 format: serialization.PublicFormat, 

558 ) -> bytes: 

559 return self._backend._public_key_bytes( 

560 encoding, format, self, self._evp_pkey, self._rsa_cdata 

561 ) 

562 

563 def verify( 

564 self, 

565 signature: bytes, 

566 data: bytes, 

567 padding: AsymmetricPadding, 

568 algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], 

569 ) -> None: 

570 data, algorithm = _calculate_digest_and_algorithm(data, algorithm) 

571 _rsa_sig_verify( 

572 self._backend, padding, algorithm, self, signature, data 

573 ) 

574 

575 def recover_data_from_signature( 

576 self, 

577 signature: bytes, 

578 padding: AsymmetricPadding, 

579 algorithm: typing.Optional[hashes.HashAlgorithm], 

580 ) -> bytes: 

581 if isinstance(algorithm, asym_utils.Prehashed): 

582 raise TypeError( 

583 "Prehashed is only supported in the sign and verify methods. " 

584 "It cannot be used with recover_data_from_signature." 

585 ) 

586 return _rsa_sig_recover( 

587 self._backend, padding, algorithm, self, signature 

588 )