1.. hazmat:: 2 3RSA 4=== 5 6.. module:: cryptography.hazmat.primitives.asymmetric.rsa 7 8`RSA`_ is a `public-key`_ algorithm for encrypting and signing messages. 9 10Generation 11~~~~~~~~~~ 12 13Unlike symmetric cryptography, where the key is typically just a random series 14of bytes, RSA keys have a complex internal structure with `specific 15mathematical properties`_. 16 17.. function:: generate_private_key(public_exponent, key_size, backend) 18 19 .. versionadded:: 0.5 20 21 Generates a new RSA private key using the provided ``backend``. 22 ``key_size`` describes how many :term:`bits` long the key should be. Larger 23 keys provide more security; currently ``1024`` and below are considered 24 breakable while ``2048`` or ``4096`` are reasonable default key sizes for 25 new keys. The ``public_exponent`` indicates what one mathematical property 26 of the key generation will be. Unless you have a specific reason to do 27 otherwise, you should always `use 65537`_. 28 29 .. doctest:: 30 31 >>> from cryptography.hazmat.backends import default_backend 32 >>> from cryptography.hazmat.primitives.asymmetric import rsa 33 >>> private_key = rsa.generate_private_key( 34 ... public_exponent=65537, 35 ... key_size=2048, 36 ... backend=default_backend() 37 ... ) 38 39 :param int public_exponent: The public exponent of the new key. 40 Usually one of the small Fermat primes 3, 5, 17, 257, 65537. If in 41 doubt you should `use 65537`_. 42 43 :param int key_size: The length of the modulus in :term:`bits`. For keys 44 generated in 2015 it is strongly recommended to be 45 `at least 2048`_ (See page 41). It must not be less than 512. 46 Some backends may have additional limitations. 47 48 :param backend: A backend which implements 49 :class:`~cryptography.hazmat.backends.interfaces.RSABackend`. 50 51 :return: An instance of 52 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`. 53 54 :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if 55 the provided ``backend`` does not implement 56 :class:`~cryptography.hazmat.backends.interfaces.RSABackend` 57 58Key loading 59~~~~~~~~~~~ 60 61If you already have an on-disk key in the PEM format (which are recognizable by 62the distinctive ``-----BEGIN {format}-----`` and ``-----END {format}-----`` 63markers), you can load it: 64 65.. code-block:: pycon 66 67 >>> from cryptography.hazmat.backends import default_backend 68 >>> from cryptography.hazmat.primitives import serialization 69 70 >>> with open("path/to/key.pem", "rb") as key_file: 71 ... private_key = serialization.load_pem_private_key( 72 ... key_file.read(), 73 ... password=None, 74 ... backend=default_backend() 75 ... ) 76 77Serialized keys may optionally be encrypted on disk using a password. In this 78example we loaded an unencrypted key, and therefore we did not provide a 79password. If the key is encrypted we can pass a ``bytes`` object as the 80``password`` argument. 81 82There is also support for :func:`loading public keys in the SSH format 83<cryptography.hazmat.primitives.serialization.load_ssh_public_key>`. 84 85Key serialization 86~~~~~~~~~~~~~~~~~ 87 88If you have a private key that you've loaded or generated which implements the 89:class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization` 90interface you can use 91:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization.private_bytes` 92to serialize the key. 93 94.. doctest:: 95 96 >>> from cryptography.hazmat.primitives import serialization 97 >>> pem = private_key.private_bytes( 98 ... encoding=serialization.Encoding.PEM, 99 ... format=serialization.PrivateFormat.PKCS8, 100 ... encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword') 101 ... ) 102 >>> pem.splitlines()[0] 103 b'-----BEGIN ENCRYPTED PRIVATE KEY-----' 104 105It is also possible to serialize without encryption using 106:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`. 107 108.. doctest:: 109 110 >>> pem = private_key.private_bytes( 111 ... encoding=serialization.Encoding.PEM, 112 ... format=serialization.PrivateFormat.TraditionalOpenSSL, 113 ... encryption_algorithm=serialization.NoEncryption() 114 ... ) 115 >>> pem.splitlines()[0] 116 b'-----BEGIN RSA PRIVATE KEY-----' 117 118For public keys you can use 119:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.public_bytes` 120to serialize the key. 121 122.. doctest:: 123 124 >>> from cryptography.hazmat.primitives import serialization 125 >>> public_key = private_key.public_key() 126 >>> pem = public_key.public_bytes( 127 ... encoding=serialization.Encoding.PEM, 128 ... format=serialization.PublicFormat.SubjectPublicKeyInfo 129 ... ) 130 >>> pem.splitlines()[0] 131 b'-----BEGIN PUBLIC KEY-----' 132 133Signing 134~~~~~~~ 135 136A private key can be used to sign a message. This allows anyone with the public 137key to verify that the message was created by someone who possesses the 138corresponding private key. RSA signatures require a specific hash function, and 139padding to be used. Here is an example of signing ``message`` using RSA, with a 140secure hash function and padding: 141 142.. doctest:: 143 144 >>> from cryptography.hazmat.primitives import hashes 145 >>> from cryptography.hazmat.primitives.asymmetric import padding 146 >>> message = b"A message I want to sign" 147 >>> signature = private_key.sign( 148 ... message, 149 ... padding.PSS( 150 ... mgf=padding.MGF1(hashes.SHA256()), 151 ... salt_length=padding.PSS.MAX_LENGTH 152 ... ), 153 ... hashes.SHA256() 154 ... ) 155 156Valid paddings for signatures are 157:class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS` and 158:class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`. ``PSS`` 159is the recommended choice for any new protocols or applications, ``PKCS1v15`` 160should only be used to support legacy protocols. 161 162If your data is too large to be passed in a single call, you can hash it 163separately and pass that value using 164:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`. 165 166.. doctest:: 167 168 >>> from cryptography.hazmat.primitives.asymmetric import utils 169 >>> chosen_hash = hashes.SHA256() 170 >>> hasher = hashes.Hash(chosen_hash, default_backend()) 171 >>> hasher.update(b"data & ") 172 >>> hasher.update(b"more data") 173 >>> digest = hasher.finalize() 174 >>> sig = private_key.sign( 175 ... digest, 176 ... padding.PSS( 177 ... mgf=padding.MGF1(hashes.SHA256()), 178 ... salt_length=padding.PSS.MAX_LENGTH 179 ... ), 180 ... utils.Prehashed(chosen_hash) 181 ... ) 182 183Verification 184~~~~~~~~~~~~ 185 186The previous section describes what to do if you have a private key and want to 187sign something. If you have a public key, a message, a signature, and the 188signing algorithm that was used you can check that the private key associated 189with a given public key was used to sign that specific message. You can obtain 190a public key to use in verification using 191:func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`, 192:func:`~cryptography.hazmat.primitives.serialization.load_der_public_key`, 193:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers.public_key` 194, or 195:meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey.public_key`. 196 197.. doctest:: 198 199 >>> public_key = private_key.public_key() 200 >>> public_key.verify( 201 ... signature, 202 ... message, 203 ... padding.PSS( 204 ... mgf=padding.MGF1(hashes.SHA256()), 205 ... salt_length=padding.PSS.MAX_LENGTH 206 ... ), 207 ... hashes.SHA256() 208 ... ) 209 210If the signature does not match, ``verify()`` will raise an 211:class:`~cryptography.exceptions.InvalidSignature` exception. 212 213If your data is too large to be passed in a single call, you can hash it 214separately and pass that value using 215:class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`. 216 217.. doctest:: 218 219 >>> chosen_hash = hashes.SHA256() 220 >>> hasher = hashes.Hash(chosen_hash, default_backend()) 221 >>> hasher.update(b"data & ") 222 >>> hasher.update(b"more data") 223 >>> digest = hasher.finalize() 224 >>> public_key.verify( 225 ... sig, 226 ... digest, 227 ... padding.PSS( 228 ... mgf=padding.MGF1(hashes.SHA256()), 229 ... salt_length=padding.PSS.MAX_LENGTH 230 ... ), 231 ... utils.Prehashed(chosen_hash) 232 ... ) 233 234Encryption 235~~~~~~~~~~ 236 237RSA encryption is interesting because encryption is performed using the 238**public** key, meaning anyone can encrypt data. The data is then decrypted 239using the **private** key. 240 241Like signatures, RSA supports encryption with several different padding 242options. Here's an example using a secure padding and hash function: 243 244.. doctest:: 245 246 >>> message = b"encrypted data" 247 >>> ciphertext = public_key.encrypt( 248 ... message, 249 ... padding.OAEP( 250 ... mgf=padding.MGF1(algorithm=hashes.SHA256()), 251 ... algorithm=hashes.SHA256(), 252 ... label=None 253 ... ) 254 ... ) 255 256Valid paddings for encryption are 257:class:`~cryptography.hazmat.primitives.asymmetric.padding.OAEP` and 258:class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`. ``OAEP`` 259is the recommended choice for any new protocols or applications, ``PKCS1v15`` 260should only be used to support legacy protocols. 261 262 263Decryption 264~~~~~~~~~~ 265 266Once you have an encrypted message, it can be decrypted using the private key: 267 268.. doctest:: 269 270 >>> plaintext = private_key.decrypt( 271 ... ciphertext, 272 ... padding.OAEP( 273 ... mgf=padding.MGF1(algorithm=hashes.SHA256()), 274 ... algorithm=hashes.SHA256(), 275 ... label=None 276 ... ) 277 ... ) 278 >>> plaintext == message 279 True 280 281Padding 282~~~~~~~ 283 284.. module:: cryptography.hazmat.primitives.asymmetric.padding 285 286.. class:: AsymmetricPadding 287 288 .. versionadded:: 0.2 289 290 .. attribute:: name 291 292.. class:: PSS(mgf, salt_length) 293 294 .. versionadded:: 0.3 295 296 .. versionchanged:: 0.4 297 Added ``salt_length`` parameter. 298 299 PSS (Probabilistic Signature Scheme) is a signature scheme defined in 300 :rfc:`3447`. It is more complex than PKCS1 but possesses a `security proof`_. 301 This is the `recommended padding algorithm`_ for RSA signatures. It cannot 302 be used with RSA encryption. 303 304 :param mgf: A mask generation function object. At this time the only 305 supported MGF is :class:`MGF1`. 306 307 :param int salt_length: The length of the salt. It is recommended that this 308 be set to ``PSS.MAX_LENGTH``. 309 310 .. attribute:: MAX_LENGTH 311 312 Pass this attribute to ``salt_length`` to get the maximum salt length 313 available. 314 315.. class:: OAEP(mgf, algorithm, label) 316 317 .. versionadded:: 0.4 318 319 OAEP (Optimal Asymmetric Encryption Padding) is a padding scheme defined in 320 :rfc:`3447`. It provides probabilistic encryption and is `proven secure`_ 321 against several attack types. This is the `recommended padding algorithm`_ 322 for RSA encryption. It cannot be used with RSA signing. 323 324 :param mgf: A mask generation function object. At this time the only 325 supported MGF is :class:`MGF1`. 326 327 :param algorithm: An instance of 328 :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. 329 330 :param bytes label: A label to apply. This is a rarely used field and 331 should typically be set to ``None`` or ``b""``, which are equivalent. 332 333.. class:: PKCS1v15() 334 335 .. versionadded:: 0.3 336 337 PKCS1 v1.5 (also known as simply PKCS1) is a simple padding scheme 338 developed for use with RSA keys. It is defined in :rfc:`3447`. This padding 339 can be used for signing and encryption. 340 341 It is not recommended that ``PKCS1v15`` be used for new applications, 342 :class:`OAEP` should be preferred for encryption and :class:`PSS` should be 343 preferred for signatures. 344 345 346.. function:: calculate_max_pss_salt_length(key, hash_algorithm) 347 348 .. versionadded:: 1.5 349 350 :param key: An RSA public or private key. 351 :param hash_algorithm: A 352 :class:`cryptography.hazmat.primitives.hashes.HashAlgorithm`. 353 :returns int: The computed salt length. 354 355 Computes the length of the salt that :class:`PSS` will use if 356 :data:`PSS.MAX_LENGTH` is used. 357 358 359Mask generation functions 360------------------------- 361 362.. class:: MGF1(algorithm) 363 364 .. versionadded:: 0.3 365 366 .. versionchanged:: 0.6 367 Removed the deprecated ``salt_length`` parameter. 368 369 MGF1 (Mask Generation Function 1) is used as the mask generation function 370 in :class:`PSS` and :class:`OAEP` padding. It takes a hash algorithm. 371 372 :param algorithm: An instance of 373 :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. 374 375Numbers 376~~~~~~~ 377 378.. currentmodule:: cryptography.hazmat.primitives.asymmetric.rsa 379 380These classes hold the constituent components of an RSA key. They are useful 381only when more traditional :doc:`/hazmat/primitives/asymmetric/serialization` 382is unavailable. 383 384.. class:: RSAPublicNumbers(e, n) 385 386 .. versionadded:: 0.5 387 388 The collection of integers that make up an RSA public key. 389 390 .. attribute:: n 391 392 :type: int 393 394 The public modulus. 395 396 .. attribute:: e 397 398 :type: int 399 400 The public exponent. 401 402 .. method:: public_key(backend) 403 404 :param backend: An instance of 405 :class:`~cryptography.hazmat.backends.interfaces.RSABackend`. 406 407 :returns: A new instance of 408 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`. 409 410.. class:: RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, public_numbers) 411 412 .. versionadded:: 0.5 413 414 The collection of integers that make up an RSA private key. 415 416 .. warning:: 417 418 With the exception of the integers contained in the 419 :class:`RSAPublicNumbers` all attributes of this class must be kept 420 secret. Revealing them will compromise the security of any 421 cryptographic operations performed with a key loaded from them. 422 423 .. attribute:: public_numbers 424 425 :type: :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers` 426 427 The :class:`RSAPublicNumbers` which makes up the RSA public key 428 associated with this RSA private key. 429 430 .. attribute:: p 431 432 :type: int 433 434 ``p``, one of the two primes composing ``n``. 435 436 .. attribute:: q 437 438 :type: int 439 440 ``q``, one of the two primes composing ``n``. 441 442 .. attribute:: d 443 444 :type: int 445 446 The private exponent. 447 448 .. attribute:: dmp1 449 450 :type: int 451 452 A `Chinese remainder theorem`_ coefficient used to speed up RSA 453 operations. Calculated as: d mod (p-1) 454 455 .. attribute:: dmq1 456 457 :type: int 458 459 A `Chinese remainder theorem`_ coefficient used to speed up RSA 460 operations. Calculated as: d mod (q-1) 461 462 .. attribute:: iqmp 463 464 :type: int 465 466 A `Chinese remainder theorem`_ coefficient used to speed up RSA 467 operations. Calculated as: q\ :sup:`-1` mod p 468 469 .. method:: private_key(backend) 470 471 :param backend: A new instance of 472 :class:`~cryptography.hazmat.backends.interfaces.RSABackend`. 473 474 :returns: An instance of 475 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`. 476 477Handling partial RSA private keys 478~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 479 480If you are trying to load RSA private keys yourself you may find that not all 481parameters required by ``RSAPrivateNumbers`` are available. In particular the 482`Chinese Remainder Theorem`_ (CRT) values ``dmp1``, ``dmq1``, ``iqmp`` may be 483missing or present in a different form. For example, `OpenPGP`_ does not include 484the ``iqmp``, ``dmp1`` or ``dmq1`` parameters. 485 486The following functions are provided for users who want to work with keys like 487this without having to do the math themselves. 488 489.. function:: rsa_crt_iqmp(p, q) 490 491 .. versionadded:: 0.4 492 493 Computes the ``iqmp`` (also known as ``qInv``) parameter from the RSA 494 primes ``p`` and ``q``. 495 496.. function:: rsa_crt_dmp1(private_exponent, p) 497 498 .. versionadded:: 0.4 499 500 Computes the ``dmp1`` parameter from the RSA private exponent (``d``) and 501 prime ``p``. 502 503.. function:: rsa_crt_dmq1(private_exponent, q) 504 505 .. versionadded:: 0.4 506 507 Computes the ``dmq1`` parameter from the RSA private exponent (``d``) and 508 prime ``q``. 509 510.. function:: rsa_recover_prime_factors(n, e, d) 511 512 .. versionadded:: 0.8 513 514 Computes the prime factors ``(p, q)`` given the modulus, public exponent, 515 and private exponent. 516 517 .. note:: 518 519 When recovering prime factors this algorithm will always return ``p`` 520 and ``q`` such that ``p > q``. Note: before 1.5, this function always 521 returned ``p`` and ``q`` such that ``p < q``. It was changed because 522 libraries commonly require ``p > q``. 523 524 :return: A tuple ``(p, q)`` 525 526 527Key interfaces 528~~~~~~~~~~~~~~ 529 530.. class:: RSAPrivateKey 531 532 .. versionadded:: 0.2 533 534 An `RSA`_ private key. An RSA private key that is not an 535 :term:`opaque key` also implements :class:`RSAPrivateKeyWithSerialization` 536 to provide serialization methods. 537 538 .. method:: decrypt(ciphertext, padding) 539 540 .. versionadded:: 0.4 541 542 Decrypt data that was encrypted with the public key. 543 544 :param bytes ciphertext: The ciphertext to decrypt. 545 546 :param padding: An instance of 547 :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`. 548 549 :return bytes: Decrypted data. 550 551 .. method:: public_key() 552 553 :return: :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` 554 555 An RSA public key object corresponding to the values of the private key. 556 557 .. attribute:: key_size 558 559 :type: int 560 561 The bit length of the modulus. 562 563 .. method:: sign(data, padding, algorithm) 564 565 .. versionadded:: 1.4 566 .. versionchanged:: 1.6 567 :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed` 568 can now be used as an ``algorithm``. 569 570 Sign one block of data which can be verified later by others using the 571 public key. 572 573 :param bytes data: The message string to sign. 574 575 :param padding: An instance of 576 :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`. 577 578 :param algorithm: An instance of 579 :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or 580 :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed` 581 if the ``data`` you want to sign has already been hashed. 582 583 :return bytes: Signature. 584 585 586.. class:: RSAPrivateKeyWithSerialization 587 588 .. versionadded:: 0.8 589 590 This interface contains additional methods relating to serialization. 591 Any object with this interface also has all the methods from 592 :class:`RSAPrivateKey`. 593 594 .. method:: private_numbers() 595 596 Create a 597 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers` 598 object. 599 600 :returns: An 601 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers` 602 instance. 603 604 .. method:: private_bytes(encoding, format, encryption_algorithm) 605 606 Allows serialization of the key to bytes. Encoding ( 607 :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or 608 :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`), 609 format ( 610 :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.TraditionalOpenSSL` 611 or 612 :attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`) 613 and encryption algorithm (such as 614 :class:`~cryptography.hazmat.primitives.serialization.BestAvailableEncryption` 615 or :class:`~cryptography.hazmat.primitives.serialization.NoEncryption`) 616 are chosen to define the exact serialization. 617 618 :param encoding: A value from the 619 :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum. 620 621 :param format: A value from the 622 :class:`~cryptography.hazmat.primitives.serialization.PrivateFormat` 623 enum. 624 625 :param encryption_algorithm: An instance of an object conforming to the 626 :class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption` 627 interface. 628 629 :return bytes: Serialized key. 630 631 632.. class:: RSAPublicKey 633 634 .. versionadded:: 0.2 635 636 An `RSA`_ public key. 637 638 .. method:: encrypt(plaintext, padding) 639 640 .. versionadded:: 0.4 641 642 Encrypt data with the public key. 643 644 :param bytes plaintext: The plaintext to encrypt. 645 646 :param padding: An instance of 647 :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`. 648 649 :return bytes: Encrypted data. 650 651 .. attribute:: key_size 652 653 :type: int 654 655 The bit length of the modulus. 656 657 .. method:: public_numbers() 658 659 Create a 660 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers` 661 object. 662 663 :returns: An 664 :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers` 665 instance. 666 667 .. method:: public_bytes(encoding, format) 668 669 Allows serialization of the key to bytes. Encoding ( 670 :attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM` or 671 :attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`) and 672 format ( 673 :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo` 674 or 675 :attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.PKCS1`) 676 are chosen to define the exact serialization. 677 678 :param encoding: A value from the 679 :class:`~cryptography.hazmat.primitives.serialization.Encoding` enum. 680 681 :param format: A value from the 682 :class:`~cryptography.hazmat.primitives.serialization.PublicFormat` enum. 683 684 :return bytes: Serialized key. 685 686 .. method:: verify(signature, data, padding, algorithm) 687 688 .. versionadded:: 1.4 689 .. versionchanged:: 1.6 690 :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed` 691 can now be used as an ``algorithm``. 692 693 Verify one block of data was signed by the private key 694 associated with this public key. 695 696 :param bytes signature: The signature to verify. 697 698 :param bytes data: The message string that was signed. 699 700 :param padding: An instance of 701 :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`. 702 703 :param algorithm: An instance of 704 :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or 705 :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed` 706 if the ``data`` you want to verify has already been hashed. 707 708 :raises cryptography.exceptions.InvalidSignature: If the signature does 709 not validate. 710 711 712.. class:: RSAPublicKeyWithSerialization 713 714 .. versionadded:: 0.8 715 716 Alias for :class:`RSAPublicKey`. 717 718 719.. _`RSA`: https://en.wikipedia.org/wiki/RSA_(cryptosystem) 720.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography 721.. _`specific mathematical properties`: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Key_generation 722.. _`use 65537`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html 723.. _`at least 2048`: https://www.cosic.esat.kuleuven.be/ecrypt/ecrypt2/documents/D.SPA.20.pdf 724.. _`OpenPGP`: https://en.wikipedia.org/wiki/Pretty_Good_Privacy 725.. _`Chinese Remainder Theorem`: https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm 726.. _`security proof`: https://eprint.iacr.org/2001/062.pdf 727.. _`recommended padding algorithm`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html 728.. _`proven secure`: https://cseweb.ucsd.edu/~mihir/papers/oae.pdf 729