// Arup Guha
// 9/23/2024
// Examples of using some bitwise operators.

#include <stdio.h>
#include <stdlib.h>

int* xorwithkey(int* plain, int length, int key);
int xordigest(int* plain, int length);

int main() {

    int bits[] = {35, 82, 99, 13, 45};
    int mykey = 77;

    // Just XOR each "byte" with the key.
    int* mycipher = xorwithkey(bits, 5, mykey);

    // Print result.
    for (int i=0; i<5; i++)
        printf("%d ", mycipher[i]);
    printf("\n");
    free(mycipher);

    // This calculates the xor digest of all the bytes here as described in the function below.
    int code = xordigest(bits, 5);
    printf("code is %d\n", code);

    return 0;
}

// XORs each element of plain with key, stores the result in a new array and returns that.
int* xorwithkey(int* plain, int length, int key) {

    // Allocate space, XOR each item as mentioned.
    int* cipher = malloc(sizeof(int)*length);
    for (int i=0; i<length; i++)
        cipher[i] = (plain[i]^key);

    // Return the new array.
    return cipher;
}

// This will split up each element in plain into blocks of 4 bits each and XOR all these blocks
// together, returning the answer (should be in between 0 and 15, inclusive.)
int xordigest(int* plain, int length) {

    int answer = 0;

    // This number has 1s in the last four slots.
    int mask = (1<<4)-1;

    // Go through each integer.
    for (int i=0; i<length; i++) {

        // So I don't change plain.
        int block = plain[i];

        // Go through each block.
        for (int j=0; j<8; j++) {

            // Isolate the last four bits of block.
            int term = (block & mask);

            // XOR this into my buffer.
            answer = (answer ^ term);

            // Shift the block over by 4 so the next 4 bits are in place.
            block = (block >> 4);
        }
    }

    // This is the bitwise XOR of all the items split into blocks of 4 bits.
    return answer;
}
