Symmetric encryption schemes are typically used to encrypt large amounts of data using the same key to both encrypt and decrypt shown in the figure below:
To begin with, on the KaliVM, generate a random 32-byte symmetric key and store it in
openssl rand 32 > sk.bin
One symmetric encryption algorithm that can be used is AES-256. There are several modes it supports with varying properties. One mode that is not recommended is ECB (electronic code book) mode. With this mode, blocks of plaintext that are identical in a file have the exact same ciphertext. Using the symmetric key generated, we will first encrypt a string of 64 "A" characters and examine the resulting ciphertext.
python3 -c 'print(64*"A")' | openssl enc -aes-256-ecb -pass file:sk.bin - | xxd
Examine the output and see the repeated pattern that appears in the ciphertext. Answer the following questions:
AES also supports a cipher-block chaining mode (CBC) in which the ciphertext output of the previous block is used as input in the subsequent block's encryption. This eliminates the behavior seen previously. Repeat the operation using CBC mode.
python3 -c 'print(64*"A")' | openssl enc -aes-256-cbc -pass file:sk.bin - | xxd
Symmetric encryption and decryption are typically done on files. Use the following command to create the file of 64 "A"s as
python3 -c 'print(64*"A")' > file.txt
Then, encrypt it with AES-256-CBC using
sk.bin to create
file_sk.bin (using the
_ to denote the key used to encrypt the file) and examine the encrypted file with
openssl enc -aes-256-cbc -in file.txt -out file_sk.bin -pass file:sk.bin xxd file_sk.bin
Repeat the encryption again and compare its output with the previous one.
Decrypt the file using
sk.bin to recover the original file. Verify proper decryption by performing a
openssl enc -d -aes-256-cbc -in file_sk.bin -out decrypt.txt -pass file:sk.bin diff file.txt decrypt.txt
rm sk.bin file.txt file_sk.bin decrypt.txt
If two parties (Alice and Bob), want to encrypt and decrypt messages between themselves using a symmetric key (e.g.
sk.bin), how can they securely distribute the key?
Symmetric encryption has a key distribution problem in which two parties wishing to exchange encrypted data must first agree upon a symmetric key that must be kept secret. Asymmetric encryption schemes attempt to address this by creating a key pair in which one key is public and one is private, then using them to generate a secret symmetric key that no one else can obtain. One such algorithm for doing so is the Diffie-Hellman key exchange: an algorithm that is not so much of an exchange as a mutual generation of a shared secret key.
To begin with, create two subdirectories in your home directory, one each for Alice and Bob. Any file we generate in these subdirectories will be private while any data we place in the home directory will be considered public.
cd; mkdir Bob Alice
The algorithm uses a set of global public parameters to operate. We first generate and publish these parameters for everyone to see using the privacy-enhanced mail format (
openssl genpkey -genparam -algorithm DH -out ~/PubDHParams.pem
Using the commands below, examine the PEM file directly to show the parameters encoded in Base64. Then use
openssl to decode the parameters and examine the output.
cat ~/PubDHParams.pem openssl pkeyparam -in ~/PubDHParams.pem -text -noout
Based on these global parameters, both Bob and Alice can generate their own private and public key pairs that can be used to perform the Diffie-Hellman algorithm. First, we generate Bob's keypair and examine it.
cd ~/Bob openssl genpkey -paramfile ~/PubDHParams.pem -out BobPrivDHKey.pem openssl pkey -in BobPrivDHKey.pem -text -noout
We then publish the public key part of it.
openssl pkey -in BobPrivDHKey.pem -pubout -out ~/BobPubDHKey.pem openssl pkey -pubin -in ~/BobPubDHKey.pem -text -noout
Next, we generate a keypair for Alice and publish its public key.
cd ~/Alice openssl genpkey -paramfile ~/PubDHParams.pem -out AlicePrivDHKey.pem openssl pkey -in AlicePrivDHKey.pem -pubout -out ~/AlicePubDHKey.pem
At this point, everyone can see the public keys for Alice and Bob as pictured below.
The Diffie-Hellman algorithm allows Bob to take Alice's public key (
~/AlicePubDHKey.pem) and his own private key (
BobPrivDHKey.pem) to generate another key (
Bob_sk.bin) that combines the two.
cd ~/Bob openssl pkeyutl -derive -inkey BobPrivDHKey.pem -peerkey ~/AlicePubDHKey.pem -out sk.bin
Similarly, the algorithm also allows Alice to take Bob's public key and her own private key to generate the exact same key.
cd ~/Alice openssl pkeyutl -derive -inkey AlicePrivDHKey.pem -peerkey ~/BobPubDHKey.pem -out sk.bin
xxd, examine the keys Bob and Alice have generated via Diffie-Hellman.
xxd ~/Bob/sk.bin xxd ~/Alice/sk.bin cmp ~/Bob/sk.bin ~/Alice/sk.bin
With this approach, Bob and Alice can now use this key as a shared symmetric key, effectively solving the problem of key distribution.
Cleanup before going to the next step.
rm ~/PubDHParams.pem ~/BobPubDHKey.pem ~/AlicePubDHKey.pem ~/Alice/sk.bin ~/Bob/sk.bin ~/Alice/AlicePrivDHKey.pem ~/Bob/BobPrivDHKey.pem
Asymmetric encryption keys can obviate the need to generate a shared symmetric key altogether. In this exercise, we will use RSA to have Alice send a secret message to Bob directly, relying only on Bob's public key.
Using the command below, we'll then generate a key pair for Bob using RSA and store it in
cd Bob openssl genpkey -algorithm rsa -out BobPrivKey.pem
Using the commands below, examine the PEM file directly to show the private key encoded in Base64. Then use
openssl to decode the key and examine the output.
cat BobPrivKey.pem openssl pkey -in BobPrivKey.pem -text -noout
Using the command below, emit the public key into the home directory (
openssl pkey -in BobPrivKey.pem -pubout -out ~/BobPubKey.pem
Examine the public key and see that it contains only the modulus:
cat ~/BobPubKey.pem openssl pkey -in ~/BobPubKey.pem -pubin -text -noout
Repeat the process to generate a keypair for Alice.
cd ~/Alice openssl genpkey -algorithm rsa -out AlicePrivKey.pem openssl pkey -in AlicePrivKey.pem -pubout -out ~/AlicePubKey.pem
As Bob has published his public key, Alice now wants to encrypt a message to him using this key that only he can decrypt with the corresponding private key. Begin by having Alice create a file, consisting of 512 "A" characters. Then, using Bob's public key, attempt to encrypt the file.
cd ~/Alice python3 -c 'print(512*"A")' > file.txt openssl pkeyutl -encrypt -in file.txt -pubin -inkey ~/BobPubKey.pem -out ~/file_BobPubKey.bin
Repeat the encryption using 64 "A" characters, publishing the encrypted file at
../file_BobPubKey.bin. Examine its output.
python3 -c 'print(64*"A")' > file.txt openssl pkeyutl -encrypt -in file.txt -pubin -inkey ~/BobPubKey.pem -out ~/file_BobPubKey.bin xxd ~/file_BobPubKey.bin
Although anyone can view the encrypted file, only Bob can decrypt it with his private key:
Change into Bob's directory and have Bob use his private key to decrypt the message. Examine the decrypted file to ensure the original file has been recovered.
cd ~/Bob openssl pkeyutl -decrypt -in ~/file_BobPubKey.bin -inkey BobPrivKey.pem -out decrypt.txt diff decrypt.txt ~/Alice/file.txt
rm ~/Bob/decrypt.txt ~/file_BobPubKey.bin ~/Alice/file.txt
How can we send large amounts of data using asymmetric encryption?
Asymmetric encryption makes key distribution easier, but can only send small amounts of data at a time, based on the key size being used. Symmetric encryption has a key distribution problem, but is able to send large amounts of data. Many cryptographic protocols combine the two mechanisms in order to send large amounts of data easily.
Alice is attempting to send a large file without worrying about distributing a symmetric key. As before, she generates the large file (
file.txt), a symmetric key (
sk.bin), and then encrypts the file with the symmetric key (~/
file_sk.bin) using AES in CBC mode. At this point, even though everyone can see the file, no one is able to decrypt it except Alice.
cd ~/Alice python3 -c 'print(512*"A")' > file.txt openssl rand 32 > sk.bin openssl enc -aes-256-cbc -in file.txt -out ~/file_sk.bin -pass file:sk.bin
Alice then takes the symmetric key and encrypts it with Bob's public key, generating the encrypted symmetric key (
openssl pkeyutl -encrypt -in sk.bin -pubin -inkey ~/BobPubKey.pem -out ~/sk_BobPubKey.bin
At this point, Bob is the only other person besides Alice who can decrypt the symmetric key and the original file.
To begin with, Bob takes the encrypted symmetric key (~/sk_BobPubKey.bin) and uses his private key (
BobPrivKey.pem) to decrypt the symmetric key (
cd ~/Bob openssl pkeyutl -decrypt -in ~/sk_BobPubKey.bin -inkey BobPrivKey.pem -out sk.bin
Now, using the decrypted symmetric key, Bob can now decrypt the encrypted file (
~/file_sk.bin) as before.
openssl enc -d -aes-256-cbc -in ~/file_sk.bin -out decrypt.txt -pass file:sk.bin diff decrypt.txt ~/Alice/file.txt
Once you've verified this, clean up.
rm decrypt.txt sk.bin ~/file_sk.bin ~/sk_BobPubKey.bin ~/Alice/file.txt ~/Alice/sk.bin
How does Bob know Alice sent this file? Unfortunately, he does not.