1 OpenSSL Command Line
OpenSSL is the world's most widely used implementation of the Transport Layer
Security (TLS) protocol. At the core, it's also a robust and a high-performing
cryptographic library with support for a wide range of cryptographic primitives. In
addition to the library code, OpenSSL provides a set of command-line tools that
serve a variety of purposes, including support for common PKI operations and TLS
testing.
OpenSSL is a de facto standard in this space and comes with a long history. The
code initially began its life in 1995 under the name SSLeay,1 when it was developed
by Eric A. Young and Tim J. Hudson. OpenSSL as a separate project was born in 1998,
when Eric and Tim decided to begin working on a commercial SSL/TLS toolkit called
BSAFE SSL-C. A community of developers picked up the project and continued to
maintain it.
Today, OpenSSL is ubiquitous on the server side and in many client programs. The
com- mand-line tools are also the most common choice for key and certi?cate
management. When it comes to browsers, OpenSSL also has a substantial market share,
albeit via Google's fork, called BoringSSL.
OpenSSL used to be dual-licensed under OpenSSL and SSLeay licenses. Both are BSD-
like, with an advertising clause. With version 3.0, released in September 2021,
OpenSSL simpli?ed its licensing by moving to Apache License v2.0.
Getting Started
If you're using one of the Unix platforms, getting started with OpenSSL should be
easy; you're virtually guaranteed to have it already installed on your system.
Still, things could go wrong. For example, you could have a version that's just not
right, or there could be other tools (e.g., LibreSSL) con?gured to respond when
OpenSSL is invoked. For this reason, it's best to ?rst check what you have
installed and resort to using a custom installation only if absolutely necessary.
Another option is to look for a packaging platform. For example, for OS X you
1 The letters "eay" in the name SSLeay are Eric A. Young's initials.
could use Brew or MacPorts. As always, compiling something from scratch once is
rarely a problem; maintaining that piece of software inde?nitely is.
In this chapter, I assume that you're using a Unix platform because that's the
natural envi- ronment for OpenSSL. On Windows, it's less common to compile software
from scratch be- cause the tooling is not readily available. You can still compile
OpenSSL yourself, but it might take more work. Alternatively, you can consider
downloading the binaries from the Shining Light Productions web site.2 If you're
downloading binaries from multiple web sites, you need to ensure that they're not
compiled under different versions of OpenSSL. If they are, you might experience
crashes that are dif?cult to troubleshoot. The best approach is to use a single
bundle of programs that includes everything that you need. For example, if you want
to run Apache on Windows, you can get your binaries from the Apache Lounge web
site.3
Determine OpenSSL Version and Con?guration
Before you do any work, you should know which OpenSSL version you'll be using. TLS
and PKI continue to develop at a fairly rapid pace, and you may ?nd that what you
can do is limited if your version of OpenSSL doesn't support them. Here's what I
get for version information with openssl version on Ubuntu 20.04 LTS, which is the
system that I'll be using for the examples in this chapter:
$ openssl version
OpenSSL 1.1.1f 31 Mar 2020
At the time of writing, OpenSSL 1.1.1 is the dominant branch used in production and
has all the nice features. On older systems, you may ?nd a release from the 1.1.0
branch, which is ?ne because it can be used securely with TLS 1.2, but it won't
support modern features, such as TLS 1.3. In the other direction is OpenSSL 3.0,
which introduces a major update of the libraries, with substantial architectural
changes and a switch to the Apache License 2.0 for better interoperability with
other programs and libraries. The command-line tooling, which is what I am covering
in this chapter and the next, should be pretty much the same. That said, every
release-and especially the major ones-is very likely to change the tools' behavior,
often in subtle ways. When you're changing from one branch to another, it's worth
going through the change documentation to understand what the differences might be.
Note
Although you wouldn't know it from looking at the version number, various oper-
ating systems often don't actually ship the exact of?cial OpenSSL releases. More
of- ten than not, they contain forks that are either customized for a speci?c
platform or patched to address various known issues. However, the version number
generally
2 Win32/Win64 OpenSSL (Shining Light Productions, retrieved 19 July 2020)
3 Apache 2.4 VS16 Windows Binaries and Modules (Apache Lounge, retrieved 18
September 2021)
stays the same, and there is no indication that the code is a fork of the original
project that may have different capabilities. Keep this in mind if you notice
something un- expected.
To get complete version information, use the -a switch:
$ openssl version -a OpenSSL 1.1.1f 31 Mar 2020
built on: Mon Apr 20 11:53:50 2020 UTC platform: debian-amd64
options: bn(64,64) rc4(16x,int) des(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -
O2 ...
-fdebug-prefix-map=/build/openssl-P_ODHM/openssl-1.1.1f=. -fstack-protector-
strong ...
-Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE...
_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 ...
-DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM ...
-DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -
DVPAES...
_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG ...
-Wdate-time -D_FORTIFY_SOURCE=2 OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1" Seeding source: os-specific
I don't suppose that you would ?nd this output very interesting initially, but it's
useful to know where you can ?nd out how your OpenSSL was compiled. Of special
interest is the OPENSSLDIR setting, which in my example points to /usr/lib/ssl; it
will tell you where OpenSSL looks for its default con?guration and root certi?
cates. On my system, that location is essentially an alias for /etc/ssl, Ubuntu's
main location for PKI-related ?les:
lrwxrwxrwx 1 root root 14 Apr 20 11:53 certs -> /etc/ssl/certs
drwxr-xr-x 2 root root 4096 May 14 21:38 misc
lrwxrwxrwx 1 root root 20 Apr 20 11:53 openssl.cnf -> /etc/ssl/openssl.cnf
lrwxrwxrwx 1 root root 16 Apr 20 11:53 private -> /etc/ssl/private
The misc/ folder contains a few supplementary scripts, the most interesting of
which are the scripts that allow you to implement a private certi?cation authority
(CA). You may or may not end up using it, but later in this chapter I will show you
how to do the equivalent work from scratch.
Building OpenSSL
In most cases, you will be using the system-supplied version of OpenSSL, but
sometimes there are good reasons to use a newer or indeed an older version. For
example, if you have an older system, it may be stuck with a version of OpenSSL
that does not support TLS 1.3. On the other side, newer OpenSSL versions might not
support SSL 2 or SSL 3. Although this is the
right thing to do in a general case, you'll need support for these older features
if your job is to test systems for security.
You can start by downloading the most recent version of OpenSSL (in my case,
1.1.1g):
$ wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
The next step is to con?gure OpenSSL before compilation. For this, you will usually
use the config script, which ?rst attempts to guess your architecture and then runs
through the con?guration process:
$ ./config \
--prefix=/opt/openssl \
--openssldir=/opt/openssl \ no-shared \
-DOPENSSL_TLS_SECURITY_LEVEL=2 \
enable-ec_nistp_64_gcc_128
The automated architecture detection can sometimes fail (e.g., with older versions
of OpenSSL on OS X), in which case you should instead invoke the Configure script
with the explicit architecture string. The con?guration syntax is otherwise the
same.
Unless you're sure you want to do otherwise, it is essential to use the --prefix
option to install OpenSSL to a private location that doesn't clash with the system-
provided version. Getting this wrong may break your server. The other important
option is no-shared, which forces static linking and makes self-contained command-
line tools. If you don't use this option, you'll need to play with your
LD_LIBRARY_PATH con?guration to get your tools to work.
When compiling OpenSSL 1.1.0 or later, the OPENSSL_TLS_SECURITY_LEVEL option con?
gures the default security level, which establishes default minimum security
requirements for all library users. It's very useful to set this value at compile
time as it can be used to prevent con?guration mistakes. I discuss security levels
in more detail later in this chapter.
The enable-ec_nistp_64_gcc_128 parameter activates optimized versions of certain
frequent- ly used elliptic curves. This optimization depends on a compiler feature
that can't be auto- matically detected, which is why it's disabled by default. The
complete set of con?guration options is available on the OpenSSL wiki.4
Note
When compiling software, it's important to be familiar with the default con?
guration of your compiler. System-provided packages are usually compiled using
various hardening options, but if you compile some software yourself there is no
guarantee that the same options will be used.5
4 Compilation and Installation (OpenSSL, retrieved 12 August 2020)
5 Hardening (Debian, 3 August 2020)
If you're compiling a version before 1.1.0, you'll need to build the dependencies ?
rst:
$ make depend
OpenSSL 1.1.0 and above will do this automatically, so you can proceed to build the
main package with the following:
$ make
$ make test
$ sudo make install
You'll get the following in /opt/openssl:
drwxr-xr-x 2 root root
4096 Jun
3 08:49 bin
drwxr-xr-x 2 root root
4096 Jun
3 08:49 certs
drwxr-xr-x 3 root root
4096 Jun
3 08:49 include
drwxr-xr-x 4 root root
4096 Jun
3 08:49 lib
drwxr-xr-x 6 root root
4096 Jun
3 08:48 man
drwxr-xr-x 2 root root
4096 Jun
3 08:49 misc
-rw-r--r-- 1 root root
10835 Jun
3 08:49 openssl.cnf
drwxr-xr-x 2 root root
4096 Jun
3 08:49 private
The private/ folder is empty, but that's normal; you do not yet have any private
keys. On the other hand, you'll probably be surprised to learn that the certs/
folder is empty too. OpenSSL does not include any root certi?cates; maintaining a
trust store is considered outside the scope of the project. Luckily, your operating
system probably already comes with a trust store that you can use immediately. The
following worked on my server:
$ cd /opt/openssl
$ sudo rmdir certs
$ sudo ln -s /etc/ssl/certs
Examine Available Commands
OpenSSL is a cryptographic toolkit that consists of many different utilities. I
counted 48 in my version. If there was ever an appropriate time to use the phrase
Swiss Army knife of cryp- tography, this is it. Even though you'll use only a
handful of the utilities, you should familiar- ize yourself with everything that's
available because you never know what you might need in the future.
To get an idea of what is on offer, simply request help:
$ openssl help
The ?rst part of the help output lists all available utilities. To get more
information about a particular utility, use the man command followed by the name of
the utility. For example, man
ciphers will give you detailed information on how cipher suites are con?gured.
However, man openssl-ciphers should also work:
Standard commands
asn1parse
ca
ciphers
cms
crl
crl2pkcs7
dgst
dhparam
dsa
dsaparam
ec
ecparam
enc
engine
errstr
gendsa
genpkey
genrsa
help
list
nseq
ocsp
passwd
pkcs12
pkcs7
pkcs8
pkey
pkeyparam
pkeyutl
prime
rand
rehash
req
rsa
rsautl
s_client
s_server
s_time
sess_id
smime
speed
spkac
srp
storeutl
ts
verify
version
x509
The help output doesn't actually end there, but the rest is somewhat less
interesting. In the second part, you get the list of message digest commands:
Message Digest commands (see the `dgst' command for more details)
blake2b512
blake2s256
gost
md4
md5
rmd160
sha1
sha224
sha256
sha3-224
sha3-256
sha3-384
sha3-512
sha384
sha512
sha512-224
sha512-256
shake128
shake256
sm3
And then in the third part, you'll see the list of all cipher commands:
Cipher commands (see the `enc' command for more details)
aes-128-cbc
aes-128-ecb
aes-192-cbc
aes-192-ecb
aes-256-cbc
aes-256-ecb
aria-128-cbc
aria-128-cfb
aria-128-cfb1
aria-128-cfb8
aria-128-ctr
aria-128-ecb
aria-128-ofb
aria-192-cbc
aria-192-cfb
aria-192-cfb1
aria-192-cfb8
aria-192-ctr
aria-192-ecb
aria-192-ofb
aria-256-cbc
aria-256-cfb
aria-256-cfb1
aria-256-cfb8
aria-256-ctr
aria-256-ecb
aria-256-ofb
base64
bf
bf-cbc
bf-cfb
bf-ecb
bf-ofb
camellia-128-cbc
camellia-128-ecb
camellia-192-cbc
camellia-192-ecb
camellia-256-cbc
camellia-256-ecb
cast
cast-cbc
cast5-cbc
cast5-cfb
cast5-ecb
cast5-ofb
des
des-cbc
des-cfb
des-ecb
des-ede
des-ede-cbc
des-ede-cfb
des-ede-ofb
des-ede3
des-ede3-cbc
des-ede3-cfb
des-ede3-ofb
des-ofb
des3
desx
rc2
rc2-40-cbc
rc2-64-cbc
rc2-cbc
rc2-cfb
rc2-ecb
rc2-ofb
rc4
rc4-40
seed
seed-cbc
seed-cfb
seed-ecb
seed-ofb
sm4-cbc
sm4-cfb
sm4-ctr
sm4-ecb
sm4-ofb
Building a Trust Store
OpenSSL does not come with a collection of trusted root certi?cates (also known as
a root store or a trust store), so if you're installing from scratch you'll have to
?nd them somewhere else. One possibility is to use the trust store built into your
operating system, as I've shown earlier. This choice is usually ?ne, but the built-
in trust stores may not always be up to date. Also, in a mixed environment there
could be meaningful differences between the default stores in a variety of systems.
A consistent and possibly better choice-but one that involves more work
-is to reuse Mozilla's work. Mozilla put a lot of effort into maintaining a
transparent and up-to-date root store for use in Firefox.6
Because it's open source, Mozilla keeps the trust store in the source code
repository:
https://hg.mozilla.org/releases/mozilla-beta/file/tip/security/nss/lib/ckfw...
/builtins/certdata.txt
Unfortunately, its certi?cate collection is in a proprietary format, which is not
of much use to others as is. If you don't mind getting the collection via a third
party, the Curl project provides a regularly updated conversion in Privacy-Enhanced
Mail (PEM) format, which you can use directly:
http://curl.haxx.se/docs/caextract.html
If you'd rather work directly with Mozilla, you can convert its data using the same
tool that the Curl project is using. You'll ?nd more information about it in the
following section.
Note
If you have an itch to write your own conversion script, note that Mozilla's root
certi?cate ?le is not a simple list of certi?cates. Although most of the certi?
cates are those that are considered trusted, there are also some that are
explicitly disallowed. Additionally, some certi?cates may only be considered
trusted for certain types of usage. The Perl script I describe here is smart enough
to know the difference.
At this point, what you have is a root store with all trusted certi?cates in the
same ?le. This will work ?ne if you're only going to be using it with, say, the
s_client tool. In that case, all you need to do is point the -CAfile switch to your
root store. Replacing the root store on a server will require more work, depending
on what operating system is used.
On Ubuntu, for example, you'll need to replace the contents of the /etc/ssl/certs
folder. Ubuntu ships with a tool called update-ca-certificates that might work.
Alternatively, you
6 Mozilla CA Certi?cate Store (Mozilla; 9 August 2020)
could make the changes manually by replicating the structure of the existing data.
From the looks of it, that folder contains the trusted certi?cates as individual ?
les, as well as all of them in a single ?le called ca-certificates.crt. You will
also observe some symbolic links; they are created by the OpenSSL's rehash or
c_rehash tools. The drawback of any manual changes is that they may be overwritten
when the system is updated.
Manual Conversion
To convert Mozilla's root store, the Curl project uses a Perl script originally
written by Guenter Knauf. This script is part of the Curl project, but you can
download it directly by following this link:
https://raw.githubusercontent.com/curl/curl/master/lib/mk-ca-bundle.pl
After you download and run the script, it will fetch the certi?cate data from
Mozilla and convert it to the PEM format:
$ ./mk-ca-bundle.pl SHA256 of old file: 0
Downloading certdata.txt ... Get certdata with curl! [...]
Downloaded certdata.txt
SHA256 of new file:
cc6408bd4be7fbfb8699bdb40ccb7f6de5780d681d87785ea362646e4dad5e8... e
Processing 'certdata.txt' ...
Done (138 CA certs processed, 30 skipped).
If you keep previously downloaded certi?cate data around, the script will use it to
determine what changed and process only the updates.
Key and Certi?cate Management
Most users turn to OpenSSL because they wish to con?gure and run a web server that
supports SSL. That process consists of three steps: (1) generate a private key, (2)
create a Certi?cate Signing Request (CSR) and send it to a CA, and (3) install the
CA-provided certi?cate in your web server. These steps (and a few others) are
covered in this section.
Key Generation
The ?rst 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 sup-
ported. That leaves us with RSA and ECDSA algorithms to use in our certi?cates.
Key size
The default key sizes might not be secure, which is why you should always
explicitly con?gure 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 certi?cate and use brute force to recover your private
key, after which she could imper- sonate 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.7
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: ************
7 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 speci?cally
designed to make key extraction impossi- ble, 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.
Here, I speci?ed 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 signi?cantly improves the perfor-
mance of RSA veri?cation. You may come across advice to choose 3 as your pub- lic
exponent and make veri?cation 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
for- mat,8 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 rsa
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:
8 You will often see advice to generate private keys using the genrsa command.
Indeed, the earlier versions of this very book used this com- mand 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 uni?ed 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 ?le, you're dealing
with PKCS #8, which is the new format. If you see BEGIN RSA PRIVATE KEY, that's the
legacy format.
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
rsa command:
$ openssl pkey -in fd.key -pubout -out fd-public.key Enter pass phrase for fd.key:
****************
If you look into the newly generated ?le, 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 suf?ciently
secure and provides better perfor- mance. 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 dif- ferent types of curves and have to be speci?ed using the -algorithm
switch-for example:
$ openssl genpkey -algorithm ed25519
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIF6K3m4WM7/yMA9COn6HYyx7PjJCIzY7bnBoKupYgdTL
-----END PRIVATE KEY-----
Creating Certi?cate Signing Requests
Once you have a private key, you can proceed to create a Certi?cate Signing Request
(CSR). This is a formal request asking a CA to sign a certi?cate, and it contains
the public key of the entity requesting the certi?cate and some information about
the entity. This data will all be part of the certi?cate. A CSR is always signed
with the private key corresponding to the public key it carries.
CSR creation is usually an interactive process during which you'll be providing the
elements of the certi?cate distinguished name. Read the instructions given by the
openssl tool careful- ly; if you want a ?eld to be empty, you must enter a single
dot (.) on the line, rather than just hit Return. If you do the latter, OpenSSL
will populate the corresponding CSR ?eld with the default value. (This behavior
doesn't make any sense when used with the default OpenSSL con?guration, which is
what virtually everyone does. It does make sense once you realize you can actually
change the defaults, either by modifying the OpenSSL con?guration or by pro- viding
your own con?guration ?les.)
$ openssl req -new -key fd.key -out fd.csr Enter pass phrase for fd.key:
****************
You are about to be asked to enter information that will be incorporated into your
certificate request.
What you are about to enter is what is called a Distinguished Name or a DN. There
are quite a few fields but you can leave some blank
For some fields there will be a default value, If you enter '.', the field will be
left blank.
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:. Locality Name (eg, city)
[]:London
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Feisty Duck Ltd
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.feistyduck.com Email Address []:
Please enter the following 'extra' attributes to be sent with your certificate
request
A challenge password []:
An optional company name []:
Note
According to Section 5.4.1 of RFC 2985,9 challenge password is an optional ?eld
that was intended for use during certi?cate revocation as a way of identifying the
original entity that had requested the certi?cate. If entered, the password will be
included verbatim in the CSR and communicated to the CA. It's rare to ?nd a CA that
relies on this ?eld; all instructions I've seen recommend leaving it alone. Having
a challenge password does not increase the security of the CSR in any way. Further,
this ?eld should not be confused with the key passphrase, which is a separate
feature.
After a CSR is generated, use it to sign your own certi?cate and/or send it to a
public CA and ask it to sign the certi?cate. Both approaches are described in the
following sections. But before you do that, it's a good idea to double-check that
the CSR is correct. Here's how:
$ openssl req -text -in fd.csr -noout Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = GB, L = London, O = Feisty Duck Ltd, CN = www.feistyduck.com Subject
Public Key Info:
Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit)
pub:
04:8a:d5:de:69:30:c7:77:b0:a0:54:f7:b3:34:9a:
96:1c:23:81:e3:9c:0c:81:a6:8a:a5:14:76:f4:4c:
9 RFC 2985: PKCS #9: Selected Object Classes and Attribute Types Version 2.0 (M.
Nystrom and B. Kaliski, November 2000)
b3:10:cb:ee:50:d1:ea:70:e9:7f:8f:75:67:f9:12:
83:b0:11:e7:6c:64:de:bc:af:bd:3f:43:da:b8:41: 96:75:34:63:85
ASN1 OID: prime256v1 NIST CURVE: P-256
Attributes: a0:00
Signature Algorithm: ecdsa-with-SHA256
30:44:02:20:52:b9:cf:ca:d1:25:1c:b7:57:65:fb:24:5d:95:
15:f0:39:79:36:6c:d6:0a:42:6e:26:7c:54:e8:71:17:a5:99:
02:20:5a:e0:cd:b3:60:ec:2c:fc:29:8c:f9:21:01:08:9a:a3:
0d:fc:9a:d3:4f:24:fb:23:4f:c6:d7:a2:14:d1:54:f9
Creating CSRs from Existing Certi?cates
You can save yourself some typing if you're renewing a certi?cate and don't want to
make any changes to the information presented in it. With the following command,
you can create a brand-new CSR from an existing certi?cate:
$ openssl x509 -x509toreq -in fd.crt -out fd.csr -signkey fd.key
Note
Unless you're using some form of public key pinning and wish to continue using the
existing key, it's best practice to generate a new key every time you apply for a
new certi?cate. Key generation is quick and inexpensive and reduces your exposure
in case of a compromise that went undetected.
Unattended CSR Generation
CSR generation doesn't have to be interactive. Using a custom OpenSSL con?
guration ?le, you can both automate the process (as explained in this section) and
do certain things that are not possible interactively (e.g., how to have multiple
domain names in the same certi?cate, as discussed in subsequent sections).
For example, let's say that we want to automate the generation of a CSR for
www.feistyduck.com. We would start by creating a ?le fd.cnf with the following
contents:
[req] prompt = no
distinguished_name = dn req_extensions = ext input_password = PASSPHRASE
[dn]
CN = www.feistyduck.com
emailAddress = webmaster@feistyduck.com
O = Feisty Duck Ltd L = London
C = GB