// Arup Guha
// 11/19/2012
// edited on 11/20/2015 for 2015 version of the homework
// Hash Function for CIS 3362 Homework #5: Crack the Password!

#include <stdio.h>
#include <string.h>

long long hashFunction(char input[]);
int f(int value);
int reverse(int value);
int box(int value);
int box2(int value);
long long f2(long long value);

int main() {

    // This is the message referred to in Part B of the assignment.
    printf("%lld\n", hashFunction("I have the goods. Meet me in 1 hr, by the blue dumpster by the loading docks."));
    printf("%lld\n", hashFunction("there is naother day"));
    printf("%lld\n", hashFunction("come on!"));
    printf("%lld\n", hashFunction("come on?"));
    printf("%lld\n", hashFunction("c"));
    return 0;
}

// Pre-condition: input must be null terminated.
long long hashFunction(char input[]) {

    int i = 0, n = strlen(input);
    long long buffer = 0x3f290785c16eLL;
    while (i < n) {
        long long temp = 0;
        int j;
        for (j=0; j<6 && i+j<n; j++)
            temp += ( ( (long long)(f((int)input[i+j])) ) << (40-8*j)  );
        i += 6;

        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[] = {10, 8, 12, 9, 4, 15, 0, 6, 7, 2, 11, 13, 3, 14, 1, 5};
    return ans[value];
}

// A second random s-box of values.
int box2(int value) {
    return (37*value)%64;
}

// A second function based on the sbox. Value is once again reversed, with
// another substitution into a different sbox.
long long f2(long long value) {

    int i;
    long long ans = 0;
    for (i=0; i<8; i++) {
        int index = value & 0x3f;
        if (index < 0) index += 64;
        ans = (ans << 6)  + box2(index);
        value = value >> 6;
    }
    return ans;
}
