OpenSSL

From Segfault
Jump to navigation Jump to search

Installation

From a tarball:

wget https://www.openssl.org/source/openssl-1.1.0.tar.gz{,.sha256,.asc}
sha256sum openssl*.tar.gz | grep --color `cat openssl*.tar.gz.sha256`
gpg --verify openssl*.tar.gz.asc                                                                     # → PGP Key IDs

tar -xzvf openssl*.tar.gz

From the Git repository:

git clone git://git.openssl.org/openssl.git openssl-git

Install prerequisites:

apt-get install zlib1g-dev                                                                           # Debian, Ubuntu
dnf install zlib-devel                                                                               # Fedora, CentOS

Build and install:[1]

./Configure --prefix=/opt/openssl no-idea no-mdc2 no-rc5 no-zlib no-ssl3 no-ssl3-method shared linux-$(uname -m)
make depend && make && sudo make install

Note: we're using the shared option to install libssl.so. You may have to utilize LD_LIBRARY_PATH[2] later on though :-\

You man want to run some tests afterwards:

make test

Usage

Private key

Certificates need a private key to be generated from[3][4]. To generate an RSA key:

openssl genrsa -out privkey.pem 4096                                                                 # Add -aes128 to encrypt the private key.

For a DSA key:

openssl dsaparam -out dsaparam.pem 4096
openssl gendsa -out privkey.pem dsaparam.pem                                                         # Add -aes128 to encrypt the private key.

Or, for an ECC key:

openssl ecparam -name prime256v1 -genkey -noout -out privkey.pem                                     # Encrypt with: openssl ec -in privkey.pem -aes128 -out privkey_enc.pem

Newer versions of OpenSSL support[5] support X25519, but we cannot sign certificates with that key[6] and we'll have to use an even newer version[7] to use Ed25519 for our key:

openssl genpkey -algorithm Ed25519 -out privkey.pem                                                  # Add -aes128 to encrypt the private key.

Notes:

  • Use the -noout option to omit the EC parameters, as they may not be needed.[8]
  • In lieu of a SafeCurves OpenSSL implementation[9][10], we shall choose P-256 (or P-384)[11] for now.
  • Add -param_enc explicit to EC key generation[12] to include the curve's parameters into the key.

Public key

To get the public key from the private' key we just generated, use:

openssl  rsa -in privkey.pem -pubout
openssl  dsa -in privkey.pem -pubout
openssl   ec -in privkey.pem -pubout
openssl pkey -in privkey.pem -pubout                                                                 # Should work for all key types.

Self-signed certificate

Self-signed certificates can be created without a Certificate Authority (CA):

SUBJECT='/C=US/ST=CA/L=SF/O=None/OU=None/CN=localhost/emailAddress=admin@localhost'
openssl req -new -x509 -sha512 -days 3650 -key privkey.pem -out cert.pem -subj "$SUBJECT"            # For DSA keys, use -sha256 instead.
openssl dhparam -out dhparam.pem 2048                                                                # This[13] may take a long time to complete.

The generated certificate can now be used, for example for a webserver:

openssl s_server -tls1_3 -www -accept localhost:8443 -key privkey.pem -cert cert.pem -dhparam dhparam.pem

Connect via:

curl -k https://localhost:8443                                                                       # Using -insecure because it's a self-signed certificate
openssl s_client -connect localhost:8443

Verification

For RSA keys, we can check if the modulus[14] of the certificate matches the key; this is sometimes useful to see if a certificate (generated by a 3rd party) would match our key:

$ openssl rsa -in privkey.pem -noout -modulus | md5sum
56184f0a09279f188ee20cfc715bad99  -
openssl x509 -in cert.pem -noout -modulus | md5sum
56184f0a09279f188ee20cfc715bad99  -

EC keys have no RSA modulus, but we can still check if the public part matches:[15]

$ openssl ec -in privkey.pem -text -noout 2>/dev/null | awk '/^pub:/,/ASN1/'
pub:
   04:2c:53:6b:0a:5b:15:bd:6f:dd:7b:af:ce:fd:0c:
   09:11:25:f1:71:69:b2:47:da:49:b9:d0:39:df:91:
   31:29:d5:60:cc:be:cf:da:35:70:49:f5:35:8e:12:
   3c:d8:eb:a6:11:42:40:fc:49:47:20:e5:24:f3:8f:
   64:50:18:b8:e2
ASN1 OID: prime256v1

$ openssl ec -in privkey.pem -pubout 2>/dev/null
297e4cf3d550560f1549fe1e920683c9  -

Or, more generally (this will work for Ed25519 keys too):

