2002/03/21 01:19:32
[org.ibex.core.git] / src / org / bouncycastle / crypto / engines / RC4Engine.java
diff --git a/src/org/bouncycastle/crypto/engines/RC4Engine.java b/src/org/bouncycastle/crypto/engines/RC4Engine.java
new file mode 100644 (file)
index 0000000..0adc923
--- /dev/null
@@ -0,0 +1,144 @@
+package org.bouncycastle.crypto.engines;\r
+\r
+import org.bouncycastle.crypto.StreamCipher;\r
+import org.bouncycastle.crypto.CipherParameters;\r
+import org.bouncycastle.crypto.DataLengthException;\r
+import org.bouncycastle.crypto.params.KeyParameter;\r
+\r
+public class RC4Engine implements StreamCipher\r
+{\r
+    private final static int STATE_LENGTH = 256;\r
+\r
+    /*\r
+     * variables to hold the state of the RC4 engine\r
+     * during encryption and decryption\r
+     */\r
+\r
+    private byte[]      engineState = null;\r
+    private int         x = 0;\r
+    private int         y = 0;\r
+    private byte[]      workingKey = null;\r
+\r
+    /**\r
+     * initialise a RC4 cipher.\r
+     *\r
+     * @param forEncryption whether or not we are for encryption.\r
+     * @param params the parameters required to set up the cipher.\r
+     * @exception IllegalArgumentException if the params argument is\r
+     * inappropriate.\r
+     */\r
+    public void init(\r
+        boolean             forEncryption, \r
+        CipherParameters     params\r
+    )\r
+    {\r
+        if (params instanceof KeyParameter)\r
+        {\r
+            /* \r
+             * RC4 encryption and decryption is completely\r
+             * symmetrical, so the 'forEncryption' is \r
+             * irrelevant.\r
+             */\r
+            workingKey = ((KeyParameter)params).getKey();\r
+            setKey(workingKey);\r
+\r
+            return;\r
+        }\r
+\r
+        throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());\r
+    }\r
+\r
+    public String getAlgorithmName()\r
+    {\r
+        return "RC4";\r
+    }\r
+\r
+    public byte returnByte(byte in)\r
+    {\r
+        x = (x + 1) & 0xff;\r
+        y = (engineState[x] + y) & 0xff;\r
+\r
+        // swap\r
+        byte tmp = engineState[x];\r
+        engineState[x] = engineState[y];\r
+        engineState[y] = tmp;\r
+\r
+        // xor\r
+        return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);\r
+    }\r
+\r
+    public void processBytes(\r
+        byte[]     in, \r
+        int     inOff, \r
+        int     len, \r
+        byte[]     out, \r
+        int     outOff\r
+    )\r
+    {\r
+        if ((inOff + len) > in.length)\r
+        {\r
+            throw new DataLengthException("input buffer too short");\r
+        }\r
+\r
+        if ((outOff + len) > out.length)\r
+        {\r
+            throw new DataLengthException("output buffer too short");\r
+        }\r
+\r
+        for (int i = 0; i < len ; i++)\r
+        {\r
+            x = (x + 1) & 0xff;\r
+            y = (engineState[x] + y) & 0xff;\r
+\r
+            // swap\r
+            byte tmp = engineState[x];\r
+            engineState[x] = engineState[y];\r
+            engineState[y] = tmp;\r
+\r
+            // xor\r
+            out[i+outOff] = (byte)(in[i + inOff]\r
+                    ^ engineState[(engineState[x] + engineState[y]) & 0xff]);\r
+        }\r
+    }\r
+\r
+    public void reset()\r
+    {\r
+        setKey(workingKey);\r
+    }\r
+\r
+    // Private implementation\r
+\r
+    private void setKey(byte[] keyBytes)\r
+    {\r
+        workingKey = keyBytes;\r
+\r
+        // System.out.println("the key length is ; "+ workingKey.length);\r
+\r
+        x = 0;\r
+        y = 0;\r
+\r
+        if (engineState == null)\r
+        {\r
+            engineState = new byte[STATE_LENGTH];\r
+        }\r
+\r
+        // reset the state of the engine\r
+        for (int i=0; i < STATE_LENGTH; i++)\r
+        {\r
+            engineState[i] = (byte)i;\r
+        }\r
+        \r
+        int i1 = 0;\r
+        int i2 = 0;\r
+\r
+        for (int i=0; i < STATE_LENGTH; i++)\r
+        {\r
+            i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;\r
+            // do the byte-swap inline\r
+            byte tmp = engineState[i];\r
+            engineState[i] = engineState[i2];\r
+            engineState[i2] = tmp;\r
+            i1 = (i1+1) % keyBytes.length; \r
+        }\r
+    }\r
+}\r