10

I am generating private and public keys using OpenSSL in PHP, which I intend to store in a database (although you probably don't need to know PHP to answer this question).

They look like this:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIi4rlLSKA9/8CAggA
...
-----END ENCRYPTED PRIVATE KEY-----

and

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8YvAFZHSGNITeDNdXFbc
...
-----END PUBLIC KEY-----

(and yes those are just examples)

They have been created like so:

$resource = openssl_pkey_new([
        'private_key_bits' => '2048',
        "private_key_type" => OPENSSL_KEYTYPE_RSA,
]);
openssl_pkey_export($resource, $privateKey, $passPhrase) === false
$opensslDetails = openssl_pkey_get_details($resource);
$publicKey = $opensslDetails['key'];

I want to know what the maximum length is for these private and public keys.

From my experimentation, I have found that:

  • 1704 characters for private keys
  • 1834 characters for private keys with passphrase
  • 451 characters for public keys

However I haven't found any formal documentation on this to prove that this is the case, so I can't be sure.

halfer
  • 19,824
  • 17
  • 99
  • 186
Yahya Uddin
  • 26,997
  • 35
  • 140
  • 231
  • 2 times the key size for the public key and 8 times the key size for the private key are good upper bounds. If you *really need* it more accurate, then you need to look into what elements are in a key and how they are serialized. It's possible to calculate it accurately, but a valid key has many forms and not all elements of a private key are mandatory. This question is likely too broad, because there are many valid keys that have different sizes. – Artjom B. Aug 21 '16 at 20:28
  • A upper bound is more than sufficient. I just need an upperbound for a database. – Yahya Uddin Aug 21 '16 at 20:29
  • @ArtjomB. Also what are you basing these numbers on. My key size is 2048 bit, so is my upperbound 2048 for private and 1024 for public? – Yahya Uddin Aug 21 '16 at 20:36
  • 1
    2048 bit are 256 byte. Since we're talking about ASCII here, a character is a byte. So 2 * 256 chars = 512 chars would be an upper bound for a public key and 8 * 256 chars = 2048 chars for the private key. Of course, if you permit non-standard public exponents, both factors must be incremented by one. – Artjom B. Aug 21 '16 at 20:39
  • Whoops made a slight calculation error. Also where did you figure out the upper bounds from and what do you mean "if you permit non-standard public exponents, both factors must be incremented by one"? – Yahya Uddin Aug 21 '16 at 20:43

1 Answers1

15

What is the maximum length of private and public RSA keys?

In theory, there is no limit. In practice, there is a limit. Also, limits are usually imposed on the modulus size (n = p*q), and not the public or private key per se. You may be facing additional limits from your web server or database.

For OpenSSL and RSA, your RSA keys are limited to 16K at generation. There's also a limit imposed by OpenSSL's s_client utility used during key exchange. The limit during key exchange is 2K, and it seems artificially low to me. You can side-step the s_client limit by avoiding key transport schemes used during key agreement (i.e., use DH or EDH instead of RSA).

If you start hitting the limits, then it usually indicates its time to switch to elliptic curves. 16K RSA and 521-bit EC provides about 512-bits of security.

Also see Openssl software failure for RSA 16K modulus on the OpenSSL users mailing list.


Here are some factoids on RSA key generation time using the Crypto++ library from small (256-bit) to large (60K-bit). I believe the numbers were gathered about 5 years ago on a Core2 Duo machine. OpenSSL should have asymptotically similar running times.

cryptopp$ rsa_kgen.exe 61440
Elapsed time for 61140 RSA key: 25654.01s (7 hours, 7 minutes, 34 seconds)
cryptopp$ rsa_kgen.exe 30720
Elapsed time for 30720 RSA key: 2255.30s (37 minutes, 35 seconds)
cryptopp$ rsa_kgen.exe 15360
Elapsed time for 15360 RSA key: 285.05s (4 minutes, 45 seconds)
cryptopp$ rsa_kgen.exe 11776
Elapsed time for 11776 RSA key: 142.52s (2 minutes, 22 seconds)
cryptopp$ rsa_kgen.exe 8192
Elapsed time for 8192 RSA key: 43.08s (43 seconds)
cryptopp$ rsa_kgen.exe 4096
Elapsed time for 4096 RSA key: 0.70s
cryptopp$ rsa_kgen.exe 2048
Elapsed time for 2048 RSA key: 0.09s
cryptopp$ rsa_kgen.exe 1024
Elapsed time for 1024 RSA key: 0.01s
cryptopp$ rsa_kgen.exe 512
Elapsed time for 512 RSA key: 0.00s
cryptopp$ rsa_kgen.exe 256
Elapsed time for 256 RSA key: 0.00s
jww
  • 97,681
  • 90
  • 411
  • 885
  • Wow that's a detailed answer. So what in your opinion is a good upperbound in my database, as I obviously need an upperbound. – Yahya Uddin Aug 21 '16 at 21:56
  • @YahyaUddin - You use a key that has a security level to meet your needs. If the database cannot store it because its too large, then you increase the field size or switch databases to ensure your security requirements are met. Also see [Are there any limits on length of string in mysql?](http://stackoverflow.com/q/3022170), [String field length in Postgres SQL?](http://stackoverflow.com/q/23988406) and [How SQLite on Android handles long strings?](http://stackoverflow.com/q/3068180) Maybe you should provide the name of the database engine and your schema. – jww Aug 21 '16 at 22:30
  • I'm using MySql. I wanted to define a upper bound on the string length. – Yahya Uddin Aug 21 '16 at 22:39
  • 3
    @YahyaUddin - just guessing (and it may waste some space), but use *`3*sizeof(n)*EncodingFactor+3*80`* for a public key, and *`9*sizeof(n)*EncodingFactor+3*80`* for a private key. The `c*sizeof(n)` is for the two fields of a public key or eight fields of a private key. `EncodingFactor` tries to compensate for ASN.1 -> ASCII Encoding expansion (like Hex, Base32 or Base64). The `3*80` attempts to account for the pre- and post-encapsulation headers. You may need to bump that to `5*80` for fields like the DEK-Info. – jww Aug 21 '16 at 22:48
  • 6
    What is `n` and `encodingFactor` in my case. I know my key size is 2048. I just need to know how many characters I need to specify in MySQL. – Yahya Uddin Aug 22 '16 at 03:24
  • @YahyaUddin what upper bound did you choose? – Myzel394 Oct 02 '22 at 13:25
  • The definition of the encoding can be found under [PKCS](https://www.rfc-editor.org/rfc/rfc3447) – Florat Jul 26 '23 at 16:30