Home Books Training Newsletter Resources
Sign up Log in
book cover

OpenSSL Cookbook  3rd Edition

The definitive guide to using the OpenSSL command line for configuration and testing. Topics covered in this book include key and certificate management, server configuration, a step by step guide to creating a private CA, and testing of online services. Written by Ivan Ristić.


1.2.1 Key Generation

The first step in preparing to run a TLS server is to generate a private key. Before you begin, you must make several decisions:

Key algorithm

OpenSSL supports RSA, DSA, ECDSA, and EdDSA key algorithms, but not all of them are useful in practice. For example, DSA is obsolete and EdDSA is not yet widely supported. That leaves us with RSA and ECDSA algorithms to use in our certificates.

Key size

The default key sizes might not be secure, which is why you should always explicitly configure key size. For example, the default for RSA keys used to be 512 bits, which is insecure. If you used a 512-bit key on your server today, an intruder could take your certificate and use brute force to recover your private key, after which she could impersonate your web site. Today, 2,048-bit RSA keys are considered secure, or 256 bits for ECDSA.

Passphrase

Using a passphrase with a key is optional, but strongly recommended. Protected keys can be safely stored, transported, and backed up. On the other hand, such keys are inconvenient, because they can’t be used without their passphrases. For example, you might be asked to enter the passphrase every time you wish to restart your web server. For most, this is either too inconvenient or has unacceptable availability implications. In addition, using protected keys in production does not actually increase the security much, if at all. This is because, once activated, private keys are kept unprotected in program memory; an attacker who can get to the server can get the keys from there with just a little more effort. Thus, passphrases should be viewed only as a mechanism for protecting private keys when they are not installed on production systems. In other words, it’s all right to keep passphrases on production systems, next to the keys. If you need better security in production, you should invest in a hardware solution.1

To generate an RSA key, use the following genpkey command:

$ openssl genpkey -out fd.key \
-algorithm RSA \
-pkeyopt rsa_keygen_bits:2048 \
-aes-128-cbc
..........................................+++++
...................................................................+++++
Enter PEM pass phrase: ************
Verifying - Enter PEM pass phrase: ************

Here, I specified that the key be protected with AES-128. You can also use AES-256 (with the -aes-256-cbc switch), but it’s best to stay away from the other algorithms (e.g., DES, 3DES, and SEED).

⯃︎
Warning

By default, OpenSSL will set the public exponent of new RSA keys to 65,537. This is what’s known as a short public exponent, and it significantly improves the performance of RSA verification. You may come across advice to choose 3 as your public exponent and make verification even faster. Although that’s true, there are some unpleasant historical weaknesses associated with the use of 3 as a public exponent, which is why you should stick with 65,537. This choice provides a safety margin that’s been proven effective in the past.

When you use the genpkey command, the generated private keys are stored in PKCS #8 format,2 which is just text and doesn’t look like much:

$ cat fd.key
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQInW7GrFjUhUcCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBBn8AErtRKB9p7ii1+g2OhWBIIE
0MnC2dwGznZqpTMX0MYekzyxe4dKlJiIsVr1hgwmjFifzEBs/KvHBV3eIe9wDAzq
[21 lines removed...]
IfveVZzM6PLbDaysxX6jEgi4xVbqWugd9h3eAPeBv9Z5iZ/bZq5hMbt37ElA2Rnh
RfmWSzlASjQi4XAHVLCs6XmULCda6QGvyB7WXxuzbhOv3C6BPXR49z6S1MFvOyDA
2oaXkfS+Ip3x2svgFJj/VpYZHUHwRCzXcDl/CdVg9fxwxcYHuJDH16Qfue/LRtiJ
hqr4fHrnbbk+MZpDaU+h4shLRBg2dONdUEzhPkpdOOkF
-----END ENCRYPTED PRIVATE KEY-----

However, a private key isn’t just a blob of random data, even though that’s what it looks like at a glance. You can see a key’s structure using the following pkey command:

$ openssl pkey -in fd.key -text -noout
Enter pass phrase for fd.key: ****************
RSA Private-Key: (2048 bit, 2 primes)
modulus:
    00:be:79:08:22:1a:bc:78:3c:17:34:4a:d3:5f:2b:
    [...]
publicExponent: 65537 (0x10001)
privateExponent:
    10:20:95:54:b5:e8:d1:51:5d:31:9b:48:4c:5d:90:
    [...]
prime1:
    00:f5:3f:74:cf:ef:8f:93:e9:54:b3:79:a1:f2:91:
    5a:7e:15:13:26:f7:f9:d7:a8:f3:f9:6b:2b:90:93:
    57:54:cc:84:c9:ea:6f:9f:39:ad:ad:60:4c:f0:68:
    16:db:1a:49:51:56:87:f1:70:ae:c9:42:89:2a:38:
    55:3e:17:a0:78:a7:52:49:10:79:cf:99:ae:53:c8:
    e0:60:5d:7e:91:26:86:3b:79:d2:70:c0:39:38:dd:
    ed:ee:75:c0:15:c6:30:51:00:a8:93:f3:8b:25:01:
    04:25:72:fc:9c:e9:73:d0:93:11:2d:82:e2:e3:d0:
    66:c0:36:2f:b6:de:de:0d:47
