Computer System Security
Useful Functions from the dcrypt Library

Below is a description of some of the functions implemented in the dcrypt library that you may find useful in completing the lab assignments. You will need to include the dcrypt.h header file to access these functions. You may also want to take a look at these sample programs (tst.c, tst_sha1.c) to see some of these functions in action.

Data serialization

Pseudo-Random Number Generation Functions

The libraries you are using contain a cryptographic pseudo-random number generator, whose state is kept in a global 16-byte array called prng_state. Before using the random number generator, you must initialize it.

Symmetric-Key Encryption Functions

For actually encrypting and decrypting file data, you will use the Rijndael [FIPS-197] block cipher (also called AES---Advanced Encryption Standard). Rijndael is a 128-bit block cipher. It supports two operations--encryption, and decryption. Encryption transforms 16 bytes (128 bits) of plaintext data into 16 bytes of ciphertext data using a secret key. Someone who does not know the secret key cannot recover the plaintext from the ciphertext. The decryption algorithm, given knowledge of the secret key, transforms ciphertext into plaintext.

The libraries you are using define a struct called aes_ctx that you should use to hold secret keys for AES. You should manipulate your AES secret keys with the following functions:

Public-Key Encryption Functions

If you only used symmetric-key cryptography, you would need to exchange a secret key with all the friends with whom you want to have confidential communication. With Public-Key Cryptography, instead, you can give all your friend the same public key, and they will be able to send you encrypted content that only you can recover. Similarly, you only need to know your friend's public key to create a ciphertext that only he/she will be able to decrypt. The libraries you are going to use contain an implementation of two very well-known Public-Key Encryption schemes: Rabin [Wil80] and ElGamal [ElG86] To complete the assignment, you don't need to know anything about how these schemes work, except for the interface that they provide, which is described below:

Cryptographic Hash Functions

The SHA-1 [FIPS-180-1] hash function hashes an arbitrary-length input (up to 2^64 bytes) to a 20-byte output. SHA-1 is known as a cryptographic hash function. While nothing has been formally proven about the function, it is generally assumed that SHA-1 is one-way and collision-resistant. These properties are defined as follows:

The libraries you are using contain an implementation of SHA-1.

Sometimes the input that you want to hash is so long that it is inconvenient to store it entirely in memory before being able to hash it. This is the case for example when hashing the entire content of a file into a short digest.
For this reason, the libraries you are using allow you to process a long input "one chunk at a time." To do that, you should use a struct called sha1_ctx, which will store the "partial digest" as you keep providing new input to be hashed. You should manipulate sha1_ctx structs with the following functions:

Message Authentication Codes (MACs)

Message Authentication Codes (MACs) are a symmetric-key primitive allowing you to check the integrity of the information to which the MAC is applied. Recall that encryption does not guarantee integrity! The fact that you were able to decrypt a ciphertext is not enough to be sure that nobody tampered with its content. For integrity, you should always append a MAC to the content.

You use MACs as follows. Let's say that you want to store a file on your file-server, but you are afraid that its content will be changed behind your back. Then, you use a secret key to "mac" the file, and store the resulting MAC along with the file. Now, when you check back with your file-server and retrieve your file, you will also retrieve the MAC that you appended. Then, you will use the secret key to compute the MAC again, and if the MAC you just computed is the same as the value that you retrieved from the file-server, then you are sure that nobody touched your file. This is because, if somebody had changed the file, then they should have computed the corresponding MAC in order to fool you. However, secure MACs are concocted such that, without knowing the secret key, it is computationally intractable to compute the right MAC, even after having seen a lot of valid (message, MAC) pairs.

The Keyed-Hash Message Authentication Code (HMAC) [FIPS-198a] is a secure Message Authentication Code based on the use of any cryptographic hash function, like SHA-1. The libraries you are using contain an implementation of HMAC, instantiated with the SHA-1 cryptographic hash function.

Similarly to what discussed for the case of SHA-1, the libraries you are using allow you to process a long input "one chunk at a time."

References

[ElG85] T. ElGamal, A public key cryptosystem and a signature scheme based on discrete logarithms.
IEEE Transactions on Information Theory, Vol. IT-31, No. 4, pp. 469--472, July 1985.
[FIPS-180-1] FIPS-180-1, Secure Hash Standard.
U.S. Department of Commerce/N.I.S.T., 1994
[FIPS-197] FIPS-197, Announcing the Advanced Encryption Standard.
U.S. Department of Commerce/N.I.S.T., 2001
[FIPS-198a] FIPS-198a, The Keyed-Hash Message Authentication Code (HMAC).
U.S. Department of Commerce/N.I.S.T., 2002
[Wil80] H. C. Williams, A Modification of the RSA Public-Key Encryption Procedure.
IEEE Transactions on Information Theory, Vol. IT-26, No. 6, November 1980.