X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fbouncycastle%2Fcrypto%2Fengines%2FRC4Engine.java;fp=src%2Forg%2Fbouncycastle%2Fcrypto%2Fengines%2FRC4Engine.java;h=0adc923a8c9f65681b9082bb240b10bdf12e781c;hb=e5e9355b4f4e0e2c8de9068a71c1e3cc26fa9905;hp=0000000000000000000000000000000000000000;hpb=f35445729371789b3d496f426d7f87542f8e1a45;p=org.ibex.core.git diff --git a/src/org/bouncycastle/crypto/engines/RC4Engine.java b/src/org/bouncycastle/crypto/engines/RC4Engine.java new file mode 100644 index 0000000..0adc923 --- /dev/null +++ b/src/org/bouncycastle/crypto/engines/RC4Engine.java @@ -0,0 +1,144 @@ +package org.bouncycastle.crypto.engines; + +import org.bouncycastle.crypto.StreamCipher; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.params.KeyParameter; + +public class RC4Engine implements StreamCipher +{ + private final static int STATE_LENGTH = 256; + + /* + * variables to hold the state of the RC4 engine + * during encryption and decryption + */ + + private byte[] engineState = null; + private int x = 0; + private int y = 0; + private byte[] workingKey = null; + + /** + * initialise a RC4 cipher. + * + * @param forEncryption 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. + */ + public void init( + boolean forEncryption, + CipherParameters params + ) + { + if (params instanceof KeyParameter) + { + /* + * RC4 encryption and decryption is completely + * symmetrical, so the 'forEncryption' is + * irrelevant. + */ + workingKey = ((KeyParameter)params).getKey(); + setKey(workingKey); + + return; + } + + throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName()); + } + + public String getAlgorithmName() + { + return "RC4"; + } + + public byte returnByte(byte in) + { + x = (x + 1) & 0xff; + y = (engineState[x] + y) & 0xff; + + // swap + byte tmp = engineState[x]; + engineState[x] = engineState[y]; + engineState[y] = tmp; + + // xor + return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]); + } + + public void processBytes( + byte[] in, + int inOff, + int len, + byte[] out, + int outOff + ) + { + if ((inOff + len) > in.length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + len) > out.length) + { + throw new DataLengthException("output buffer too short"); + } + + for (int i = 0; i < len ; i++) + { + x = (x + 1) & 0xff; + y = (engineState[x] + y) & 0xff; + + // swap + byte tmp = engineState[x]; + engineState[x] = engineState[y]; + engineState[y] = tmp; + + // xor + out[i+outOff] = (byte)(in[i + inOff] + ^ engineState[(engineState[x] + engineState[y]) & 0xff]); + } + } + + public void reset() + { + setKey(workingKey); + } + + // Private implementation + + private void setKey(byte[] keyBytes) + { + workingKey = keyBytes; + + // System.out.println("the key length is ; "+ workingKey.length); + + x = 0; + y = 0; + + if (engineState == null) + { + engineState = new byte[STATE_LENGTH]; + } + + // reset the state of the engine + for (int i=0; i < STATE_LENGTH; i++) + { + engineState[i] = (byte)i; + } + + int i1 = 0; + int i2 = 0; + + for (int i=0; i < STATE_LENGTH; i++) + { + i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff; + // do the byte-swap inline + byte tmp = engineState[i]; + engineState[i] = engineState[i2]; + engineState[i2] = tmp; + i1 = (i1+1) % keyBytes.length; + } + } +}