void encrypt(WORD *plainTxt, WORD *cipherTxt) { WORD A = plainTxt[0] + S[0]; WORD B = plainTxt[1] + S[1]; int i; for (i = 1; i <= r; i++) { A = ROTATE_L(A^B, B) + S[2*i]; B = ROTATE_L(B^A, A) + S[2*i+1]; } cipherTxt[0] = A; cipherTxt[1] = B; }
void setup(unsigned char *K) { WORD C, D, L[c]; /* L will be zeroed */ int u = w/8; /* u = number of bytes per word */ int i, j, h; // Copy secret key into L //for(i = b-1, L[c-1]=0; i != -1; --i) for(i = b-1; i != -1; --i) L[i/u] = (L[i/u] << 8) + K[i]; //L[i/u] = ROTATE_L(L[i/u], 8) + K[i]; // Initialize Array S for (S[0] = P, i = 1; i < t; ++i) S[i] = S[i-1] + Q; // Mix in Secret Key for (i=j=h=C=D=0; h < 3*t; ++h, i=(i+1)%t, j=(j+1)%c) { C = S[i] = ROTATE_L(S[i] + (C + D), 3); D = L[j] = ROTATE_L(L[j] + (C + D), (C+D)); } }
int main(int argc, unsigned char **argv) { char byte; int cnt, i, j; WORD plainTxt[2] = {0,0}; WORD cipherTxt[2] = {0,0}; #ifdef DEBUG (isBigEndian()) ? printf("*** Big Endian ***\n") : printf("*** Little Endian ***\n\n"); #endif // Some basic error checking if (argc < 2) { printf("Key not supplied... Exiting!\n"); exit(1); } if (strlen(argv[1]) > 2*b) { printf("Key exceeded %d hex characters... Exiting!\n", 2*b); exit(1); } setHexKey(argv[1]); #if DEBUG printf("[HEX KEY] 0x: "); for (i=0; i < b; i++) { printf("%02x ", K[i]); } puts("\n"); #endif setup(K); cnt = i = j = 0; while ( (byte = getchar()) != EOF ) { ++cnt; // i in interval [0,3]; Alternate plainTxt index, j, every 4 characters if (i == 4) { i = 0; j = (j == 0) ? 1 : 0; } plainTxt[j] += (unsigned int)ROTATE_L(byte, i*8); // Encrypt after every 8 characters if (cnt % 8 == 0) { encrypt(plainTxt, cipherTxt); printf("[CIPHER HEX] %.8X %.8X\n", cipherTxt[0], cipherTxt[1]); #if 1 // Decryption decrypt(cipherTxt, plainTxt); printf("[PLAIN HEX ] %.8X %.8X\n\n", plainTxt[0], plainTxt[1]); #endif plainTxt[0] = 0; plainTxt[1] = 0; } ++i; } // Encrypt any remaining characters if (cnt % 8 != 0) { encrypt(plainTxt, cipherTxt); printf("[CIPHER HEX] %.8X %.8X\n", cipherTxt[0], cipherTxt[1]); decrypt(cipherTxt, plainTxt); printf("[PLAIN HEX ] %.8X %.8X\n\n", plainTxt[0], plainTxt[1]); } #if DEBUG printf("[cnt = %d : cnt (mod 8) = %d ]\n", cnt, cnt%8); #endif return 0; }
(x2) = (x2) ^ (round_key)[2]; \ (x3) = (x3) ^ (round_key)[3] void serpent_key_expand(uint32_t* key, uint32_t key_length, uint32_t* round_key){ uint32_t i; if (key_length < SERPENT_KEY_MAX_NB_BIT){ key[key_length >> 5] &= ~(0xffffffff << (key_length & 0x0000001f)); key[key_length >> 5] |= 0x00000001 << (key_length & 0x0000001f); for (i = (key_length >> 5) + 1; i < SERPENT_KEY_MAX_NB_DWORD; i++){ key[i] = 0; } } round_key[0] = ROTATE_L(key[0] ^ key[3] ^ key[5] ^ key[7] ^ SERPENT_GOLDEN_RATIO ^ 0, 11); round_key[1] = ROTATE_L(key[1] ^ key[4] ^ key[6] ^ round_key[0] ^ SERPENT_GOLDEN_RATIO ^ 1, 11); round_key[2] = ROTATE_L(key[2] ^ key[5] ^ key[7] ^ round_key[1] ^ SERPENT_GOLDEN_RATIO ^ 2, 11); round_key[3] = ROTATE_L(key[3] ^ key[6] ^ round_key[0] ^ round_key[2] ^ SERPENT_GOLDEN_RATIO ^ 3, 11); round_key[4] = ROTATE_L(key[4] ^ key[7] ^ round_key[1] ^ round_key[3] ^ SERPENT_GOLDEN_RATIO ^ 4, 11); round_key[5] = ROTATE_L(key[5] ^ round_key[0] ^ round_key[2] ^ round_key[4] ^ SERPENT_GOLDEN_RATIO ^ 5, 11); round_key[6] = ROTATE_L(key[6] ^ round_key[1] ^ round_key[3] ^ round_key[5] ^ SERPENT_GOLDEN_RATIO ^ 6, 11); round_key[7] = ROTATE_L(key[7] ^ round_key[2] ^ round_key[4] ^ round_key[6] ^ SERPENT_GOLDEN_RATIO ^ 7, 11); for (i = 8; i < SERPENT_ROUND_KEY_NB_DWORD; i++){ round_key[i] = ROTATE_L(round_key[i - 8] ^ round_key[i - 5] ^ round_key[i - 3] ^ round_key[i - 1] ^ SERPENT_GOLDEN_RATIO ^ i, 11); } SBoxE3(round_key[0 ], round_key[1 ], round_key[2 ], round_key[3 ]); SBoxE2(round_key[4 ], round_key[5 ], round_key[6 ], round_key[7 ]); SBoxE1(round_key[8 ], round_key[9 ], round_key[10 ], round_key[11 ]);