initial checkin
[org.ibex.nanogoat.git] / src / org / bouncycastle / crypto / engines / RC4Engine.java
1 package org.bouncycastle.crypto.engines;\r
2 \r
3 import org.bouncycastle.crypto.StreamCipher;\r
4 import org.bouncycastle.crypto.CipherParameters;\r
5 import org.bouncycastle.crypto.DataLengthException;\r
6 import org.bouncycastle.crypto.params.KeyParameter;\r
7 \r
8 public class RC4Engine implements StreamCipher\r
9 {\r
10     private final static int STATE_LENGTH = 256;\r
11 \r
12     /*\r
13      * variables to hold the state of the RC4 engine\r
14      * during encryption and decryption\r
15      */\r
16 \r
17     private byte[]      engineState = null;\r
18     private int         x = 0;\r
19     private int         y = 0;\r
20     private byte[]      workingKey = null;\r
21 \r
22     /**\r
23      * initialise a RC4 cipher.\r
24      *\r
25      * @param forEncryption whether or not we are for encryption.\r
26      * @param params the parameters required to set up the cipher.\r
27      * @exception IllegalArgumentException if the params argument is\r
28      * inappropriate.\r
29      */\r
30     public void init(\r
31         boolean             forEncryption, \r
32         CipherParameters     params\r
33     )\r
34     {\r
35         if (params instanceof KeyParameter)\r
36         {\r
37             /* \r
38              * RC4 encryption and decryption is completely\r
39              * symmetrical, so the 'forEncryption' is \r
40              * irrelevant.\r
41              */\r
42             workingKey = ((KeyParameter)params).getKey();\r
43             setKey(workingKey);\r
44 \r
45             return;\r
46         }\r
47 \r
48         throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());\r
49     }\r
50 \r
51     public String getAlgorithmName()\r
52     {\r
53         return "RC4";\r
54     }\r
55 \r
56     public byte returnByte(byte in)\r
57     {\r
58         x = (x + 1) & 0xff;\r
59         y = (engineState[x] + y) & 0xff;\r
60 \r
61         // swap\r
62         byte tmp = engineState[x];\r
63         engineState[x] = engineState[y];\r
64         engineState[y] = tmp;\r
65 \r
66         // xor\r
67         return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);\r
68     }\r
69 \r
70     public void processBytes(\r
71         byte[]     in, \r
72         int     inOff, \r
73         int     len, \r
74         byte[]     out, \r
75         int     outOff\r
76     )\r
77     {\r
78         if ((inOff + len) > in.length)\r
79         {\r
80             throw new DataLengthException("input buffer too short");\r
81         }\r
82 \r
83         if ((outOff + len) > out.length)\r
84         {\r
85             throw new DataLengthException("output buffer too short");\r
86         }\r
87 \r
88         for (int i = 0; i < len ; i++)\r
89         {\r
90             x = (x + 1) & 0xff;\r
91             y = (engineState[x] + y) & 0xff;\r
92 \r
93             // swap\r
94             byte tmp = engineState[x];\r
95             engineState[x] = engineState[y];\r
96             engineState[y] = tmp;\r
97 \r
98             // xor\r
99             out[i+outOff] = (byte)(in[i + inOff]\r
100                     ^ engineState[(engineState[x] + engineState[y]) & 0xff]);\r
101         }\r
102     }\r
103 \r
104     public void reset()\r
105     {\r
106         setKey(workingKey);\r
107     }\r
108 \r
109     // Private implementation\r
110 \r
111     private void setKey(byte[] keyBytes)\r
112     {\r
113         workingKey = keyBytes;\r
114 \r
115         // System.out.println("the key length is ; "+ workingKey.length);\r
116 \r
117         x = 0;\r
118         y = 0;\r
119 \r
120         if (engineState == null)\r
121         {\r
122             engineState = new byte[STATE_LENGTH];\r
123         }\r
124 \r
125         // reset the state of the engine\r
126         for (int i=0; i < STATE_LENGTH; i++)\r
127         {\r
128             engineState[i] = (byte)i;\r
129         }\r
130         \r
131         int i1 = 0;\r
132         int i2 = 0;\r
133 \r
134         for (int i=0; i < STATE_LENGTH; i++)\r
135         {\r
136             i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;\r
137             // do the byte-swap inline\r
138             byte tmp = engineState[i];\r
139             engineState[i] = engineState[i2];\r
140             engineState[i2] = tmp;\r
141             i1 = (i1+1) % keyBytes.length; \r
142         }\r
143     }\r
144 }\r