A = A + S[0]; B = B + S[1]; for (i = 1 ; i <= R ; i++) { A = A ^ B; A = rotateLeft(A, B) + S[2*i];
B = B ^ A; B = rotateLeft(B, A) + S[(2*i)+1]; }
Here's a simplified version, without a key schedule, for
differential cryptanalysis testing.
/* A cipher similar to RC5: */ typedef unsigned long var; /* Bit rotate rightwards */ var ror(var v,unsigned int bits) { return (v>>bits)|(v<<(8*sizeof(var)-bits)); } /* Bit rotate left */ var rol(var v,unsigned int bits) { return (v<<bits)|(v>>(8*sizeof(var)-bits)); } /* This class is used to encrypt or decrypt a block of data. */ class cipherblock { public: var L,R; // current state, Left and Right halves // Perform one forward round, using this key. // Modifies L depending on both R and the round key. void round_fw(var &L,const var &R,var key,unsigned int stage) { L=L^R; L=rol(L,R); L=L+key+stage; } // Perform one reverse round, using this key. // Modifies L depending on both R and the round key. void round_bw(var &L,const var &R,var key,unsigned int stage) { L=L-key-stage; L=ror(L,R); L=L^R; } // Print the current state of this block void print(const char *description,int stage) { printf("%s %d: %016lx %016lx\n",description,stage,L,R); } }; int foo(void) { for (int diff=0;diff<100;diff++) { var plain=0xabcdef0000000+diff; // plaintext var key=0xf0f0f0f; // encryption key int r; // round count cipherblock b; b.L=plain; b.R=plain>>32; if (diff==0) b.print(" P",0); // Take several rounds to scramble the data // FIXME: real RC5 uses more rounds, and a real key schedule. for (r=0;r<10;r++) { b.round_fw(b.L,b.R,key,r); if (diff==0) b.print("L",r); b.round_fw(b.R,b.L,key,r); if (diff==0) b.print("R",r); } b.print(" C",0); // Walk rounds backwards to unscramble the data for (r--;r>=0;r--) { if (diff==0) b.print("R",r); b.round_bw(b.R,b.L,key,r); if (diff==0) b.print("L",r); b.round_bw(b.L,b.R,key,r); } if (diff==0) b.print(" P",0); } return 0; }