/******************************************************** * Programmed by: John Law * * Date: July 12th 2012 * * Purpose: Implementation of blowfish encryption * ********************************************************/ #include #include #include #include "blowfish_consts.c" #include using namespace std; unsigned long long getNextBlock (int startingLocation, int blockSize, char source[]); unsigned long long blowfishEncrypt (unsigned long long block, unsigned long *p, unsigned long *s0, unsigned long *s1, unsigned long *s2, unsigned long *s3, int reverse); unsigned long long generateSubkeys(unsigned long *subkey, int sizeOfArray, unsigned long long zeroString, unsigned long *p, unsigned long *s0, unsigned long *s1, unsigned long *s2, unsigned long *s3); int main (int argc, char *argv[]) { if (argc < 2) { cout << "Encryption key not provided. Please provide 16 hex characters as command argument." << endl; return (0); } //Get plaintext message char plaintextMessage[1000]; cout << "Your message in plaintext: "; fgets(plaintextMessage, 1000, stdin); //remove the newlines int m = 0; for (m = 0; m < strlen(plaintextMessage); m++) { if ( plaintextMessage[m] == '\n' ) { plaintextMessage[m] = '\0'; } } //Split key into two 32 bit pieces unsigned long long fullKey = getNextBlock(0, 8, argv[1]); unsigned long keyLeft = fullKey >> 32; unsigned long keyRight = fullKey & 0xFFFFFFFF; //initialize P int i = 0; for (i = 0; i < sizeof(parray)/sizeof(unsigned long); i++) { if ( i % 2 == 0 ) { parray[i] = parray[i] ^ keyRight; } else { parray[i] = parray[i] ^ keyLeft; } } //Generate the subkeys unsigned long long zeroString = 0; zeroString = generateSubkeys(parray, sizeof(parray)/sizeof(unsigned long), zeroString, parray, sbox0, sbox1, sbox2, sbox3); zeroString = generateSubkeys(sbox0, sizeof(sbox0)/sizeof(unsigned long), zeroString, parray, sbox0, sbox1, sbox2, sbox3); zeroString = generateSubkeys(sbox1, sizeof(sbox1)/sizeof(unsigned long), zeroString, parray, sbox0, sbox1, sbox2, sbox3); zeroString = generateSubkeys(sbox2, sizeof(sbox2)/sizeof(unsigned long), zeroString, parray, sbox0, sbox1, sbox2, sbox3); zeroString = generateSubkeys(sbox3, sizeof(sbox3)/sizeof(unsigned long), zeroString, parray, sbox0, sbox1, sbox2, sbox3); //Loop through each block in the message, encrypting and ouputing result to screen cout << endl << "Encrypted blocks: " << endl; int numOfBlocks = strlen(plaintextMessage) / 8 + 1; if (strlen(plaintextMessage) % 8 == 0) { numOfBlocks = strlen(plaintextMessage) / 8; } int location = 0; for (i = 0; i < numOfBlocks; i++) { cout << "Original block: " << hex << getNextBlock(location, 8, plaintextMessage) << " Encrypted block: "; unsigned long long encryptedBlock = blowfishEncrypt(getNextBlock(location, 8, plaintextMessage), parray, sbox0, sbox1, sbox2, sbox3, 0); cout << encryptedBlock << endl; location = location + 8; } return (0); } unsigned long long generateSubkeys(unsigned long *subkey, int sizeOfArray, unsigned long long zeroString, unsigned long *p, unsigned long *s0, unsigned long *s1, unsigned long *s2, unsigned long *s3) { int i = 0; for (i = 0; i < sizeOfArray; i++) { zeroString = blowfishEncrypt(zeroString, p, s0, s1, s2, s3, 0); subkey[i] = zeroString; subkey[i++] = zeroString; } return zeroString; } unsigned long long blowfishEncrypt (unsigned long long block, unsigned long *p, unsigned long *s0, unsigned long *s1, unsigned long *s2, unsigned long *s3, int reverse) { unsigned long long encryptedBlock = 0; //Split 64 bit block into two 32 bit pieces unsigned long leftPiece = block >> 32; unsigned long swap = 0; unsigned long rightPiece = block & 0xFFFFFFFF; int start = 0, end = 16; if (reverse == 1) { start = 18; end = 0; } //Blowfish encryption rounds int i = 0; int a = 0, b = 0, c = 0, d = 0; //Decryption if (reverse == 1) { for (i = start; i > end; i--) { leftPiece = leftPiece ^ p[i]; //split leftPiece into four bytes to feed its encryption function d = leftPiece & 0xFF; c = (leftPiece >> 8) & 0xFF; b = (leftPiece >> 16) & 0xFF; a = leftPiece >> 24; rightPiece = ((s0[a] + s1[b] % 2^32) ^ (s2[c] + s3[d] % 2^32)) ^ rightPiece; swap = leftPiece; leftPiece = rightPiece; rightPiece = swap; } swap = leftPiece; leftPiece = rightPiece; rightPiece = swap; rightPiece = rightPiece ^ p[1]; leftPiece = leftPiece ^ p[0]; } //Encryption else { for (i = start; i < end; i++) { leftPiece = leftPiece ^ p[i]; //split leftPiece into four bytes to feed its encryption function d = leftPiece & 0xFF; c = (leftPiece >> 8) & 0xFF; b = (leftPiece >> 16) & 0xFF; a = leftPiece >> 24; rightPiece = ((s0[a] + s1[b] % 2^32) ^ (s2[c] + s3[d] % 2^32)) ^ rightPiece; swap = leftPiece; leftPiece = rightPiece; rightPiece = swap; } swap = leftPiece; leftPiece = rightPiece; rightPiece = swap; rightPiece = rightPiece ^ p[16]; leftPiece = leftPiece ^ p[17]; } //recombine the two 32 bit pieces encryptedBlock = (unsigned long long)leftPiece << 32 | rightPiece; return encryptedBlock; } unsigned long long getNextBlock (int startingLocation, int blockSize, char source[]) { int i = 0; unsigned long long block = 0; for (i = 0; i < blockSize; i++) { block <<= blockSize; block |= (startingLocation < strlen (source) ? source[startingLocation++] : '\0'); } return block; }