OpenSSL cheatsheet

I’ve always wanted to remember all the parameters that a command is actually using, however, my memory is not as good as it used to be. So, I need some cheatsheets from time to time.

Maybe you can benefit from this Cheatsheet if you are reading this.

According to https://openssl.org, “OpenSSL is a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library…”. It is licensed as some kind of Apache license. So, yes, basically it is free to use.

Working with Keys

The first thing we can do with OpenSSL is creating a new Private Key. In the example case, we are creating a key named test.private.key 4096 bit long. We can use another lengths (2048, 1024). The “more bits” used in the key generation, the stronger the cypher. 2048 is a good length for security.

# Create a new PRIVATE key
openssl genrsa -out test.private.key 4096

We might also need to create a public key to be distributed. It is quite difficult to find out a private key from a public key (it would take even years of computation), however, it is very simple to get the public key from the private key:

# Get the PUBLIC key from the private key.
openssl rsa -pubout -in  test.private.key  -out test.public.key

Both, private and public keys should have the same modulus. (You take a look to this post if you want to know why):

# Public key and Private Key need to have same modulus value to be a Key Pair
openssl rsa -noout -modulus -in test.private.key
openssl rsa -noout -modulus -pubin -in test.public.key

If the modulus are different, then the keys doesn’t match one with the other. Thus, what we cipher with the public key can’t be deciphered with the private one. Of course, “public key” means that we can give that key to anyone as something public so anyone can send messages ciphered messages to us. And “private key” means that it is private and none should know the content, we must keep in absolute secret our private keys.

Encrypt and Decrypt files

We won’t be able to encrypt large files using our public key. Let’s say that using a 4096 bit key we can only cipher up to roughly 500 bytes. Obviously it is not enough. And what’s more important, this cipher is really slow. However, we could use this to cipher some data:

# Encrypt with public key
openssl rsautl -encrypt -inkey test.public.key  -pubin -in small_file -out small_encrypted_file.dat

# Decrypt with private key
openssl rsautl --decrypt -inkey test.private.key  -in small_encrypted_file.dat -out new_small_file.txt
# Encrypt with "private key" or sign the file:
openssl rsautl -encrypt -inkey test.private.key  -sign -in small_file -out small_signed_file.dat

# Decrypt with "public key" or verify a signed file:
openssl rsautl -verify -inkey test.public.key -pubin -in small_signed_file.dat -out new_verified_small_file

However, we can encrypt a file as large as we want just by using symmetric cryptography, using a password shared between 2 endpoints. so the message can only be read by those who have the the password to decrypt it:

# Encrypt a file:
openssl enc -aes-256-cbc -salt -in file.xxx  -out file.xxx.encripted

# Decrypt the file
openssl enc -aes-256-cbc -d -in file.xxx.encripted -out new_file.xxx

Digests (Hash algorithms)

This is the way to get hashes for file, so they can be verified by the recipients of the files.

# Digest example Using SHA-512 algorithm
openssl dgst -sha512 file.xxx

# To get the list of all digests available:
openssl dgst -list --digest-comands

In order to see if a file has been modified, we could get a digest of the file and sign it (encrypt it with the private key):

openssl dgst  -sha256 -sign test.private.key  file.xxx  > file.xxx.sign

We van verify the signature of the file if we have the public key:

openssl dgst -sha256 -verify  test.public.key  -signature file.xxx.sign  file.xxx

We can get back the original information encoded in file.xxx.sign using the command shown above when I talked about Decrypt with public key:

openssl rsautl -verify -inkey test.public.key -pubin -in file.xxx.sign -out simply_as_curiosity_file

The sha256 sum will be in the “simply_as_curiosity_file” file in a binary format. We can see it using hd (hex dump) command:

So, if we’ve been able to decrypt the signature file using a public key, it must be true that it has been encrypted using the private key that only is installed in one place of for a single user.

Certificates

To create a new certificate we need a Certificate request first using our private key, we can run a command like the next one:

openssl req -new -sha256 -key test.private.key -subj "/C=ES/ST=Salamanca/L=Corporario/O=Test OpenSSL S.L./OU=IT department/CN=test.example.com" -out test.example.com.csr

Of course, the modulus in our certificate must be the same than in our public and in our private keys.

openssl req -noout -modulus -in test.example.com.csr  

For the verification of the certificate request, we can run:

openssl req -text -noout -verify -in test.example.com.csr  

We can also create a Certificate Request and generate a private key for that certificate in the same command:

# This generates a certifcate request (test.example.com..csr) and a new private key (2.test.private.key)
# Last parameter -nodes means that there will be no password for the private key.
openssl req -newkey rsa:4096 -subj "/C=ES/ST=Salamanca/L=Corporario/O=Test OpenSSL S.L./OU=IT department/CN=test.example.com" \
 -out test.example.com.csr -keyout 2.test.private.key -nodes

