#include #include int minBias = 0; int maxBias = 0; unsigned int plainText[20000]; unsigned int cipherText[20000]; unsigned short realKey; unsigned int _rotl(unsigned short value, int shift) { shift &= 7; return (value << shift) | (value >> (8 - shift)); } long power(int a, int x) { long r = 1; int c; for(c = 0; c < x; c++) r *= a; return r; } int grabBit(long input, int bit) { return ((input >> bit) & 1); } int setBit(int input, int bit) { return input + power(2, bit); } int sboxFunction(int k, int a) { int out = 0; return ((k + a) % 256); } int express[256][256]; void findExpressions() { int c = 0; int d = 0; int e = 0; int f = 0; int g = 0; for (c = 0; c < 256; c++) for (d = 0; d < 256; d++) express[c][d] = 0; for (c = 1; c < 256; c++) //Key Mask { for (d = 1; d < 256; d++) //Output Mask { for (e = 0; e < 256; e++) //Input { int inputXor = 0; for (f = 0; f < 8; f++) inputXor ^= grabBit(e, f); for (g = 0; g < 256; g++) //Key { int keyXor = 0; for (f = 0; f < 8; f++) if (grabBit(c, f)) keyXor ^= grabBit(g, f); int output = sboxFunction(g, e); int outputXor = 0; for (f = 0; f < 8; f++) if (grabBit(d, f)) outputXor ^= grabBit(output, f); if (outputXor == (keyXor ^ inputXor)) express[c][d]++; else express[c][d]--; } } } } } void findMinMaxBias() { minBias = 0; maxBias = 0; int c, d; for(c = 1; c < 256; c++) for(d = 1; d < 256; d++) { if (express[c][d] < minBias) minBias = express[c][d]; if (express[c][d] > maxBias) maxBias = express[c][d]; } } void showExpression(int x, int y) { int c, d; int first = 1; printf("%i ", express[x][y]); for(c = 0; c < 8; c++) if (grabBit(x, c)) { if (!first) printf(" + "); first = 0; printf("%i"); } printf(" = "); first = 1; for(c = 0; c< 8; c++) if (grabBit(y, c)) { if (!first) printf(" + "); first = 0; printf("%i"); } printf("\n"); } unsigned short getXorSum(int keyMask, unsigned short key) { unsigned short xorKey = 0; int c; for(c = 0; c < 8; c++) { if (grabBit(keyMask, c)) xorKey ^= grabBit(key, c); } return xorKey; } unsigned short splitLeft(unsigned int plain) { return plain / 256; } unsigned short splitRight(unsigned int plain) { return plain % 256; } unsigned int rc5Round(unsigned int plain, unsigned short key) { unsigned int cipher = 0; unsigned short left = splitLeft(plain); unsigned short right = splitRight(plain); left ^= right; left = _rotl(left, right); left = (left + key) % 256; unsigned short temp = left; left = right; right = temp; cipher = (left * 256) + right; return cipher; } void generateData(int num) { int c; realKey = rand() % 256; for(c = 0; c < num; c++) { plainText[c] = rand() % 65536; cipherText[c] = rc5Round(plainText[c], realKey); //printf("%i\n", plainText[c]); } } int findRightSide(int num) { int c; int totalOnes = 0; for(c = 0; c < num; c++) { if (getXorSum(255, splitRight(plainText[c])) ^ getXorSum(255, splitLeft(plainText[c])) ^ getXorSum(255, splitRight(cipherText[c]))) totalOnes++; } return totalOnes; } unsigned long realKeysChecked = 0; int keyFound = 0; void checkKeys(int a, short keyMask, int numPlain) { int c, d; int keysChecked = 0; for(c = 0; c < 256; c++) { if (getXorSum(keyMask, c) == a) { int crap = 0; for (d = 0; d < numPlain; d++) { if (rc5Round(plainText[d], c) != cipherText[d]) { crap = 1; break; } if (crap == 0) { /* printf("Key Found! %i\n", c); printf("Real key: %i\n", realKey); printf("Keys checked (real): %i\n", keysChecked); */ realKeysChecked += keysChecked; keyFound++; break; } } keysChecked++; } } //printf("Theoretical Keys Checked %i\n", keysChecked); } int main() { srand(time(NULL)); int c; for(c = 0; c < 10000; c++) { generateData(20); int a = findRightSide(20); //printf("Right Side Ones = %i\n", a); if (a > 10) a = 1; else a = 0; checkKeys(a, 255, 20); } printf("Total Keys Found = %i%%\n", keyFound/100); printf("Keys Checked Average when Found = %i/255\n", (realKeysChecked / keyFound)); /* findExpressions(); findMinMaxBias(); int c = 0; int d = 0; for(c = 0; c < 256; c++) for(d = 0; d < 256; d++) if ((express[c][d] == minBias) || (express[c][d] == maxBias)) showExpression(c, d); */ return 0; }