Ever wondered what TLS is? You might heard about private- and public-keys, about digital certificates and don’t know what exactly that is and how you can use them? Frankly I was in the same situation and thought I write an blog article regarding these issues to make them a little bit clearer for everyone who needs or wants to learn about it.
To use Transport Layer Security (TLS) a private-public-key-pair, and a X.509 certificate is needed. With the public key, a file or message gets encoded and can only be decoded with the corresponding private key, that’s called asymmetric cryptography. The most common algorithm for the creation of these key pairs are RSA and ECC. Where the digital certificate guarantees the authenticity and integrity of a server or a client.
In this tutorial we will learn how to generate key-pairs using RSA and ECC as well as an self-signed and CA-signed X.509 certificate. This guide also covers the first steps of using signature and encryption with OpenSSL. The OS I used for this guide is Debian 10.5, but the commands should work on Ubuntu or other distributions too.
Why is OpenSSL so popular?
OpenSSL is an open source toolkit for the Transport Layer Security (TLS) and Secure Socket Layer (SSL) protocols and is available for Linux, Windows, macOS and BSD systems. It is also a cryptographic library and offers the possibility to create RSA and ECC key pairs as well as X.509 certificates and can also be used for encryption, decryption and signing documents.
The pioneer – RSA asymmetric cryptography
In order to encrypt or sign data, we first need to create a private-public key pair. The most common algorithm is RSA. It’s been around for nearly 20 years and can be classified as secure, though the big downside of this algorithm is the high amount of bits needed for a secure key. To create a private key the following command is used where -aes256 is the algorithm used to encrypt the private key file, private_key.pem is the name of the output file and 4096 is the key length in bits (the key should be at least 2048 bit long). Beware to keep the private key secret. Anyone who gets this key is able to decrypt documents that are encrypted for you.
openssl genrsa -aes256 -out private_key.pem 4096
After entering the command you will be prompted to enter a password to encrypt the private key file so nobody who steals this file, is able to use it. Don’t forget this password!
$ openssl genrsa -aes256 -out private_key.pem 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
………………………………………………………………………………..++++
……………………………………….++++
e is 65537 (0x010001)
The output file should look like this:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,7DA374B25D942240BE15A62E2353EAAF
7bmq9RcUinjeeHD6vsSTQlntpV7Jubu1S3PYgclztjNTItyZ5SWueOwvK3UN/JSW
…
…
a5NfKwUZyjesoudqrBEsbzHMJ5RnvvJR2J9dMs4JmCSgVmfEoPeDtRraXLKz8d64
/LsPThaLELW2P/j44X6V3P14BARrs+bux415S8AFBUB8vibLoEHPVlAfhkoFkiRq
-----END RSA PRIVATE KEY-----
Now we need to generate the corresponding public key with the following command where private_key.pem is the input of the just generated private key and public_key.pem is the name of the output file. If you use an encrypted private key file you need to enter the password in order to generate the public key. This key is shared with others in order for them to encrypt data for you and therefore it’s not supposed to be encrypted like the private key.
openssl rsa -in private_key.pem -pubout -out public_key.pem
The output should look like this:
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxKilTm0pTGrPiSsIVGF4
…
…
…
tbe4TErSqyNTbGmPfGVGrsJE6fhniAZgi4s5T841IpeFZNKyJVEHaqfRkagTBk8Y
E6Iju10/4gXGJ9QwPMTMcqUCAwEAAQ==
-----END PUBLIC KEY-----
The hidden champion in cryptography – ECC
ECC (Elliptic-curve cryptography) is another algorithm which can be used for the asymmetric cryptography. It’s based on elliptic curves over finite fields. The principle is the same like RSA, it needs a private-public key pair for encryption and decryption. Instead of specifying the key length, we have to define which curve we want to use. The most common curves are:
Curve | Also known as | Type of curve |
prime256v1 | secp256r1 | NIST curve |
secp256k1 | – | Koblitz curve |
brainpoolP384r1 | – | Brainpool curve |
To get a list of all available curves use the command:
openssl ecparam -list_curves
From the previous output we can choose a curve based on which we will create a private key. In the following command prime256v1 is the used curve, aes256 is the used algorithm for the encryption of the private key file and private_key.pem is the name of the output file. Unlike the RSA private key command, we need to combine two commands to generate an encrypted file.
openssl ecparam -genkey -name prime256v1 | openssl ec -aes256 -out private_key.pem
If you create an RSA and ECC private key and compare them, you will notice that the ECC key is much smaller while providing the same security. That’s the big advantage of ECC.
The output file should look like this:
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,DA4374DFE3D9626EC80552334FA8C229
DM1K6h+6pGXgfB9YDh/Z8qLMQOlk3mFIRMalidVXPlVxYM5zXPDYnVJcKheQqTcZ
d64tVUTZgwI2H0sXNhWKQNzILLBdqbVtVefLU9ojiCS/rFEnLV+axzH4Y1Na+xih
3MFBqQgViisulIB8NGMG3c43Dhj1a2rp8BReU9rOIVc=
-----END EC PRIVATE KEY-----
Next, we will create the corresponding public key. In the following command private_key.pem is the private key for which we want to create the public key and public_key.pem is the name of the output file.
openssl ec -in private_key.pem -pubout -out public_key.pem
Later in this guide we will use these keys for encryption, decryption and signing but first some information about file extensions. Stay tuned!
What are PEM and DER file extensions?
Now that we know what cryptographic keys are and how to create them, you might wonder what the file extension .pem is. In this section I will give you a brief overview of the common file extensions that you might come across while working with cryptography.
.PEM files
PEM (Privacy Enhanced Mail) is a format for cryptographic keys, digital certificates and CSRs (Certificate Signing Request). It contains one or more Base64 ASCII items each with plain text header and footers.
-----BEGIN <type> -----
…
…
…
-----END <type> -----
The content can be an end-entity certificate, a private key or multiple certificates forming a complete chain of trust. Common file extensions of PEM files can be .crt, .pem, .cer and .key (for private keys).
.DER files
A DER (Destinguish Encoding Rules) files contains binary encoded X.509 certificates and private keys. Unlike a PEM format, it doesn’t contain any plain text headers or footers. Common extensions for DER files are .der and .cer. and it looks as an output of a hex-dump like this:
3082 07fd 3082 05e5 a003 0201 0202 1068
1604 dff3 34f1 71d8 0a73 5599 c141 7230
0d06 092a 8648 86f7 0d01 010b 0500 3072
310b 3009 0603 5504 0613 0255 5331 0e30
0c06 0355 0408 0c05 5465 7861 7331 1030
0e06 0355 0407 0c07 486f 7573 746f 6e31
1130 0f06 0355 040a 0c08 5353 4c20 436f
7270 312e 302c 0603 5504 030c 2553 534c
2e63 6f6d 2045 5620 5353 4c20 496e 7465
...
To show the content of a DER file, you can use the following command:
openssl x509 -inform der -in certificate.der -text -noout
If you want to convert a PEM file to a DER file, the following command can be used:
openssl x509 -outform der -in certificate.pem -out certificate.der
All in one! PKCS#12 containers: .P12 or .PFX files
PKCS#12 is a binary format for storing a certificate chain and private keys in a single file. The usual file extension is .p12 and .pfx. With the following command you can create a PKCS#12 file from a certificate and a private key. Here the private_key.key needs to be the private key for the certificate certificate.crt . After executing the command you will be prompted to create a password to protect the .pfx file. Don’t forget this password because you will need it to access any item stored in the file!
openssl pkcs12 -export -out certificate.pfx -inkey priate_key.key -in certificate.crt -certfile MORE.crt
Tell me who you are: X.509 digital certificates
If you visit for example a website, you want to be sure to visit the real website and not a fake one. Therefore digital certificates are used. These certificates securely associates cryptographic key pair with entities such as websites or server. A X.509 certificate includes a public key, a digital signature, information about the entity associated with the certificate and the certification authority that signed it. When you visit a website, your browser checks in the background the validity of the certificate and show a warning if the certificate is not valid or not signed by a trusted certification authority.
In order to use TLS you need to provide a X.509 certificate. This certificate can be self-signed or signed by a trusted certification authority (CA). Note that a self-signed certificate can’t be used for public websites since it’s not signed by a trusted authority. Therefore you will need a CA-signed (Certification Authority) certificate.
Quick and dirty: Self-Signed
In case of using a self-signed certificate you only need one command to create a private key and the corresponding certificate. In the command sha256 is the used hashing algorithm, rsa:2048 is the used algorithm for the generation of the private key and the length of the key in bit, private_key.key is the name of the generated private key, certificate.crt is the name of the self-signed certificate and 1024 stands for certificates duration of validity.
openssl req -x509 -sha256 -newkey rsa:2048 -keyout private_key.key -out certificate.crt -days 1024 -nodes
Well trusted: CA-Signed
In addition to a self-signed certificate you can use a CA-signed certificate. This is signed by a trusted certification authority. First you have to create a certificate signing request (CSR) and a new private key. After the creation you will be prompted to enter a passphrase for the private key. The newly generated private key file privkey.pem is encrypted and can only be decrypted with the passphrase.
openssl req -new -in private_key.key -out cert_signing_request.csr
After the passphrase you will be prompted to enter information that will be written into your certificate. Everyone who gets a copy of your certificate (i.e. if someone wants to connect to your server)is able to see these information.
$ openssl req -new -in private_key.key -out cert_signing_request.csr Generating a RSA private key ……………..+++++ ……………………..+++++ writing new private key to 'privkey.pem' Enter PEM pass phrase: Verifying - Enter PEM pass phrase: 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]:AT State or Province Name (full name) [Some-State]:Vienna Locality Name (eg, city) []:Vienna Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company Organizational Unit Name (eg, section) []:Security Common Name (e.g. server FQDN or YOUR name) []:My Name Email Address []:email@mycompany.at Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:whats my age An optional company name []:
The ouput is a PEM file (with .csr extension) looking like the following.
-----BEGIN CERTIFICATE REQUEST-----
MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
…
…
zCDlQ7akwlF2h4RC4YJJojNpmAwHGOeAs3u1A5g9gZCcn/8tygAZflpVV86PHeXu
DFAxWU5GlZIpGHUXi0ETRZ0GaDXLbUg1IKiYFRK2
-----END CERTIFICATE REQUEST-----
To get a trusted certificate from this CSR you need to send it to a CA which will then sign it.
Intro in encryption, decryption and digital signature
Now that we generated key pairs and got a certificate we can finally start to use OpenSSL for encryption, decryption and signature.
How to encrypt?
First we start with the encryption of a file. This can be achieved with a public key. Let’s assume we got Alice and Bob who got a secret file only they are allowed to read. First they need to exchange their public keys in order for the other to encrypt data. If Alice wants to encrypt a file for Bob she needs to use the following command where pubkey_bob.pem is bobs public key, filename is the name of the file they want to encrypt and filename.enc the encrypted output file.
openssl rsautl -encrypt -pubin -inkey pubkey_bob.pem -in filename -out filename.enc
Let´s decrypt!
Now she can send the file to Bob over an unsecure channel and only Bob is able to read the content of the file. To decrypt the file Bob needs to use his private key in the following command where private_key_bob is Bobs private key (which only he has) filename.enc the encrypted file and decrypted_name.pem the output file.
openssl rsautl -decrypt -inkey private_key_bob.key -in filename.enc -out decrypted_file.pem
Create an OpenSSL signature
But encryption and decryption is not all we can do with OpenSSL. To ensure the integrity and authenticity of the document, Alice can sign it with her private key. By signing a document a hash value (digest) of the document is generated, and encrypted with the private key. This digest is sent alongside the document to the receiver. The receiver will then decrypt the digest with the corresponding public key, calculate a digest of the received document himself and compare these two values. If they match, the document wasn’t altered on the way from the sender to the receiver. In the following command priv_key_alice.key is Alice’s private key, -sha256 the hashing algorithm, signature.sign the name of the signed digest, and filename.txt the name of the input file.
openssl dgst -sign priv_key_alice.pem -keyform PEM -sha256 -out signature.sign -binary filename.txt
When Bob gets the document filename.txt inclusive the signature signature.sign, he can verify it with the following command:
openssl dgst -verify pub_key_alice.pem -keyform PEM -sha256 -signature signature.sign -binary filename.txt
If the document wasn’t altered he will get the message :
Verified OK
This is a guest article from my friend Nikolaus (Niki) Müllner who want to share his experience with the powerful tool OpenSSL. Feel free to take any examples in your scripts and applications to greatly enhance your software with high-end cryptography!
Any comments will help other readers to better understand OpenSSL, please contribute in English or German!