Introduction
In the world of cryptography, we often face a trade-off between speed and security. Symmetric encryption algorithms like AES are very fast and ideal for encrypting large amounts of data, but they require a shared secret key that must be securely distributed to both the sender and receiver. Asymmetric encryption algorithms like RSA are excellent for secure key exchange using a public/private key pair, but they are computationally intensive and too slow for encrypting bulk data.
Hybrid encryption solves this problem by combining the strengths of both methods. It uses the "best of both worlds" approach:
- Asymmetric encryption is used to securely encrypt and share a temporary, one-time symmetric key (often called a "session key").
- Symmetric encryption is then used with this session key to encrypt the actual, larger message data quickly and efficiently.
In this lab, you will implement a complete hybrid encryption scheme from scratch using the openssl command-line tool. You will generate an RSA key pair, create a random AES session key, use RSA to encrypt the session key, use AES to encrypt a message, and finally, reverse the process to decrypt the message.
Hybrid Encryption Overview
In this step, we will briefly review the core concepts that make hybrid encryption a powerful and widely used technique. There are no commands to execute in this step; the goal is to build a solid conceptual foundation before we begin the hands-on work.
Symmetric Encryption (e.g., AES)
- How it works: Uses a single, shared secret key for both encryption and decryption.
- Strength: Very fast and efficient, making it perfect for encrypting large files or data streams.
- Weakness: Key distribution. How do you get the shared secret key to the recipient securely? If an attacker intercepts the key, they can decrypt all communication.
Asymmetric Encryption (e.g., RSA)
- How it works: Uses a pair of keys: a public key for encryption and a private key for decryption. The public key can be shared freely, while the private key must be kept secret by its owner.
- Strength: Solves the key distribution problem. Anyone can use your public key to encrypt a message for you, but only you can decrypt it with your private key.
- Weakness: It is mathematically complex and therefore much slower than symmetric encryption. It is impractical for encrypting large amounts of data.
The Hybrid Solution
Hybrid encryption combines these two methods to get the security of asymmetric encryption and the speed of symmetric encryption. Here is the typical workflow:
- The sender (Alice) wants to send a secure message to the receiver (Bob).
- Alice generates a new, random symmetric session key.
- Alice encrypts her actual message using this fast symmetric session key.
- Alice gets Bob's public key. She uses it to encrypt only the small symmetric session key.
- Alice sends both the symmetrically-encrypted message and the asymmetrically-encrypted session key to Bob.
- Bob receives the two items. He first uses his private key to decrypt the encrypted session key.
- Now that Bob has the original symmetric session key, he uses it to quickly decrypt the actual message.
This process ensures that the bulk data is encrypted efficiently, and the key used for that encryption is exchanged with maximum security. In the following steps, we will implement this exact workflow.
Generate RSA and AES Keys
In this step, we will generate the two sets of keys required for our hybrid encryption scheme: an RSA key pair (public and private) for the asymmetric part, and a random session key for the symmetric part (AES). All operations will be performed in the ~/project directory.
First, let's generate a 2048-bit RSA private key. This key must be kept secret by the recipient.
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
You will see some output as the key is being generated. Next, we need to extract the corresponding public key from the private key we just created. This public key can be shared with anyone who wants to send you an encrypted message.
openssl rsa -pubout -in private_key.pem -out public_key.pem
The command will output writing RSA key.
Now, let's create a random 256-bit (32-byte) session key. This key will be used with the AES algorithm to encrypt our actual data. We use openssl rand to generate cryptographically strong random data and encode it in Base64 for easier handling.
openssl rand -base64 32 > session_key.key
Let's list the files in our directory to see the keys we've created.
ls -l
You should see the three key files you just generated, along with the message.txt file created during setup.
-rw-rw-r-- 1 labex labex 57 Oct 20 15:12 message.txt
-rw------- 1 labex labex 1704 Oct 20 15:14 private_key.pem
-rw-rw-r-- 1 labex labex 451 Oct 20 15:14 public_key.pem
-rw-rw-r-- 1 labex labex 45 Oct 20 15:14 session_key.key
Encrypt Session Key with RSA
In this step, we will perform a critical part of the hybrid encryption process: encrypting the symmetric session key. To ensure that only the intended recipient can use the session key, we will encrypt it using their RSA public key.
We will use the openssl pkeyutl command, which is a utility for public key operations. We'll use it to encrypt the session_key.key file with the public_key.pem.
Execute the following command:
openssl pkeyutl -encrypt -pubin -inkey public_key.pem -in session_key.key -out encrypted_session_key.bin
Let's break down this command:
pkeyutl: The public key utility tool.-encrypt: Specifies that we want to perform an encryption operation.-pubin: Indicates that the input key (-inkey) is a public key.-inkey public_key.pem: Specifies the public key to use for encryption.-in session_key.key: The input file to be encrypted (our AES session key).-out encrypted_session_key.bin: The output file where the encrypted key will be stored.
This command creates a new file, encrypted_session_key.bin, which contains the session key in an encrypted format. This file can now be transmitted securely, as only the owner of the corresponding private key can decrypt it.
Let's check for the newly created file:
ls -l encrypted_session_key.bin
You will see the binary file containing the encrypted key.
-rw-rw-r-- 1 labex labex 256 Oct 20 15:14 encrypted_session_key.bin
Encrypt Data with AES
Now that we have secured our session key, we can use the original, unencrypted session key to quickly encrypt our main data file, message.txt. We will use the AES-256-CBC symmetric cipher for this task.
The openssl enc command requires the key and Initialization Vector (IV) to be provided in hexadecimal format. Our session_key.key is in Base64, so we first need to decode it and convert it to hex. We will also generate a random IV. We'll store both in environment variables for convenience.
First, convert the session key and store it in the AES_KEY variable:
export AES_KEY=$(cat session_key.key | base64 -d | xxd -p -c 32)
Next, generate a 128-bit (16-byte) random IV and store it in the AES_IV variable. An IV is used to ensure that encrypting the same plaintext multiple times results in different ciphertexts.
export AES_IV=$(openssl rand -hex 16)
With the key and IV ready, we can now encrypt message.txt using openssl enc:
openssl enc -aes-256-cbc -in message.txt -out encrypted_message.dat -K $AES_KEY -iv $AES_IV
Let's review the command options:
-aes-256-cbc: Specifies the AES-256 cipher in CBC mode.-in message.txt: The input data file.-out encrypted_message.dat: The output file for the encrypted data.-K $AES_KEY: The encryption key in hex format (uppercase K).-iv $AES_IV: The initialization vector in hex format.
At this point, the sender would package encrypted_message.dat, encrypted_session_key.bin, and the IV ($AES_IV) to send to the recipient. For this lab, we have all the files in our directory, ready for the decryption step.
Let's verify that the encrypted data file was created:
ls -l encrypted_message.dat
-rw-rw-r-- 1 labex labex 64 Oct 20 15:14 encrypted_message.dat
Decrypt Message
In this final step, we will simulate the actions of the recipient. The recipient has received the encrypted data (encrypted_message.dat), the encrypted session key (encrypted_session_key.bin), and the IV. They will use their secret private key to reverse the process and retrieve the original message.
First, the recipient must decrypt the session key using their private_key.pem.
openssl pkeyutl -decrypt -inkey private_key.pem -in encrypted_session_key.bin -out decrypted_session_key.key
This command uses pkeyutl with the -decrypt flag and the private key to recover the original AES session key, saving it to decrypted_session_key.key.
We can quickly verify that the decrypted key is identical to the original one we created in Step 2. The diff command should produce no output if the files are the same.
diff session_key.key decrypted_session_key.key
Now that we have the session key, we can decrypt the main message. Just like in the encryption step, we need to convert the key to hex format first.
export DECRYPTED_AES_KEY=$(cat decrypted_session_key.key | base64 -d | xxd -p -c 32)
Finally, use openssl enc with the -d (decrypt) flag, providing the same key and IV that were used for encryption. (The $AES_IV variable is still set in our shell from the previous step).
openssl enc -d -aes-256-cbc -in encrypted_message.dat -out decrypted_message.txt -K $DECRYPTED_AES_KEY -iv $AES_IV
The process is complete! The original message has been recovered and saved to decrypted_message.txt. Let's view its contents to confirm our success.
cat decrypted_message.txt
You should see the original secret message printed to your terminal:
This is a secret message that needs to be sent securely.
Summary
In this lab, you successfully implemented a complete hybrid encryption and decryption workflow using OpenSSL. You have gained hands-on experience with the fundamental concepts that secure much of our digital communication.
You learned how to:
- Generate an RSA key pair for asymmetric encryption.
- Create a random AES session key for symmetric encryption.
- Securely encrypt the session key using the RSA public key.
- Efficiently encrypt bulk data using the AES session key.
- Reverse the process by decrypting the session key with the RSA private key and then decrypting the data.
This "best of both worlds" approach, which combines the security of asymmetric cryptography for key exchange with the speed of symmetric cryptography for data encryption, is a cornerstone of modern security protocols like TLS/SSL that protect your data on the internet every day.



