FileDocCategorySizeDatePackage
RC2Engine.javaAPI DocAndroid 1.5 API12180Wed May 06 22:41:06 BST 2009org.bouncycastle.crypto.engines

RC2Engine

public class RC2Engine extends Object implements org.bouncycastle.crypto.BlockCipher
an implementation of RC2 as described in RFC 2268 "A Description of the RC2(r) Encryption Algorithm" R. Rivest.

Fields Summary
private static byte[]
piTable
private static final int
BLOCK_SIZE
private int[]
workingKey
private boolean
encrypting
Constructors Summary
Methods Summary
private voiddecryptBlock(byte[] in, int inOff, byte[] out, int outOff)

        int x76, x54, x32, x10;

        x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
        x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
        x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
        x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);

        for (int i = 60; i >= 44; i -= 4)
        {
            x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
            x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
            x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
            x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i  ]);
        }

        x76 -= workingKey[x54 & 63];
        x54 -= workingKey[x32 & 63];
        x32 -= workingKey[x10 & 63];
        x10 -= workingKey[x76 & 63];

        for (int i = 40; i >= 20; i -= 4)
        {
            x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
            x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
            x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
            x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i  ]);
        }

        x76 -= workingKey[x54 & 63];
        x54 -= workingKey[x32 & 63];
        x32 -= workingKey[x10 & 63];
        x10 -= workingKey[x76 & 63];

        for (int i = 16; i >= 0; i -= 4)
        {
            x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
            x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
            x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
            x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i  ]);
        }

        out[outOff + 0] = (byte)x10;
        out[outOff + 1] = (byte)(x10 >> 8);
        out[outOff + 2] = (byte)x32;
        out[outOff + 3] = (byte)(x32 >> 8);
        out[outOff + 4] = (byte)x54;
        out[outOff + 5] = (byte)(x54 >> 8);
        out[outOff + 6] = (byte)x76;
        out[outOff + 7] = (byte)(x76 >> 8);
    
private voidencryptBlock(byte[] in, int inOff, byte[] out, int outOff)

        int x76, x54, x32, x10;

        x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
        x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
        x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
        x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);

        for (int i = 0; i <= 16; i += 4)
        {
                x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i  ], 1);
                x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
                x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
                x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
        }

        x10 += workingKey[x76 & 63];
        x32 += workingKey[x10 & 63];
        x54 += workingKey[x32 & 63];
        x76 += workingKey[x54 & 63];

        for (int i = 20; i <= 40; i += 4)
        {
                x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i  ], 1);
                x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
                x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
                x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
        }

        x10 += workingKey[x76 & 63];
        x32 += workingKey[x10 & 63];
        x54 += workingKey[x32 & 63];
        x76 += workingKey[x54 & 63];

        for (int i = 44; i < 64; i += 4)
        {
                x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i  ], 1);
                x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
                x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
                x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
        }

        out[outOff + 0] = (byte)x10;
        out[outOff + 1] = (byte)(x10 >> 8);
        out[outOff + 2] = (byte)x32;
        out[outOff + 3] = (byte)(x32 >> 8);
        out[outOff + 4] = (byte)x54;
        out[outOff + 5] = (byte)(x54 >> 8);
        out[outOff + 6] = (byte)x76;
        out[outOff + 7] = (byte)(x76 >> 8);
    
private int[]generateWorkingKey(byte[] key, int bits)


      
              
                 
    
        int     x;
        int[]   xKey = new int[128];

        for (int i = 0; i != key.length; i++)
        {
            xKey[i] = key[i] & 0xff;
        }

        // Phase 1: Expand input key to 128 bytes
        int len = key.length;

        if (len < 128)
        {
            int     index = 0;

            x = xKey[len - 1];

            do
            {
                x = piTable[(x + xKey[index++]) & 255] & 0xff;
                xKey[len++] = x;
            }
            while (len < 128);
        }

        // Phase 2 - reduce effective key size to "bits"
        len = (bits + 7) >> 3;
        x = piTable[xKey[128 - len] & (255 >> (7 & -bits))] & 0xff;
        xKey[128 - len] = x;

        for (int i = 128 - len - 1; i >= 0; i--)
        {
                x = piTable[x ^ xKey[i + len]] & 0xff;
                xKey[i] = x;
        }

        // Phase 3 - copy to newKey in little-endian order 
        int[] newKey = new int[64];

        for (int i = 0; i != newKey.length; i++)
        {
            newKey[i] = (xKey[2 * i] + (xKey[2 * i + 1] << 8));
        }

        return newKey;
    
public java.lang.StringgetAlgorithmName()

        return "RC2";
    
public intgetBlockSize()

        return BLOCK_SIZE;
    
public voidinit(boolean encrypting, org.bouncycastle.crypto.CipherParameters params)
initialise a RC2 cipher.

param
encrypting whether or not we are for encryption.
param
params the parameters required to set up the cipher.
exception
IllegalArgumentException if the params argument is inappropriate.

        this.encrypting = encrypting;

        if (params instanceof RC2Parameters)
        {
            RC2Parameters   param = (RC2Parameters)params;

            workingKey = generateWorkingKey(param.getKey(),
                                            param.getEffectiveKeyBits());
        }
        else if (params instanceof KeyParameter)
        {
            byte[]    key = ((KeyParameter)params).getKey();

            workingKey = generateWorkingKey(key, key.length * 8);
        }
        else
        {
            throw new IllegalArgumentException("invalid parameter passed to RC2 init - " + params.getClass().getName());
        }

    
public final intprocessBlock(byte[] in, int inOff, byte[] out, int outOff)

        if (workingKey == null)
        {
            throw new IllegalStateException("RC2 engine not initialised");
        }

        if ((inOff + BLOCK_SIZE) > in.length)
        {
            throw new DataLengthException("input buffer too short");
        }

        if ((outOff + BLOCK_SIZE) > out.length)
        {
            throw new DataLengthException("output buffer too short");
        }

        if (encrypting)
        {
            encryptBlock(in, inOff, out, outOff);
        }
        else
        {
            decryptBlock(in, inOff, out, outOff);
        }

        return BLOCK_SIZE;
    
public voidreset()

    
private introtateWordLeft(int x, int y)
return the result rotating the 16 bit number in x left by y

        x &= 0xffff;
        return (x << y) | (x >> (16 - y));