akshayupendran.github.io


Project maintained by akshayupendran Hosted on GitHub Pages — Theme by mattgraham

OpenSSL RSA

Introduction

OpenSSL is a general purpose cryptography library / utility. In this article we will be exploring the Command Line Interface / Utility part of OpenSSL for RSA and Elliptic Curve Cryptography (EC). We will be using OpenSSL 1.1.1f in the below article. 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:

  1. GenPKey is a sub utility to generate Private Keys.
  2. RSA is a sub utility for processing RSA keys.
  3. EC is a sub utility for processing EC keys.
  4. DGST is a sub utility for generating a digest and also signing / verifying the digest using a private key.
  5. 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:

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

OpenSSL defaults:

EC

Elliptic Curve public key is of the following format:

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