*****************************
** GECRYPT-0.2 FILE FORMAT **
*****************************
2007-07-29 Dwayne C. Litzenberger
** DEFINITIONS **
Let AES-CTR(K, N, M) represent the encryption (or decryption, which is
equivalent) of M using AES in counter mode using key K and nonce N.
Define the constants (represented as 128-bit big-endian integers):
FILE_ID = 0x616d1d67ca294e2eb98bc01ff0470100
HEADER_ID = 0x616d1d67ca294e2eb98bc01ff0470101
Let || represent the string concatenation operator.
Let S * N represent the string S repeated N times.
Let Len(X) represent the length (in octets) of X.
Let Int8(N) represent the unsigned 8-bit big-endian representation of N.
Let Int16(N) represent the unsigned 16-bit big-endian representation of N.
Let Int64(N) represent the unsigned 64-bit big-endian representation of N.
** HOW TO WRITE A GECRYPT-0.2 FILE **
1. Get from the user:
- The arbitrary-length master key K_M
- The plaintext message M
- The 16-bit iteration count c (must be >= 10. If the master key is a
passphrase, c should be at least 1000.)
- An optional, 64-bit padding size p. The default is 0 if none is
specified.
2. Randomly generate:
- 128-bit salt: S
- 64-bit nonces: N_H, N_P
- 128-, 192-, or 256-bit payload cipher key: K_P
3. Using the password-based key derivation function PBKDF2(P, S, c, dkLen) from
RSA PKCS#5 v2.0, compute the session key (using HMAC-SHA256 as the underlying
pseudorandom function):
K = PBKDF2(K_M, FILE_ID || S, c, 96)
4. Set the authentication key K_A to be the first 512 bits of the session key:
K_A = K<0..63>
5. Set the header cipher key K_H to be the last 256 bits of the session key:
K_H = K<64..95>
6. Generate the encrypted portion of the header:
C_H = AES-CTR(K_H, N_H, HEADER_ID || N_P || Int8(Len(K_P)) || K_P)
7. Generate the header:
HEADER = FILE_ID || S || N_H || Int16(c) || C_H
8. Split the plaintext into n chunks M_1, M_2, ... M_n such that the length
(in octets) of each chunk falls within the interval [1..2^16-1]. For each
chunk M_i:
Let L_i = Int16(Len(M_i))
9. Generate the payload:
PAYLOAD = L_1 || M_1 || L_2 || M_2 || ... || L_n || M_n || Int16(0)
10. Generate the padding:
PAD = Int8(0) * p ; zero repeated p times
PADDING = Int64(p) || PAD
11. Generate the ciphertext:
CIPHERTEXT = AES-CTR(K_P, N_P, PAYLOAD || PADDING)
12. Generate the 256-bit MAC:
MAC = HMAC-SHA256(K_A, HEADER || CIPHERTEXT)
13. Generate the final message:
MESSAGE = HEADER || CIPHERTEXT || MAC
14. Output MESSAGE.
** EOF **