$ openssl pkey -in privkey.pem -text -noout
pub:
   04:d3:4b:1d:fd:72:4f:e0:6e:04:6f:32:dc:80:37:
   6a:55:6c:82:94:de:db:e2:c8:44:5c:75:4b:28:24:
   46:2c:5b:88:a7:4e:45:a4:25:c8:8c:1c:37:b8:ed:
   78:f7:1d:cd:4d:22:35:b8:09:da:19:f1:81:7f:e7:
   47:6c:84:03:54

$ openssl pkey -in privkey.pem -pubout | md5sum
297e4cf3d550560f1549fe1e920683c9  -

And for the certificate:

$ openssl x509 -in cert.pem -text -noout
               pub:
                   04:2c:53:6b:0a:5b:15:bd:6f:dd:7b:af:ce:fd:0c:
                   09:11:25:f1:71:69:b2:47:da:49:b9:d0:39:df:91:
                   31:29:d5:60:cc:be:cf:da:35:70:49:f5:35:8e:12:
                   3c:d8:eb:a6:11:42:40:fc:49:47:20:e5:24:f3:8f:
                   64:50:18:b8:e2
$ openssl x509 -in cert.pem -noout -pubkey | md5sum
297e4cf3d550560f1549fe1e920683c9  -

PKCS12

PKCS 12 is a file format used to store a privat key along with its certificate, protected with a password-based symmetric key. Sometimes it's necessary to remove the password[16] from the pkcs12 file.

openssl pkcs12 -in file.p12 -nodes  -out file.pem
openssl pkcs12 -in file.pem -export -out file_plain.p12
rm file.pem

Certificate bundles

Sometimes we need to split up[17] a certificate bundle into separate certificate files. With awk:

awk 'BEGIN {c=0;} /BEGIN CERT/{c++} {print > "cert." c ".pem"}' < ../bundle.pem
c_rehash .

Or, if csplit[18] is available:

csplit -k -b '%02d.pem' -f cert- ../bundle.pem '/END CERTIFICATE/+1' {1000}
c_rehash .

Root CAs

Let's Encrypt

TBD

CAcert

Since Debian does no longer[19][20][21] ship the CAcert Root Certificate, we have to install it ourselves:

wget https://www.cacert.org/certs/root.crt                          # Find the predicament! :-)
sudo mkdir /usr/local/share/ca-certificates/cacert/
sudo mv root.crt /usr/local/share/ca-certificates/cacert/
sudo update-ca-certificates

Now the CAcert certificate should be usable.

Self-Signed

This will explain[22], in short, how to be our own self-signed certificate authority (CA).

SUBJECT='/C=US/ST=CA/L=SF/O=Foobar CA/OU=None/CN=Foobar CA/emailAddress=ca@example.org'
openssl req -new -x509 -sha512 -days 3650 -extensions v3_ca -keyout cakey.pem -newkey rsa:4096 -sha512 -nodes -out cacert.pem -subj "$SUBJECT"

Or, for EC[23] keys:

openssl ecparam -genkey -name prime256v1 -out cakey.pem
openssl req -new -x509 -sha512 -days 3650 -key cakey.pem -nodes -out cacert.pem -subj "$SUBJECT"

Notes:

  • With -nodes, the resulting ca-key.pem will not be encrypted.
  • The Organization Name (O) must match the one from the certificate request we're about to create.
  • The Organizational UnitName (ON) is optional, but we included it here for completeness.

Create the certificate request:

SUBJECT='/C=US/ST=CA/L=SF/O=Foobar CA/OU=None/CN=server.example.org/emailAddress=root@example.org'
openssl req -new -out server-req.pem -keyout server-key.pem -newkey rsa:2048 -sha512 -nodes -subj "$SUBJECT"

Again, for EC keys:

openssl ecparam -genkey -name prime256v1 -out server-key.pem
openssl req -new -sha512 -key server-key.pem -nodes -out server-req.pem -subj "$SUBJECT"

Sign the request by our CA and generate the certificate:

openssl x509 -req -sha256 -days 730 -in server-req.pem -CA cacert.pem -CAkey cakey.pem -CAcreateserial -out server-cert.pem

OCSP

OCSP is used to check the revocation status of certificates. Firefox uses OCSP since version 3[24], Google Chrome stopped using OCSP in 2012 [25], citing latency and privacy issues.

In Firefox, OCSP is enabled with:

security.OCSP.enabled = 1                         # Default
security.OCSP.require = false                     # Assume that the certificate is not revoked as a fallback mechanism
security.OCSP.GET.enabled = false                 # Use POST requests to the OCSP responder by default

OCSP stapling can be used as an alternative to OCSP: the server will append a previously received signed OCSP response to the client, thus eliminating the need for the client to contact the CA. OCSP stapling needs to be supported by both the server and the client.[26][27]

On the client side, OCSP stapling seems to be enabled by default in Google Chrome[28] and in Firefox with version 26[29]:

