OpenSSL CLI Tutorial#
Installation#
Below command installs openssl:
sudo apt install openssl
Output:
openssl is already the newest version (3.0.13-0ubuntu3.5)
You can check the installed version with:
openssl version
Output:
OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
Introduction#
openssl <command> [options] [arguments]
Before we go into the details, let us first learn a bit of theory on Asymmetric Cryptography, EC and RSA.
Asymmetric Key Cryptography#
Asymmetric key cryptography is a form of cryptography where there are two keys involved - a public key and a private key.
The public key is distributed to other people but the private key is always held a secret.
There are two main forms in which asymmetric key cryptography is used: Encryption/Decryption and SignatureGeneration/Verification.
The server generates a key pair and distributes the public key to the clients.
In case of Encryption/Decryption, the clients can encrypt their transmission using the public key and the server would be the only one who is able to decrypt it as he holds the private key.
Even though the above method is logical, as its extremely time consuming, the client usually establishes a session by encrypting a symmetric key with the public key and transmits it to the server, who decrypts it using the private key and uses that symmetric key for all future communications.
Hence this article will mainly explore the generation of the key pair and encryption/decryption and signatureGeneration/Verification using RSA and EC (Elliptic Key Cryptography).
The various asymmetric key cryptography algorithms supported by OpenSSL utility are RSA, RSA-PSS, EC, X25519, X448, ED25519 and ED448.
RSA is the most common form of asymmetric key cryptography.
OpenSSL CLI Introduction#
We have a list of OpenSSL sub utilities which we can use to demonstrate the different types of asymmetric key cryptographic operations.
The main sub utilities and their respective purposes are as follows:
- GenPKey is a sub utility to generate Private Keys.
- RSA is a sub utility for processing RSA keys.
- EC is a sub utility for processing EC keys.
- DGST is a sub utility for generating a digest and also signing / verifying the digest using a private key.
- PKeyUtl is a sub utility to sign/verify hash and also encryption/decryption of plain text.
OpenSSL has a few defaults which are as follows:
- OpenSSL assumes the keys in the arguments to be of the PEM(privacy Enhanced Mail) format if not specified.
- OpenSSL considers the keys in arguments to be private keys by default.
PEM vs DER#
DER is the preferred ASN.1 syntax for Cryptographic Keys and for identifying Schemes.
But as DER is not transmittable over a network, the DER is base64 encoded to form the PEM format.
Update DER encoding here #ToDo
Update ASN.1 encoding here #ToDo
RSA#
References:
PKCS #1 specification -> RFC 8017
- A RSA Private key consists of:
- version (0 unless multi prime is used in which case its 1)
- Modulus (same length as key)
- publicExponent
- privateExponent (same length as key)
- prime1
- prime2
- exponent1
- exponent2
- coefficient
- prime n
- exponent n
- coefficient n
- A RSA Public key is nothing but extracting the Modulus and public exponent.
- Hence a public key consists of:
- Modulus
- Public Exponent
OpenSSL defaults:
- The RSA key sizes shall be a minimum of 1024 bits.
- The default size of RSA key in OpenSSL is 2048 bits.
- The default number of prime numbers used is 2.
- The maximum number of prime numbers supported is 3.
- The default public exponent is 65537.
- As the public exponent becomes smaller and smaller, the computation time becomes lesser.
EC#
Elliptic Curve public key is of the following format:
- first bit is compression
- ((n-1)/2) bits are x
- ((n-1)/2) bits are y
Structured version of ECC Keys are to be described #ToDo
Practical Experiments#
Generating a private key (RSA)#
The sub-utility used for generating a private key is genpkey
.
Generating a RSA Private Key in PEM format:
openssl genpkey -out private_key.pem -algorithm RSA
Generating a RSA 3072 bit Private Key with 3 primes and a public exponent 17 in DER format:
openssl genpkey -out private_key.der -outform DER -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -pkeyopt rsa_keygen_primes:3 -pkeyopt rsa_keygen_pubexp:17
To confirm if our parameters have taken effect, we can run the same in -text without an output file.
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -pkeyopt rsa_keygen_primes:3 -pkeyopt rsa_keygen_pubexp:17 -text
Extracting the public Key (RSA)#
Prerequisites
Generating a private key (RSA)
The public key can be extracted from the private key using the rsa
sub-utility.
We can extract the public key using the RSA utility.
There are two major formats for a RSA Public key.
The PEM public key format uses the header and footer lines:
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
The PEM RSAPublicKey format uses the header and footer lines:
-----BEGIN RSA PUBLIC KEY-----
-----END RSA PUBLIC KEY-----
To extract the key in the first PEM public key format:
openssl rsa -in private_key.pem -pubout -out public_key.pem
To extract the key in the second PEM RSAPublicKey key format:
openssl rsa -in private_key.pem -RSAPublicKey_out -out public_key.pem
Generating a signature (RSA)#
Prerequisites
Generating a private key (RSA)
Signature can be created either using the dgst
sub util or using the pkeyutl
sub utility.
Lets create a plain text:
echo "Wonderful Wolrd!" > plain_text.txt
There are two ways we can sign a plain text as described above.
Let us first generate the signature using the dgst
sub utility.
openssl dgst -sha256 -out signature.sig -sign private_key.pem plain_text.txt
Let us create another signature using the second method.
For this first lets generate the SHA2-256 digest of the plain_text.txt
.
openssl dgst -sha256 -binary -out hash.sha256 plain_text.txt
Now let us sign the generated hash using pkeyutl
.
openssl pkeyutl -sign -in hash.sha256 -inkey private_key.pem -out signature2.sig -pkeyopt digest:sha256
To show that both methods produce the same signature, we can confirm without
diff signature.sig signature2.sig
Investigate why OpenSSL does not generate a private key of -----BEGIN RSA PRIVATE KEY----- but rather generates -----BEGIN PRIVATE KEY-----. #ToDo
Verifying a signature (RSA)#
Prerequisites
Generating a signature (RSA) and Extracting the public Key (RSA)
The verify signature is similar to Generating a signature (RSA)
openssl dgst -sha256 -verify public_key.pem -signature signature.sig plain_text.txt
The second method is the roundabout way of calculating hash and then verifying the signature.
But this was not successful for me - hence lets update when we get the time. #ToDo
Encrypting a file (RSA)#
Prerequisites
Extracting the public Key (RSA)
We could encrypt any plain text using the public key as follows:
openssl pkeyutl -encrypt -inkey public_key.pem -pubin -in plain_text.txt -out cipher_text.txt
Decrypting a file (RSA)#
Prerequisites
Generating a private key (RSA)
We could decrypt any plain text using the private key as follows:
openssl pkeyutl -decrypt -inkey private_key.pem -in cipher_text.txt -out plain_text2.txt
Encrypted Private keys (RSA)#
An encrypted private key is better and safer than a plain private key.
Generation of private Key (Encrypted RSA)#
openssl genpkey -out private_key2.pem -algorithm RSA -aes-128-cbc -pass pass:hello
Now lets find out what exactly happens in the background.
Let us create a non encrypted private key from the encrypted one.
openssl rsa -in private_key2.pem -passin pass:hello -out private_key3.pem
I still don't know how to encrypt private_key3.pem to make it private_key2.pem #ToDo
I could encrypt using ```openssl enc -aes-128-cbc -e -pass pass:hello -in private_key3.pem -out private_key4.pem -a #ToDo
Hence lets fallback and try the other operations.
Extracting the Public key (Encrypted RSA)#
openssl rsa -in private_key2.pem -passin pass:hello --RSAPublicKey_out -out public_key2.pem
Generating a Signature (Encrypted RSA)#
openssl dgst -sha256 -out signature3.sig -sign private_key2.pem -passin pass:hello plain_text.txt
openssl pkeyutl -sign -in hash.sha256 -inkey private_key2.pem -passin pass:hello -out signature4.sig -pkeyopt digest:sha256
diff signature3.sig signature4.sig
Verifying the signature (Encrypted RSA)#
Find out why OpenSSL dgst function accept a RSA Public key but only accepts a generic public key.#ToDo
Hence to avoid this problem lets convert our RSA Public Key to a generic SSL public public_key.pem
openssl rsa -RSAPublicKey_in -in public_key2.pem -out public_key3.pem -pubout
openssl dgst -sha256 -verify public_key3.pem -signature signature3.sig plain_text.txt
More inforation on the above transformation can be found at How to transform between the two key styles.
Generating a private key (EC)#
Similar to Generating a private key (RSA)
openssl genpkey -out private_key.pem -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve