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;
}