// Arup Guha
// 11/19/2012
// Hash Function for CIS 3362 Homework #5: Crack the Password!

#include <stdio.h>
#include <string.h>

int hashFunction(char input[]);
int f(int value);
int reverse(int value);
int box(int value);
int box2(int value);
int f2(int value);

int main() {

    // To find the number to match, put your name in here, all lowercase, no spaces.
    // Please use the version of your name on webcourses, that I see. I'll publish
    // the numbers as soon as I get a chance, but this way you can get started earlier.
    printf("%d\n", hashFunction("arupguha"));
    return 0;
}

// Pre-condition: input must be null terminated.
int hashFunction(char input[]) {

    int i = 0, n = strlen(input);
    int buffer = 832671294;
    while (i < n) {
        int temp = 0, j;
        for (j=0; j<4 && i+j<n; j++)
            temp +=  ( (f((int)input[i+j])) << (24-8*j));
        i += 4;

        buffer = f2(buffer ^ temp);
    }
    return buffer;
}

// value must be 8 bits. Swaps the left and the right halves and runs
// each through an s-box.
int f(int value) {

    value = reverse(value);
    int left = (value & (0xf0)) >> 4;
    int right = value & (0xf);
    return (box(left) << 4) + box(right);
}

// value must be 8 bits. It's reverse (in binary) is returned.
int reverse(int value) {
    int ans = 0, i;
    for (i=0; i<8; i++) {
        ans = (ans << 1) + (value & 1);
        value = value >> 1;
    }
    return ans;
}

// Random s-box of values.
int box(int value) {
    int ans[] = {9, 4, 15, 0, 6, 7, 2, 11, 13, 12, 3, 8, 14, 1, 10 ,5};
    return ans[value];
}

// A second random s-box of values.
int box2(int value) {
    int ans[] = {13, 6, 2, 14, 7, 10, 4, 5, 0, 9, 12, 3, 15, 8, 11, 1};
    return ans[value];
}

// A second function based on the sbox. Value is once again reversed, with
// another substitution into a different sbox.
int f2(int value) {

    int i, ans = 0;
    for (i=0; i<8; i++) {
        int index = value & 0xf;
        if (index < 0) index += 16;
        ans = (ans << 4)  + box2(index);
        value = value >> 4;
    }
    return ans;
}
