No. 04 — Lab 02
Bob to Amaka
sealed
Bob encrypts the 300-word message from Lab 01 so only Amaka can read it. Then one bit is flipped on the way. Every command below was run for real, and the output is exactly what OpenSSL printed.
01 — Setup
Two key pairs
Amaka and Bob each make an RSA key pair and swap public keys. A private key never leaves its owner. These are demo keys made for this page and not published.
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out amaka_private.pem
openssl pkey -in amaka_private.pem -pubout -out amaka_public.pem
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out bob_private.pem
openssl pkey -in bob_private.pem -pubout -out bob_public.pem
02 — Bob sends
Encrypt and sign
RSA is too slow and too small for 300 words, so Bob uses the standard hybrid pattern. A random AES-256 session key encrypts the message, and Amaka's public key encrypts the session key. He also signs the message with his private key.
openssl rand -hex -out session.key 32
openssl enc -aes-256-cbc -pbkdf2 -salt -in bob-original.txt -out message.enc -pass file:session.key
openssl pkeyutl -encrypt -pubin -inkey amaka_public.pem -pkeyopt rsa_padding_mode:oaep -in session.key -out session.key.enc
openssl dgst -sha256 -sign bob_private.pem -out message.sig bob-original.txt
wc -c bob-original.txt message.enc session.key.enc message.sig
1639 bob-original.txt 1664 message.enc 384 session.key.enc 384 message.sig 4071 total
od -An -tx1 -N32 message.enc
53 61 6c 74 65 64 5f 5f be 55 b8 0b c9 2b e2 74 e7 47 d8 dd ec fb 6f 39 3a 62 75 18 2c b8 8c 06
03 — Amaka receives
Decrypt and verify
Amaka unlocks the session key with her private key, decrypts the message, checks Bob's signature, and compares hashes with the original.
openssl pkeyutl -decrypt -inkey amaka_private.pem -pkeyopt rsa_padding_mode:oaep -in session.key.enc -out session.key.recovered
openssl enc -d -aes-256-cbc -pbkdf2 -in message.enc -out message.recovered.txt -pass file:session.key.recovered
openssl dgst -sha256 -verify bob_public.pem -signature message.sig message.recovered.txt
Verified OK
sha256sum bob-original.txt message.recovered.txt
ebd64f158907aaf282b37b1d615f438049f0453828662ab1b48f52e8b70e2d70 bob-original.txt ebd64f158907aaf282b37b1d615f438049f0453828662ab1b48f52e8b70e2d70 message.recovered.txt
04 — Disruption
One bit flipped in transit
Now damage the encrypted message on its way: flip a single bit. Amaka decrypts it exactly as before.
python -c "d=bytearray(open('message.enc','rb').read()); d[100]^=1; open('message.damaged.enc','wb').write(d)"openssl enc -d -aes-256-cbc -pbkdf2 -in message.damaged.enc -out message.damaged.txt -pass file:session.key.recovered
sha256sum message.enc message.damaged.enc
8f8f820d915a0a4cb0bbd6907159db46fa8882e4a28ab6f288a6bd742609e3aa message.enc d13c0880373063855319a572b51666b405dfa55c901c63dfb48062352c442dc4 message.damaged.enc
sha256sum bob-original.txt message.damaged.txt
ebd64f158907aaf282b37b1d615f438049f0453828662ab1b48f52e8b70e2d70 bob-original.txt 6804290c11beb6dd20c6a494f78c5d478aaca6ee1d89e9ae344031074c28d72b message.damaged.txt
cmp -l bob-original.txt message.damaged.txt | wc -l
17
openssl dgst -sha256 -verify bob_public.pem -signature message.sig message.damaged.txt
Verification failure
05 — Result
Encryption is not integrity
Confidentiality worked. The ciphertext starts with the bytes 53 61 6c 74 65 64 5f 5f, which spell "Salted__", followed by random-looking data. Without Amaka's private key nobody can recover the session key.
Integrity failed silently. After one flipped bit, decryption finished with no error, but 17 bytes were wrong and the SHA-256 hash had nothing in common with the original, the same avalanche effect as Lab 01. AES-CBC garbles the block that was hit and flips one bit in the next, and it never complains.
The signature caught it. Bob's signature verified on the good copy and failed on the damaged one. That is why real systems use authenticated encryption such as AES-GCM or ChaCha20-Poly1305, or sign what they send.
06 — Run it yourself
Same commands, your machine
Run the commands in order in Git Bash, WSL or Linux (Git for Windows includes OpenSSL). Use python3 instead of python on Linux and macOS. Start from bob-original.txt.
Never publish a key. Anything ending in _private.pem or session.key must stay off GitHub. Add *.pem and session.key* to your .gitignore.