Lab - Symmetric Cryptography

Authors: João Paulo Barraca, Vitor Cunha, Paulo C. Bartolomeu, Alfredo Matos, Catarina Silva

Slides

Download here

Support File Required: symmetric_cryptography_c.zip

Symmetric Cryptography

Cipher Modes

Your task is to implement two modes of operation for the AES128 block cipher: the Electronic Codebook (ECB) mode and the Cipher Block Chaining (CBC) mode.

  • AES128 Implementation: You should use an implementation of AES128 block cipher. Remember that AES128 operates on 16-byte blocks and uses a key of 16 bytes.

  • ECB Mode: In ECB mode, each block of plaintext is encrypted separately. This means that if two identical blocks of plaintext are encrypted with the same key, they will produce identical blocks of ciphertext.

  • CBC Mode: In CBC mode, each block of plaintext is XORed with the previous ciphertext block before being encrypted. This means that each ciphertext block depends on all plaintext blocks processed up to that point. To make each message unique, an initialization vector must be used in the first block.

  • Validation: After implementing ECB, and CBC, validate your implementation against the test vectors provided in file aes128-test-vectors.txt. Your implementation should produce the same output as the test vectors for the same input. Start by encrypting the PLAINTEXT and compare the result with the CIPHERTEXT, then decrypt the result and compare it with PLAINTEXT. Note that the values in the file are in hexadecimal.

You can either use as a starting point the aes128-test-modes.c or produce your own code. Along with aes128-test-modes.c there is an implementation of AES128 built on top of Intel AES instruction set (in aes.h) and another one built on top of openssl (in aes-sw.h). Inspect both files.

NOTE : If your cpu do not support the Intel AES instruction set, you need to do 2 things: 1) change the include on aes128-test-modes.c; 2) remove -msse2 -msse -maes from file cflags.txt.

You can check the availability of Intel AES instruction set with the command:

$ grep -c aes /proc/cpuinfo # if it prints some number greater than 0 the AES instruction set is available

If you want to use python you need to install Python3 Cryptography module. The module can be installed using:

$ sudo apt update
$ sudo apt install python3-cryptography

Or

$ pip install cryptography

If you want to use c you need to install some tools to compile the code:

$ sudo apt update
$ sudo apt install build-essential libssl-dev libbsd-dev

Then you can execute:

$ gcc aes128-test-modes.c -o ase128-test-modes $(cat cflags.txt)  # remember you need to run this every time you change the code.

Additional resources:

Padding

A block cipher requires input blocks of a fixed size that equals the algorithm block size. However, its improbable that a file to encrypt as a number of bytes that is multiple of the block size of the algorithm to be used, i.e., frequently, the number of bytes that remain for the last block do not equals the block size. To solve this problem, extra bytes are added to have a block with the correct size. These extra bytes are then removed when in the decryption operation.

There are several standards for padding. PKCS#7 is one of them. The objective for this exercise is that you demonstrate the existence of padding in a encryption operation, and that it is according the PKCS#7 standard.

Your task is to implement two functions: one for adding padding to a given plaintext according to the PKCS#7 standard, and another for removing the padding from a given ciphertext.

  • Add Padding: Write a function that adds padding to an arbitrary plaintext in order to make it a valid input for the encrypt operation.

  • Remove Padding: Write a function that removes the padding of the result of a decrypt operation. The function should verify that the padding is correct.

  • Validation: Validate your implementation against the tests provided in file aes128-test-padding.txt.

Note: Take special care when the size of the input data is a multiple of the block size. In such cases, PKCS#7 padding requires that a full block of padding be added. This is to ensure that the padding can always be unambiguously removed.

You can either use as a starting point the aes128-test-padding.c or produce your own code.

Symmetric key generation

Before a cipher is used, it is required the generation of proper arguments. These arguments are the key, the cipher mode, and potentially the IV. The cipher mode is chosen at design time, and the IV should always be a large random number (size similar to the block size or key) that is never repeated. In the previous examples we have been using known keys and IVs in order to validate the implementations. This lab will discuss the creation of random keys and IVs.