security.ssl.enable_ocsp_stapling = true          # Default

Let's try to check the revocation status of a certificate[30][31], using the CA's OCSP responder:

openssl s_client -CApath /etc/ssl -connect example.net:443 -showcerts < /dev/null > showcerts

If more than one certificat has been received, we need to extract them and then chain them together[32]:

i=1; while [ $i -le $(grep -c BEGIN showcerts) ]; do
       awk "/-----BEGIN/,/-----END/ {if(++m==1)n++;if(n=="$i") print;if(/-----END/)m=0}" showcerts > showcerts_${i}
       i=$((i+1))
done
cat showcerts_[0-9] > showcerts_chained

Get the OCSP responder URI:

$ openssl x509 -in showcerts_1 -noout -ocsp_uri
http://ocsp.startssl.com/sub/class1/server/ca

Send a request to the responder.

  • Use -noverify to skip verification on the response. This is sometimes needed.
  • Use -no_nonce to not send a nonce to the responder, as some might not support it.
  • We use the (undocumented) -header option[33][34], otherwise responders might answer with "Code=400,Reason=Bad Request"
$ openssl ocsp -issuer showcerts_chained -cert showcerts_1 \
          -url http://ocsp.startssl.com/sub/class1/server/ca -header HOST ocsp.startssl.com -text

OCSP Request Data:
   Version: 1 (0x0)
   Requestor List:
       Certificate ID:
         Hash Algorithm: sha1
         Issuer Name Hash: 6568874F40750F016A3475625E1F5C93E5A26D58
         Issuer Key Hash: 607D48F437F0E4A850500BE9C2122FBEEC081235
         Serial Number: 05DA538DDBD6C2
   Request Extensions:
       OCSP Nonce:
           0410517917662E9B1DA2DE389DDDDE9527B7
OCSP Response Data:
   OCSP Response Status: successful (0x0)
   Response Type: Basic OCSP Response
   Version: 1 (0x0)
   Responder Id: C = IL, O = StartCom Ltd. (Start Commercial Limited), CN = StartCom Class 1 Server OCSP Signer
   Produced At: Aug 24 02:13:04 2015 GMT
   Responses:
   Certificate ID:
     Hash Algorithm: sha1
     Issuer Name Hash: 6568874F40750F016A3475625E1F5C93E5A26D58
     Issuer Key Hash: EB4234D098B0AB9FF41B6B08F7CC642EEF0E2C45
     Serial Number: 05DA538DDBD6C2
   Cert Status: good
   This Update: Aug 24 02:13:04 2015 GMT
   Next Update: Aug 26 02:13:04 2015 GMT
[...]
showcerts_1: ERROR: No Status found.

The OCSP responder replied with "successful" to our request - alas, OpenSSL thinks that no status has been found because the "Responses" field was empty[30] :-\

See also

Links



References

  1. Compilation and Installation
  2. $LD_LIBRARY_PATH oder doch nicht?!
  3. HOWTO certificates (Archive)
  4. OpenSSL generate different types of self signed certificate
  5. OpenSSL 1.1.0 Series Release Notes
  6. (no subject) - "It is not possible to "self-sign" an X25519 certificate because X25519 is a key-exchange algorithm only, not a digital signature algorithm."
  7. OpenSSL 1.1.1 Series Release Notes
  8. Why does openssl writes EC parameters when generating private key?
  9. SafeCurves: choosing safe curves for elliptic-curve cryptography
  10. Safe ECC curves (2014-01-01)
  11. Which elliptic curve should I use?
  12. Command Line Elliptic Curve Operations
  13. OpenVPN dhparam
  14. How does RSA work?
  15. How can you check if a private key and certificate match in OpenSSL with ECDSA?
  16. remove the passphrase from a pkcs12 certificate
  17. How can I split a CA certificate bundle into separate files?
  18. GNU/coreutils
  19. Debian #213086 - ca-certificates: Please include CAcert.org certificate
  20. Debian #718434 - ca-certificates: should CAcert.org be included?
  21. Debian and CAcert
  22. OpenSSL Certificate Authority
  23. ECDSA Certificate Authorities and Certificates With OpenSSL
  24. Bug 110161 - (ocspdefault) enable OCSP by default
  25. Revocation checking and Chrome's CRL (2012-02-05)
  26. SSLUseStapling (Apache 2.4)
  27. nginx-announce: nginx-1.3.7
  28. Check For Server Certificate Revocation checkbox is confusing
  29. OCSP Stapling in Firefox
  30. 30.0 30.1 OpenSSL: Manually verify a certificate against an OCSP
  31. Checking OCSP revocation using OpenSSL
  32. OCSP unknown status when passing cert, good status when passing serial
  33. ocsp - Online Certificate Status Protocol utility
  34. OCSP stapling with certificate servers behind CloudFlare