#include <stdio.h>

#define ROUNDS 8

unsigned feistel_f(unsigned R, unsigned K)
{
    unsigned output = 0x0000;
    output += R;
    output += K;
    //~ output ^= (output << 8);
    //~ output ^= (output >> 8);
    //~ output ^= R * K;
	return output;
}

void feistel_round(unsigned *L, unsigned *R, unsigned K)
{
	unsigned temp = * R;
	*R = *L ^ feistel_f(*R, K);
	*L = temp;
}

void feistel_encrypt(unsigned *L, unsigned *R, unsigned K[])
{
	int i;
	unsigned temp;
	for (i = 0; i < ROUNDS; i++) {
		feistel_round(L, R, K[i]);
	}
	temp = *R;
	*R = *L;
	*L = temp;
}

void feistel_decrypt(unsigned *L, unsigned *R, unsigned K[])
{
	int i;
	unsigned temp;
	for (i = ROUNDS-1; i >= 0; i--) {
		feistel_round(L, R, K[i]);
	}
	temp = *R;
	*R = *L;
	*L = temp;
}

int main(int argc, char * argv[])
{
	unsigned L = 0x12345678;
	unsigned R = 0x90ABCDEF;
	unsigned K[ROUNDS] = {
		0x11111111, 0x22222222, 0x33333333, 0x44444444,
		0x55555555, 0x66666666, 0x77777777, 0x88888888
	}; 

	printf("(0x%08X, 0x%08X)", L, R);
	feistel_encrypt(&L, &R, K);
	printf(" -> (0x%08X, 0x%08X)", L, R);
	feistel_decrypt(&L, &R, K);
	printf(" -> (0x%08X, 0x%08X)\n", L, R);

    L ^= 0x80000000;

	printf("(0x%08X, 0x%08X)", L, R);
	feistel_encrypt(&L, &R, K);
	printf(" -> (0x%08X, 0x%08X)", L, R);
	feistel_decrypt(&L, &R, K);
	printf(" -> (0x%08X, 0x%08X)\n", L, R);

	return 0;
}
