/*****
aes_streamtest.c
Zworld, 2001

stream test

tests out CFB(cipher feedback) stream encryption

encrypts and decrpyts a test string '0123456789'
and prints the decrypted result, which should be
the original string.
Uses MD5 to hash a pass phrase into a 128-bit key.

Cipher feedback encryption is a method for using a block cipher like Rijndael
to encrypt a stream of characters. It does this by maintaining a feedback
register which is the same size as the cipher block size. The feedback
register is loaded with a known initial set of data (the init vector) and
then encrypted. Each byte in the feedback register is XORed with a plain text
byte to produce the cipher text. When a feedback byte is used it is shifted
out of the feedback register and the new ciphertext byte is shifted in.
Each time a full block of new ciphertext has been shifted in to the
feedback register, it is encrypted again. This scheme allows any number
of bytes to be encrypted when needed. Since XORing the ciphertext with
matching bytes from the feedback register will recover the plaintext,
decryption is a similar process, where the decrypter's feedback register
is kept synchonized with the encrypter. For a more complete explanation
of this see 'Applied Crytography, 2nd Edition' by Bruce Schneier, pg 200.

The Rabbit implementation of cipher feedback mode uses an AESstreamState
structure to hold the state of the feedback register. As the sample below
indicates, seperate states must be used for encrypting and decrypting.


****/

#use "aes_crypt.lib"
#use "md5.lib"

const char passphrase[] = "lampshade quarter 23";

main()
{
	static char key[16];
	static char init_vector[16];
	static AESstreamState encrypt_state;
	static AESstreamState decrypt_state;
	static md5_state_t md5_state;
	static char data[11];
	static int i;
	
	//initialize data
	for(i = 0;i < 10;i++)
	{
		data[i] = '0' + i;
	}
	data[10] = 0; //Null terminator for printing

	//init vector
	for(i = 0;i < 16;i++)
	{
		init_vector[i] = 0;
	}

	//hash phrase into key
	md5_init(&md5_state);
	md5_append(&md5_state, passphrase, strlen(passphrase));
	md5_finish(&md5_state, key);	//turns passphrase into 128-bit key

	//need seperate stream states for encryption and decryption
	AESinitStream(&encrypt_state, key, init_vector);
	AESinitStream(&decrypt_state, key, init_vector);

	while(1)
	{
		//encrypts data in place
		AESencryptStream(&encrypt_state, data, 10);
		//decrypts data in place
		AESdecryptStream(&decrypt_state, data, 10);
		printf("%s\n", data);
	}
}
	
	