prime2:
    00:c6:d2:ce:66:b5:35:6b:35:d7:bb:b0:e3:f4:2d:
    [...]
exponent1:
    00:e9:2e:e9:b9:5f:f5:2b:54:fa:c5:1f:4c:7d:5f:
    [...]
exponent2:
    00:83:ea:bc:ad:a2:cf:a5:a9:9c:d0:d8:85:f6:ae:
    [...]
coefficient:
    68:18:a7:4f:aa:86:a7:e0:92:49:76:8d:24:65:fa:
    [...]

If you need to have just the public part of a key separately, you can do that with the following pkey command:

$ openssl pkey -in fd.key -pubout -out fd-public.key
Enter pass phrase for fd.key: ****************

If you look into the newly generated file, you’ll see that the markers clearly indicate that the contained information is indeed public:

$ cat fd-public.key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvnkIIhq8eDwXNErTXytD
U1JGrYUgFsN8IgFVMJmAuY15dBvSCO+6y9FA0H08utJVtHScyWeOlo1uo0TQ3RWr
Pe7W3O2SaW2gIby2cwzGf/FBExZ+BCNXkN5z8Kd38PXDLt8ar+7MJ3vrb/sW7zs2
v+rtfRar2RmhDPpVvI6sugCeHrvYDGdA/gIZAMMg3pVFivPpHnTH4AR7rTzWCWlb
nCB3z2FVYpvumrY8TvIo5OioD2I+TQyvlxDRo14QWxIdZxvPcCUxXMN9MC8fBtLu
IlllDmah8JzF2CF5IxVgVhi7hyTtSQfKsK91tAvN30F9qkZNEpjNX37M5duHUVPb
tQIDAQAB
-----END PUBLIC KEY-----

It’s good practice to verify that the output contains what you’re expecting. For example, if you forget to include the -pubout switch on the command line, the output will contain your private key instead of the public key.

The process is similar for ECDSA keys, except that it isn’t possible to create keys of arbitrary sizes. Instead, for each key you select a named curve, which controls key size, but it controls other EC parameters as well. The following example creates a 256-bit ECDSA key using the P-256 (or secp256r1) named curve:

$ openssl genpkey -out fd.key \
-algorithm EC  \
-pkeyopt ec_paramgen_curve:P-256 \
-aes-128-cbc
Enter PEM pass phrase: ****************
Verifying - Enter PEM pass phrase: ****************

OpenSSL supports many named curves, but for web server keys, you’re generally (still) limited to only two curves that are widely supported: P-256 (also known as secp256r1 or prime256v1) and P-384 (secp384r1). Of these two, P-256 is sufficiently secure and provides better performance. If you’re curious to see a list of all named curves supported by OpenSSL, you can get it using the ecparam command and the -list_curves switch.

The recent additions x25519, x448, ed25519, and ed448 are also supported, but they are different types of curves and have to be specified using the -algorithm switch—for example:

$ openssl genpkey -algorithm ed25519
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIF6K3m4WM7/yMA9COn6HYyx7PjJCIzY7bnBoKupYgdTL
-----END PRIVATE KEY-----

1

A small number of organizations will have very strict security requirements that require the private keys to be protected at any cost. For them, the solution is to invest in a Hardware Security Module (HSM), which is a type of product specifically designed to make key extraction impossible, even with physical access to the server. To make this work, HSMs not only generate and store keys, but also perform all necessary operations (e.g., signature generation). HSMs are typically very expensive.

2

You will often see advice to generate private keys using the genrsa command. Indeed, the earlier versions of this very book used this command in the examples. However, genrsa is a legacy command and should no longer be used. There is an entire new family of commands that deal with private keys in a unified manner (i.e., one command for all private key operations, no matter the algorithm). You should also be aware that genrsa outputs keys in a legacy format. Here’s how to tell them apart: if you see BEGIN ENCRYPTED PRIVATE KEY at the top of the file, you’re dealing with PKCS #8, which is the new format. If you see BEGIN RSA PRIVATE KEY, that’s the legacy format.

< Prev
^ Table of Contents
Next >
@feistyduck

Books

  • Bulletproof TLS and PKI
  • ModSecurity Handbook
  • OpenSSL Cookbook

Training

  • Practical TLS and PKI

Resources

  • Newsletter
  • SSL/TLS and PKI History
  • Archived Books
  • Bulletproof TLS Guide

Company

  • Support
  • Website Terms of Use
  • Terms and Conditions
  • Privacy Policy
  • About Us