Mercurial > projects > dcrypt
annotate dcrypt/crypto/ciphers/RC4.d @ 2:71aae178f89a
Added copy() to hash functions. Modified some code style.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Wed, 13 Aug 2008 22:01:19 -0400 |
parents | 483e4467b5f6 |
children | 5cb17e09d685 |
rev | line source |
---|---|
0 | 1 /** |
2 * This file is part of the dcrypt project. | |
3 * | |
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved. | |
5 * License: MIT | |
6 * Authors: Thomas Dixon | |
7 */ | |
8 | |
9 module dcrypt.crypto.ciphers.RC4; | |
10 | |
11 import dcrypt.crypto.StreamCipher; | |
12 | |
13 version (UnitTest) { | |
14 import dcrypt.misc.Util; | |
15 } | |
16 | |
17 /** Implementation of RC4 designed by Ron Rivest of RSA Security. */ | |
18 class RC4 : StreamCipher { | |
1
483e4467b5f6
Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
19 private { |
483e4467b5f6
Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
20 ubyte[] state, |
483e4467b5f6
Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
21 workingKey; |
483e4467b5f6
Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
22 ubyte x, y; |
483e4467b5f6
Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
23 bool initialized; |
483e4467b5f6
Added Blowfish with test vectors. Minor cleanup of other cipher classes (should probably clean more). Continued work on high-level cipher API (didn't get very far).
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
24 } |
0 | 25 |
26 void init(bool encrypt, CipherParameters params) { | |
27 SymmetricKey keyParams = cast(SymmetricKey)params; | |
28 if (!keyParams) | |
29 throw new InvalidParameterError( | |
30 name()~": Invalid parameter passed to init"); | |
31 if (keyParams.key.length < 0 || keyParams.key.length > 256) | |
32 throw new InvalidKeyError( | |
33 name()~": Invalid key length (requires 1-256 bytes)"); | |
34 workingKey = keyParams.key; | |
35 state = new ubyte[256]; | |
36 setup(workingKey); | |
37 initialized = true; | |
38 } | |
39 | |
40 char[] name() { | |
41 return "RC4"; | |
42 } | |
43 | |
44 ubyte returnByte(ubyte input) { | |
45 y += state[++x]; | |
46 ubyte t = state[x]; | |
47 state[x] = state[y]; | |
48 state[y] = t; | |
49 return (input^state[cast(ubyte)(state[x]+state[y])]); | |
50 } | |
51 | |
52 void processBytes(void[] input_, uint inOff, uint len, void[] output_, uint outOff) { | |
53 if (!initialized) | |
54 throw new NotInitializedError(name()~": Cipher not initialized"); | |
55 | |
56 ubyte[] input = cast(ubyte[]) input_; | |
57 ubyte[] output = cast(ubyte[]) output_; | |
58 | |
59 if ((inOff + len) > input.length) | |
60 throw new ShortBufferError(name()~": Input buffer too short"); | |
61 | |
62 if ((outOff + len) > output.length) | |
63 throw new ShortBufferError(name()~": Output buffer too short"); | |
64 | |
65 for (int i = 0; i < len; i++) { | |
66 y += state[++x]; | |
67 ubyte t = state[x]; | |
68 state[x] = state[y]; | |
69 state[y] = t; | |
70 output[outOff++] = input[inOff++] ^ state[cast(ubyte)(state[x]+state[y])]; | |
71 } | |
72 } | |
73 | |
74 void reset() { | |
75 setup(workingKey); | |
76 } | |
77 | |
78 // Do RC4's key setup in a separate method to ease resetting | |
79 private void setup(ubyte[] key) { | |
80 for (int i = 0; i < 256; i++) | |
81 state[i] = cast(ubyte)i; | |
82 | |
83 x = 0; | |
84 for (int i = 0; i < 256; i++) { | |
85 x += key[i % key.length] + state[i]; | |
86 ubyte t = state[i]; | |
87 state[i] = state[x]; | |
88 state[x] = t; | |
89 } | |
90 x = y = 0; | |
91 } | |
92 | |
93 /** Some RC4 test vectors. */ | |
94 version (UnitTest) { | |
95 unittest { | |
96 static const char[][] test_keys = [ | |
97 "0123456789abcdef", | |
98 "0123456789abcdef", | |
99 "0000000000000000", | |
100 "ef012345", | |
101 "0123456789abcdef" | |
102 ]; | |
103 | |
104 static const char[][] test_plaintexts = [ | |
105 "0123456789abcdef", | |
106 "0000000000000000", | |
107 "0000000000000000", | |
108 "00000000000000000000", | |
109 "01010101010101010101010101010101"~ | |
110 "01010101010101010101010101010101"~ | |
111 "01010101010101010101010101010101"~ | |
112 "01010101010101010101010101010101"~ | |
113 "01010101010101010101010101010101"~ | |
114 "01010101010101010101010101010101"~ | |
115 "01010101010101010101010101010101"~ | |
116 "01010101010101010101010101010101"~ | |
117 "01010101010101010101010101010101"~ | |
118 "01010101010101010101010101010101"~ | |
119 "01010101010101010101010101010101"~ | |
120 "01010101010101010101010101010101"~ | |
121 "01010101010101010101010101010101"~ | |
122 "01010101010101010101010101010101"~ | |
123 "01010101010101010101010101010101"~ | |
124 "01010101010101010101010101010101"~ | |
125 "01010101010101010101010101010101"~ | |
126 "01010101010101010101010101010101"~ | |
127 "01010101010101010101010101010101"~ | |
128 "01010101010101010101010101010101"~ | |
129 "01010101010101010101010101010101"~ | |
130 "01010101010101010101010101010101"~ | |
131 "01010101010101010101010101010101"~ | |
132 "01010101010101010101010101010101"~ | |
133 "01010101010101010101010101010101"~ | |
134 "01010101010101010101010101010101"~ | |
135 "01010101010101010101010101010101"~ | |
136 "01010101010101010101010101010101"~ | |
137 "01010101010101010101010101010101"~ | |
138 "01010101010101010101010101010101"~ | |
139 "01010101010101010101010101010101"~ | |
140 "01010101010101010101010101010101" | |
141 ]; | |
142 | |
143 static const char[][] test_ciphertexts = [ | |
144 "75b7878099e0c596", | |
145 "7494c2e7104b0879", | |
146 "de188941a3375d3a", | |
147 "d6a141a7ec3c38dfbd61", | |
148 "7595c3e6114a09780c4ad452338e1ffd"~ | |
149 "9a1be9498f813d76533449b6778dcad8"~ | |
150 "c78a8d2ba9ac66085d0e53d59c26c2d1"~ | |
151 "c490c1ebbe0ce66d1b6b1b13b6b919b8"~ | |
152 "47c25a91447a95e75e4ef16779cde8bf"~ | |
153 "0a95850e32af9689444fd377108f98fd"~ | |
154 "cbd4e726567500990bcc7e0ca3c4aaa3"~ | |
155 "04a387d20f3b8fbbcd42a1bd311d7a43"~ | |
156 "03dda5ab078896ae80c18b0af66dff31"~ | |
157 "9616eb784e495ad2ce90d7f772a81747"~ | |
158 "b65f62093b1e0db9e5ba532fafec4750"~ | |
159 "8323e671327df9444432cb7367cec82f"~ | |
160 "5d44c0d00b67d650a075cd4b70dedd77"~ | |
161 "eb9b10231b6b5b741347396d62897421"~ | |
162 "d43df9b42e446e358e9c11a9b2184ecb"~ | |
163 "ef0cd8e7a877ef968f1390ec9b3d35a5"~ | |
164 "585cb009290e2fcde7b5ec66d9084be4"~ | |
165 "4055a619d9dd7fc3166f9487f7cb2729"~ | |
166 "12426445998514c15d53a18c864ce3a2"~ | |
167 "b7555793988126520eacf2e3066e230c"~ | |
168 "91bee4dd5304f5fd0405b35bd99c7313"~ | |
169 "5d3d9bc335ee049ef69b3867bf2d7bd1"~ | |
170 "eaa595d8bfc0066ff8d31509eb0c6caa"~ | |
171 "006c807a623ef84c3d33c195d23ee320"~ | |
172 "c40de0558157c822d4b8c569d849aed5"~ | |
173 "9d4e0fd7f379586b4b7ff684ed6a189f"~ | |
174 "7486d49b9c4bad9ba24b96abf924372c"~ | |
175 "8a8fffb10d55354900a77a3db5f205e1"~ | |
176 "b99fcd8660863a159ad4abe40fa48934"~ | |
177 "163ddde542a6585540fd683cbfd8c00f"~ | |
178 "12129a284deacc4cdefe58be7137541c"~ | |
179 "047126c8d49e2755ab181ab7e940b0c0" | |
180 ]; | |
181 | |
182 RC4 r = new RC4(); | |
183 foreach (uint i, char[] test_key; test_keys) { | |
184 ubyte[] buffer = new ubyte[test_plaintexts[i].length>>1]; | |
185 char[] result; | |
186 | |
187 r.init(true, new SymmetricKey(Util.hexToUbytes(test_key))); | |
188 | |
189 // Encryption | |
190 r.processBytes(Util.hexToUbytes(test_plaintexts[i]), 0, buffer.length, buffer, 0); | |
191 result = Util.ubytesToHex(buffer); | |
192 assert(result == test_ciphertexts[i], | |
2
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
1
diff
changeset
|
193 r.name~": ("~result~") != ("~test_ciphertexts[i]~")"); |
0 | 194 |
195 r.reset(); | |
196 | |
197 // Decryption | |
198 r.processBytes(Util.hexToUbytes(test_ciphertexts[i]), 0, buffer.length, buffer, 0); | |
199 result = Util.ubytesToHex(buffer); | |
200 assert(result == test_plaintexts[i], | |
2
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
1
diff
changeset
|
201 r.name~": ("~result~") != ("~test_ciphertexts[i]~")"); |
0 | 202 } |
203 } | |
204 } | |
205 } |