RC2Enginepublic class RC2Engine extends Object implements org.bouncycastle.crypto.BlockCipheran 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 |
Methods Summary |
---|
private void | decryptBlock(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 void | encryptBlock(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.String | getAlgorithmName()
return "RC2";
| public int | getBlockSize()
return BLOCK_SIZE;
| public void | init(boolean encrypting, org.bouncycastle.crypto.CipherParameters params)initialise a RC2 cipher.
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 int | processBlock(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 void | reset()
| private int | rotateWordLeft(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));
|
|