Scenario: Two users Alice and Bob who are far away from each other (in other words using two different computers on different networks) want to communicate with each other (send messages and files to each other) in a secure way.
To try the commands in this blog, you need to have OpenSSL installed on your machine.
What is encryption? It is a process of making readable information as unreadable. The information we want to encrypt could be a piece of text message (e.g, as simple as your credit card number) or a file containing bank accounts or anything else.
Why you want to do that? Alice wants to send say, her credit card number (the “data” or “information” or “message”) to Bob. Before the message reaches Bob’s computer, it goes through several routers and gateways. Simply by logging the message passing through these routers, it is not difficult to see the card information and potential misuse by bad people. One can even use sophisticated network packet analysers to read all the data passing over a network device. By making card number unreadable (“encrypted”) Alice wants to make sure her card is not misused.
Lets try to encrypt Alice card having number “1234 1234 1234 1234”. Using a terminal, execute following command (don’t worry about various options given in the command, for now):
Alice Input Command:
echo “1234 1234 1234 1234” | openssl enc -aes-256-cbc -a -salt -pbkdf2 -pass pass:MySuperStrongPassword
In above command,
enc —> Encrypt/Decrypt mode (encrypt by default).
pass -> Use the password to encrypt, in our case “MySuperStrongPassword”.
Output:
You should see an output similar to: U2FsdGVkX1+BExlwmfX21dM3D0/DGOL7gwMgsXtf1H1ufQXwBlcXql3P6U+ozcFv
which is the encrypted message for Alice card number. Alice could share this message with Bob without the fear of her card misuse. But wait, how does Bob know the card number from this message? Execute below command:
Bob Input Command:
echo U2FsdGVkX1+BExlwmfX21dM3D0/DGOL7gwMgsXtf1H1ufQXwBlcXql3P6U+ozcFv | openssl enc -d -aes-256-cbc -salt -pbkdf2 -a -pass pass:MySuperStrongPassword
In above command,
d —> decrypt the message.
The output should be “1234 1234 1234 1234” which is Alice card. How did Bob know the password (MySuperStrongPassword) that Alice used to encrypt? Alice has to share this with Bob by some other way (may be a phone call or email or send a letter). The same password is used for both encryption and decryption. This is called symmetric key. Alice shares her key (the password in this case) with anyone she wants to share her card.
In above example, Alice used “MySuperStrongPassword” to encrypt the message. Though it is easy to remember, not very difficult to guess. Alice wants a really complex key, save it as a file, that is impossible to guess and use it for encryption of her card. This is what public key does. Note that public and private keys exist in pair. You first create private key to generate public key. More about private keys later. Execute below commands:
Bob Input Commands (not Alice):
1. Generate private key
openssl genrsa -out my_private.pem 2048
genrsa —> Generate RSA private key
out my_private.pem —> output to a file my_private.pem
2048 —> Key length in bits.
Above command creates a private key file in current directory. Execute below command:
openssl rsa -in my_private.pem -text -noout
output:2. Generate public key from private key
openssl rsa -in my_private.pem -pubout -out my_public.pem
You should see my_public.pem file which is public key. Bob now contains both public and private keys.
Back to encryption. We encrypt messages using public keys only. So, Bob shares his public key file with Alice. Alice encrypts her card number using below command, this time using my_public.pem key file shared to her by Bob.
echo “1234 1234 1234 1234:” | openssl pkeyutl -encrypt -pubin -inkey my_public.pem -out encrypted_card.bin
The output (encrypted card number) is stored in file encrypted_card.bin in current directory of Alice.
Alice shares the file with Bob, who would execute below command to decrypt. Bob uses his private key to decrypt the message in file.
openssl pkeyutl -decrypt -inkey my_private.pem -in encrypted_card.bin -out decrypted_card.txt
The above command creates decrypted card number on Bob computer. Take a look the file contents? You should see 1234 1234 1234 1234.
Notes:
Suppose Alice wants to send a file to Bob. She is worried the file contents may be altered before reaching Bob. It may be ok if others view the contents of the file, but must not be altered midway. This where digest is helpful. It is used for message integrity and ensure contents are not changed during transit.
You may have seen digest value when downloading software from prominent websites. You compare digest value given on the download website and compute on you own for the downloaded file to ensure the downloaded file is not altered in anyway.
The message digest is a fixed length string. Message digest sometimes is known as hash value. There are two popular ways to computer digest.
An example to computer digest value for a file is given below:
On Alice computer:
echo “This is a file for your viewing” > test_sha256.txt
openssl dgst -sha256 test_sha256.txt
You would notice the output (digest value) of above command as:
SHA2-256(test_sha256.txt)= 3851cba6bac19ba76a2ac45d7e9b0e5d82e4ec5746bc494159853290ed08e143
Now share the text_sha256.txt with Bob, who would execute same command (openssl dgst -sha256 test_sha256.txt). He would get identical digest value as Alice thus ensuring file contents are not altered. Try changing the file test_sha256.txt even by one charecter and see what happens to the command output? The digest value would be completely different from that of Alice!!
Note:
Alice wants to send a message to Bob. How can Bob be certain that the message is actually sent by Alice and it is not modified on its way to him? This is what digital signatures provide. Note that digital signature does not itself encrypt the original message. It only assures that message is from Alice and that message is not modified on its way. Here is how it works:
What are digital signature benefits here?
Let's try with an example:
1. Create private-public key pair by Alice (commands using above sections)
openssl rsa -in my_private.pem -text -noout
openssl rsa -in my_private.pem -pubout -out my_public.pem
echo "1234 1234 1234 1234" > my_card.txt
2. Create message digest (the hash) and sign the digest using private key. (We often combine the two steps into one)
openssl dgst -sha256 -sign my_private.pem -out my_card_hash_signed.bin my_card.txt
3. Alice sends my_public.pem, my_card.txt and my_card_hash_signed.bin to Bob.
4. Verification by Bob:
openssl dgst -sha256 -verify my_public.pem -signature my_card_hash_signed.bin my_card.txt
Output on Bob computer:
Verified OK.
The verification ensures that the my_card.txt has not been modified on its way to Bob. But there is still one problem. A bad actor could have intercepted the message, replaced the entire message by signing with his/her private key, include a wrong card and public key and send to Bob. How to ensure that message is actually from the right sender, Alice? Using Digital certificates.
In case of digital signatures, you needed a private/public key pair (asymmetric keys). HMAC (Hash based Message Authentication Code) solves the problem using a secret key and is much simpler to use.
HMAC is solving below problems:
Taking the example in above section (digital signature above), lets see how HMAC helps achieve the same.
1. Alice creates HMAC for the file containing card (my_card.txt)
openssl dgst -sha256 -hmac "MySuperSecretPassword" my_card.txt You should see output similar to: HMAC-SHA2-256(my_card.txt)= 8799acb89e49e8c094670d86421994110324f3b484a3ca20f2f5459b6e02ecfd
2. Bob executes exact same command, to get exact HMAC output, thus ensuring message integrity and authenticity (because he received password from Alice, which only she knows).
This is way simpler!!
Digital cerficates confirms that public key belongs to the sender. The sender could be a website, piece of code or a person/service/devices. Accordingly, there are three types of certificates.
How it works
The procedure to obtain the certificate depends on what kind of cert you want. Majority are for installation on websites, which are SSL/TLS, which is given below:
To obtain a commercial certificate, you need to pay the charges to CA. Below we show steps for a self-signed certificate:
openssl genrsa -out server.key 2048
2. Generate CSR (certificate signing request)
openssl req -new -key server.key -out server.csr -subj "/CN=example.com"
In the above command, server.crt is your self-signed certificate.
What does digital certificate contain?
It contains your (sender) public key copy + your identity information + public key of the issuing CA + validity date + issuing party (the CA details). All this information is signed by the private key of the CA (meaning digitally signed).