The key can be obtained from good sources of random numbers, or generated from other primitive material such as a password. When choosing the a password, it is imperative to transform the user text into a key of the correct complexity. While there are many methods, we will consider the Password Based Key Derivation Function 2 (PBKDF2), which takes a key, a random value named salt, a digest algorithm, and a number of iterations (you should use several thousands). The algorithm will iterate the digest algorithm in a chain starting in the concatenation of the salt and key, for the specified number of iterations. Using SHA2, the result is at least 256 bit, which can be used as key and IV, two values of 128 bit.

Your task is to enable the user to provide a password that will be used to generate random values for keys and IVs.

  • Construct a function that generates 256bits according to PBKDF2-HMAC-SHA256, i.e. with SHA256 as digest function used in the derivation (done in pbkdf2-kickoff.c).
  • Use these 256bit as two values of 128bit, the key and IV, and integrate this change with the previous cipher modes.

You can either use as a starting point the pbkdf2-kickoff.c or produce your own code. If you prefer to use Python3, to provide the password check the getpass module.

To compile pbkdf2-kickoff.c use:

gcc pbkdf2-kickoff.c -o pbkdf2-kickoff $(cat cflags.txt)

Note Try different number of iterations and measure this impact.

File encryption

Create a function to encrypt the contents of a file, whose name should be provided by the user. The key should be generated according to the previous task. The user must provide (as program parameters or by request or any other suitable method): (i) the name of the file to encrypt, (ii) the name of the file to store the cryptogram, (iii) the mode of the encryption algorithm, according to the previous tasks.

If you need to save multiple fields to the same file (e.g, salt, cryptogram), save these as fixed length fields to the beginning of the file (see pbkdf2-kickoff.c). An alternative is to use Base64 to convert the objects to text (base64), and then use a delimited such as \n.

Take in consideration that data may need to be encrypted in blocks, and the last block may require padding, according to the previous tasks.

Questions:

  • Can you determine the structure of the text from the cryptogram?
  • Compare the lengths of the text and the cryptogram?

File decryption

Alter your program by adding a function that decrypts a user file. For this functionality, the user must provide the following (as program parameters or by request or any other suitable method): (i) the name of the file to decrypt, (ii) the name of the file to store the decryption result. The key must be requested.

Take care of removing the padding (if present!)

Questions:

  • Is padding visible in the decrypted text?
  • What happens if the cryptogram is truncated?
  • What happens if the cryptogram lacks some bytes in the beginning?

Patterns

In this exercise we will analyze the impact of ECB and CBC cipher modes in the reproduction of patterns in the original document into the encrypted document. For this, we are going to encrypt an image in the bit map (BMP) file format, after which we are going to visualize the contents of the obtained encrypted file and compare it with the original image. In order we can visualize the contents of the encrypted file we must replace the first 54 bytes with the first 54 bytes from the original file (these bytes constitute the header of BMP formatted files, which is necessary so the file can be recognized as a BMP formatted file).

Use the program you developed in the previous sections to encrypt the file Tux.bmp using the ECB cipher mode. Using the dd application copy the copy the first 54 bytes from the original image file into the first 54 bytes of the encrypted file:

dd if=Tux.bmp of=Tux_enc.bmp ibs=1 count=54 conv=notrunc

Using a program to visualize images, open the original image and the encrypted image and compare them. What do you observe?

Repeat all the above operations, now using the CBC cipher mode instead of ECB cipher mode. Then, compare the original image with the obtained encrypted image.

Original Tux(credits to Wikimedia)
ECB Tux(credits to Wikimedia)
CBC Tux(credits to Wikimedia)

An image and the typical result result of ECB and CBC cipher mode.

(Images by Larry Ewing)

(OPTIONAL) Human Readable Symmetric Encryption

Modern ciphers lies in their indistinguishability from random data by a computationally limited adversary. In the previous exercises we used symmetric cryptography to produce indistinguishable results. In this exercise, we want to use ciphers to produce a human “readable” text.

Write a program using AES encryption, for example with CTR mode, and replace encrypted bytes with words from a dictionary ensuring that your code encrypts and decrypts the input text while maintaining the human “readable” format of the cipher text.

NOTE: you can use markov-word-generator Python library to generate random credible words.

Experiment with different dictionaries and input strings to observe the effects on the cipher text.

Previous
Next