C1. AES & PBKDF2 in Python (40 pts.)

What you need:

Purpose

Practice encrypting and decrypting using AES with Python. We will use only the most common form: AES-128.

1. "Textbook AES" -- Simplest Method

How AES Works

As shown below, AES has uses three values:

Block Cipher Mode of Operation

First, we'll use the less secure Electronic Code Book (ECB) mode, as shown below. In this mode, each block of plaintext is processed independently.

Example Using an Online Tool

Using a simple online tool, here's an example of AES encryption. The plaintext and key are 16 ASCII bytes, and the ciphertext is 16 bytes in hexadecimal.
PlaintextSECRET MESSAGE!!
KeySECRET KEY 128 B
Ciphertext0f 7b c9 6e 06 c0 87 3f 15 8e 08 5c e3 81 6d bb

Example in Python

It's very easy, because someone else has already written a handy AES library for us to use.

After importing the library, we assign values to plaintext and key and declare a new AES object. The AES object has an encrypt method that gives the same result as the online encryptor, as shown below.

from Crypto.Cipher import AES
plaintext = "SECRET MESSAGE!!"
key = "SECRET KEY 128 B"
cipher = AES.new(key, AES.MODE_ECB)
cipher.encrypt(plaintext).encode("hex")

Longer Input

Next, use the same key and mode on this plaintext:
SECRET MESSAGE!!SECRET MESSAGE!!SECRET MESSAGE!!
reveals a major weakness in ECB: the output contains three repeating blocks of 128 bits.
Changing the window width makes the repetitions easier to see.

2. CBC Mode: Removing Patterns

Cipher Block Chaining (CBC)

This method was invented in 1976 to remove the repeating blocks from ECB mode. Two new features are added:

Example Using an Online Tool

Using these values:
PlaintextSECRET MESSAGE!!
KeySECRET KEY 128 B
IV00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
The ciphertext begins with ae e2 4e as shown below.

Example in Python

All we need to do is change the mode and add the iv variable.
from Crypto.Cipher import AES
plaintext = "SECRET MESSAGE!!"
key = "SECRET KEY 128 B"
iv = "00112233445566778899aabbccddeeff".decode("hex")
cipher = AES.new(key, AES.MODE_CBC, iv)
cipher.encrypt(plaintext).encode("hex")
The ciphertext matches the value from the online tool, as shown below.

Longer Input

Use the same key, iv, and mode on this plaintext:
SECRET MESSAGE!!SECRET MESSAGE!!SECRET MESSAGE!!
The ciphertext no longer repeats, as shown below.

3. Padding: Handling Arbitrary Plaintext Lengths

PKCS7

If the plaintext in the last block of input is shorter than 16 bytes, it must be padded before it can be encrypted by AES.

One common method is PKCS7, in which the padding is always one of these 15 byte-strings, chosen to make the total length 16 bytes.

01
02 02
03 03 03
04 04 04 04
05 05 05 05 05
06 06 06 06 06 06
07 07 07 07 07 07 07
08 08 08 08 08 08 08 08
09 09 09 09 09 09 09 09 09 
0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 
0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 
0c 0c 0c 0c 0c 0c 0c 0c 0c 0c 0c 0c 
0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d
0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 
0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 

Example

Here's HELLO encrypted with PKCS7 padding.
from Crypto.Cipher import AES
plaintext = "HELLO" + 11 * "0b".decode("hex")
key = "SECRET KEY 128 B"
iv = "00112233445566778899aabbccddeeff".decode("hex")
cipher = AES.new(key, AES.MODE_CBC, iv)
cipher.encrypt(plaintext).encode("hex")

4. Key Derivation from a Password

PBKDF2 (Password-Based Key Derivation Function 2)

Users don't want to remember 128-bit keys and type them in. They prefer passwords. So we need a way to convert a password of any length to a key of the correct length for the encryption method.

Even if two users have the same password, they shouldn't have identical keys, so a salt value is used to make each calculation different.

The PBKDF2 algorithm uses a password, a salt, and cryptographic algorithms to create a long series of pseudorandom bytes. You can read as many bytes as you want to form a key.

This code creates a 16-byte key from a password of Password123 and a salt of RANDOM STUFF

from pbkdf2 import PBKDF2
password = "Password123"
salt = "RANDOM STUFF"
PBKDF2(password, salt).read(16).encode("hex")
This site lets you calculate simple versions of PBKDF2 online. As you can see, it has the same result for the key.
To learn a bit more about PBKDF2, execute this command at the >>> prompt:
help(PBKDF2)
When we initialize an object of type PBKDF2, the __init__ function is called. I did this on a Mac; the details of the modules shown may be different on your system.
As shown above, the __init__ function requires the caller to specify the passphrase and salt parameters, and has these default values for the other parameters:
iterations 1000
digestmodule SHA (That is, SHA-1)
macmodule HMAC
This is the first example algorithm specified in Appendix B.1.1 of RFC 2898: PKCS #5: Password-Based Cryptography Specification Version 2.0. It's called HMAC-SHA-1.

Challenge C1-1: Encrypt the Message (5 pts)

Encrypt this cleartext using AES-ECB:
SAFE AND SECURE!
Use the default PBKDF2 with no salt and a password of
123
Use the form below to get your points.
Your Name:
Ciphertext like this:
     0f7bc96e06c0873f158e085ce3816dbb

Challenge C1-2: Decrypt the Message (10 pts)

Decrypt this AES-ECB-encrypted ciphertext:
4e45e079c9c5b019d1ee66dde12db4fd8c05933ec3d01cc9df050e3791fe9cb0
The key was formed using the same one-digit PIN for both the salt and the passphrase, and default values for the other options.

Use the form below to get your points.

Your Name:
Cleartext like this:
     SAFE AND SECURE!

Challenge C1-3: Decrypt the Message (25 pts)

Decrypt this AES-CBC-encrypted ciphertext:
4a3b101904aff330dcfdca5e7548f202f7273de7d35f7f0a51964f67d666b16167c2896095b001643cd9830a2c8e2a41
The passphrase and the salt are two-digit numbers. The iv contains 128 bits, all zero.

Use the form below to get your points.

Your Name:
Cleartext like this:
     SAFE AND SECURE!

References

Rindjael Flash Animation (SWF File)
Block cipher mode of operation - Wikipedia
Padding - Wikipedia
dlitz/python-pbkdf2: Python PKCS#5 v2.0 PBKDF2 Module
Hash-based message authentication code - Wikipedia


Last modified 7-24-17