RC6 algorithm was developed by RSA laboratories from USA. It’s an improved version over its predecessors like RC2, RC4,RC5. It was proposed as an AES candidate for substituting DES algorithm. Given this, it was developed having in mind the AES specifications like operating on 128 bit blocks.

RC6 is a fully parameterized algorithm denoted like RC6 – w/r/b (w – word length, r – rounds, b – key lenght). For AES specs w = 32, r = 20 and can be refered as simply RC6.

The key length b can be anywhere between 0 and 255 bytes. Most used values are 128, 192 or 256 key length(in bits).

For all cases, RC6 work on 4 words of w bits utilizing the following basic operations.

  • a+b    integer addition modulo 2w
  • a-b     integer subtraction modulo 2w
  • a^b   xor operation at word level of w bits
  • a×b    integer multiplication modulo 2w
  • a‹‹‹b   word rotation to left with the value given by the least lgw bits of b
  • a›››b   word rotation to right with value given by the least lgw bits of  b

             where lgw is base 2 logarithm of w.

RC6 is a very compact algorithm, with no lookup tables. Following Java implementation shows its simplicity in code, yet being a very powerfull encryption algorithm.

Encryption and decryption

RC6 works on 4 registers A, B, C, D initially containing the input data. The first byte of plaintext or ciphertext is placed in the least-significant byte of register A, the last byte of plaintext or ciphertext is placed into the most significant byte of D.

Check out a more detailed description of the algorithm in this material.

Regarding java code, here are the functions for RC6 as described for AES standard(w = 32, r = 20)

  • Function encryptBloc contains the actual algorithm for encryption. We take the input and split it up in 4 pieces of 32 bits, storing them in the 4 registers. Next is the actual implementation of the algorithm as described in the official document(see pseudocode). Function rotl is a rotation to left of the first param with second param steps. The number 5 for rotation in the first two is the value given by lgw = lg 32 = 5.Array S holds the w bit round keys as described in the key scheduling process.

private static byte[] encryptBloc(byte[] input){

     byte[] tmp = new byte[input.length];
     int t,u;
     int aux;
     int[] data = new int[input.length/4];
     for(int i =0;i<data.length;i++)
          data[i] = 0;
     int off = 0;
     for(int i=0;i<data.length;i++){
          data[i] = ((input[off++]&0xff))|
		    ((input[off++]&0xff) << 8)|
		    ((input[off++]&0xff) << 16)|
		    ((input[off++]&0xff) << 24);
     }
     int A = data[0],B = data[1],C = data[2],D = data[3];

     B = B + S[0];
     D = D + S[1];
     for(int i = 1;i> (i%4)*8) & 0xff);
     }

     return tmp;
}

  • Following are 2 helper functions for rotation operation.

private static int rotl(int val, int pas) {
     return (val > (32 - pas));
}
private static int rotr(int val, int pas) {
     return (val >>> pas) | (val << (32-pas));
}

  • Decryption is similar. Function decryptBloc handles that

private static byte[] decryptBloc(byte[] input){
     byte[] tmp = new byte[input.length];
     int t,u;
     int aux;
     int[] data = new int[input.length/4];
     for(int i =0;i<data.length;i++)
          data[i] = 0;
     int off = 0;
     for(int i=0;i<data.length;i++){
          data[i] = ((input[off++]&0xff))|
	            ((input[off++]&0xff) << 8)|
                    ((input[off++]&0xff) << 16)|
                    ((input[off++]&0xff) > (i%4)*8) & 0xff);
     }

     return tmp;
}

Key schedule for RC6

Key schedule uses 2 constant called “magic constant”. Their value is given below in hexadecimal.


private static int Pw=0xb7e15163, Qw=0x9e3779b9;

As a first step of the key schedule is preloading the user key of b byte into in array L of c words. The following function does this.

private static int[] convBytesWords(byte[] key, int u, int c) {
     int[] tmp = new int[c];
     for (int i = 0; i < tmp.length; i++)
          tmp[i] = 0;

     for (int i = 0, off = 0; i < c; i++)
          tmp[i] = ((key[off++] & 0xFF))|
                   ((key[off++] & 0xFF) << 8)|
                   ((key[off++] & 0xFF) << 16)|
                   ((key[off++] & 0xFF) << 24);

     return tmp;
}

Having this defined, here is the key scheduling function for RC6

private static int[] generateSubkeys(byte[] key) {

int u = w / 8;
int c = key.length / u;
int t = 2 * r + 4;

int[] L = convBytesWords(key, u, c);

int[] S = new int[t];
S[0] = Pw;
for (int i = 1; i < t; i++)
S[i] = S[i – 1] + Qw;

int A = 0;
int B = 0;
int k = 0, j = 0;

int v = 3 * Math.max(c, t);

for (int i = 0; i < v; i++) {
A = S[k] = rotl((S[k] + A + B), 3);
B = L[j] = rotl(L[j] + A + B, A + B);
k = (k + 1) % t;
j = (j + 1) % c;

}

return S;
}

The source code contains also 2 function encrypt and decrypt as interface with the user. They add padding to the data and split it in blocks.

Below is a link for download entire java implementation of RC6 as a .java file

Download RC6.java file