Using this certificate request and the public key, we can ask to a certification authority to provide us a singed certificate (previous payments, of course). Or, we can create a self signed certificate which could be useful in companies or in projects where we could locally trust the certificate recently done. In order to create a self signed certificate, we could do:

openssl x509 -signkey test.private.key  -in test.example.com.csr  -req -days 365 -out test.domain.crt

We can see the information in the certificate with these commands:

# Check Modulus. It must be the same as in private key and public key
openssl x509 -modulus -noout -in test.domain.crt

# Show certificate info.
openssl x509 -noout -text -in test.domain.crt

In order to verify the certificate we can use this command, though it will fail because it is a self-signed certificate and possibly an untrusted one.

openssl verify test.domain.crt

We can verify a certificate installed in a Web Site this way:

openssl s_client --connect jicg.eu:443

# Or even we can extract it:
openssl s_client --connect jicg.eu:443 | sed -n '/----BEGIN CERTIFICATE/, /----END CERTIFICATE/p' 2>/dev/null

Generate Random Numbers

We can also generate random numbers with Openssl this way:

# Example a 30 digit number base64 encoded
openssl rand -base64 30

We can even manage to generate quite secure passwords using a command like the next one.

openssl rand  4096 | tr -cd '[:alnum:];:!@$#%=,.-_' | head -c 16 ; echo

A Divertimento with RSA Basis

RSA algorithm is quite easy to implement. It’s been around since 1979 and it is still quite safe.

We only need two prime numbers p and q. Let’s imagine p=701 and q=997.

The way to test a number is a prime number could be like this one: k**(p-1)%p = 1. Being k a natural integer (let’s say 2) and p a prime number. So, in my case and using Python interpreter:

After we have the prime number, we need to evaluate the “modulus” number. It is p*q = 701*997 = 698897. Let’s call this number nn=698897.

Once we have the modulus, we can calculate the Euler’s Totient function for n. Which, given that p and q are prime numbers and n is p*q, eu(n)=(p-1)(q-1) = 102 * 232 = 697200.

We only need to choose a number coprime with 697200. Let’s call this number e and ramdomly I’ll choose e=179. This number e will be used as the public key.

Only one more thing is needed: our private key. The private key will be a number d satisfying e*d%eu(n) == 1. This is only possible if e and n are coprime numbers. So, lets say d=140219.

e*d%eu(n) = 1 — I mean (179*140219)%697200 = 1

So the d is my private key. You should never share your private key. Never!

An use case

Let’s imagine I have my credit card and my mobile phone with me. But I don’t remember the code for my credit card and I can’t use it. So I ask my wife using a message in the mobile phone. “Please, can you tell me the number of the credit card? Please, encode it using RSA with public key 179 and modulus 698897. Thank you, dear”

Now let’s imagine that the credit card code is 5237.

My wife will do the following calculation: 5237**e%n = 197497

And she can answer the message like this: “The code is 197497”.

Great, now I know that the credit card code is 197497**d%n = 5237 — I can use my credit card now!!!!

However, someone steals my phone and my credit card. NOOOOOO!!!!! And the theft is able to see the messages and he knows that the public key is 179 and the modulus is 140219. However, he needs to find out what is private key. The private key is not in the messages.

Finding out the private key from the public key.

Well… the theft have the modulus (698897) and also the public key 179. And he also knows the secret message is “197497”.

So, he needs to find 2 prime numbers p,q so that n=p*q. For sure he knows that 1 and 2 are not these numbers, and he knows that the smallest number in (p,q) will be smaller or equal to the squared root of n. And none of them will be an even number..

So, for sure he could guess the private key finding out p,q. This can easily be done using this silly python script:

for np in range(3,ceil(sqrt(n)), 2):
  if (n%np==0):
    nq = n/np
    print(np, nq)
    break

So he can easily find out what were the p and q values: 701 and 997. So he can find out the value of the Euler Toitient function: eun=(700*996) = 697200

And knowing that e=179 he can just find out the private key value using the following python script (the next algorithm is not efficient at all, but it is enough in this case for the sake of simplicity):

for d in range(1,eun):
   if (e*d%eun==1):
      print(d)
      break

After running that, the theft knows that d is 140219. He guessed the Private Key value. The only thing he has left to do to guess the decrypted message: 197497**d%n = 5237

The theft got it!!! 5237 is code for the card. He can steal the money and this was done in very little time.

So RSA is a weak Cryptographic System.

Well, I wouldn’t consider that to be true. I’ve just used a 20bit modulus. So the algorithm finds the solution in 725 steps as maximum: ceil(sqrt(2**20-1)/2)

If I used 768 bit modulus (which is considered to be really unsecure) the algorithm would only need 27861425773824902618883922777920627422247679544911070145715529933961303512072360206822627414227418267832271612411904 steps as maximum to find out a reliable solution. This has been accomplished in only 22.5 hours.

Given that the least recommended is 2048 bits, and that it is recommended 4096 bits you can imagine that reliably finding out the numbers could take as long as 2.612e1232 steps to find out the solution as maximum. Quite a bit hard to evaluate that!!!