Mercurial > projects > dcrypt
annotate dcrypt/crypto/ciphers/RC4.d @ 27:8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 09 May 2009 23:29:20 -0400 |
parents | 176c933827a8 |
children | ad687db713a4 |
rev | line source |
---|---|
0 | 1 /** |
2 * This file is part of the dcrypt project. | |
3 * | |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
4 * Copyright: Copyright (C) dcrypt contributors 2009. All rights reserved. |
0 | 5 * License: MIT |
6 * Authors: Thomas Dixon | |
7 */ | |
8 | |
9 module dcrypt.crypto.ciphers.RC4; | |
10 | |
11 import dcrypt.crypto.StreamCipher; | |
12 | |
26
176c933827a8
Implemented MD4. Refactored MD5. Replaced all instances of 'version (UnitTest)' with 'debug (UnitTest)'.
Thomas Dixon <reikon@reikon.us>
parents:
24
diff
changeset
|
13 debug (UnitTest) { |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
14 import dcrypt.misc.ByteConverter; |
0 | 15 } |
16 | |
17 /** Implementation of RC4 designed by Ron Rivest of RSA Security. */ | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
18 class RC4 : StreamCipher |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
19 { |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
20 private |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
21 { |
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
|
22 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
|
23 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
|
24 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
|
25 } |
0 | 26 |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
27 this() |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
28 { |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
29 state = new ubyte[256]; |
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
30 } |
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
31 |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
32 void init(bool encrypt, CipherParameters params) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
33 { |
0 | 34 SymmetricKey keyParams = cast(SymmetricKey)params; |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
35 |
0 | 36 if (!keyParams) |
37 throw new InvalidParameterError( | |
38 name()~": Invalid parameter passed to init"); | |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
39 |
0 | 40 if (keyParams.key.length < 0 || keyParams.key.length > 256) |
41 throw new InvalidKeyError( | |
42 name()~": Invalid key length (requires 1-256 bytes)"); | |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
43 |
0 | 44 workingKey = keyParams.key; |
45 setup(workingKey); | |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
46 |
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
47 _encrypt = _initialized = true; |
0 | 48 } |
49 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
50 char[] name() |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
51 { |
0 | 52 return "RC4"; |
53 } | |
54 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
55 ubyte returnByte(ubyte input) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
56 { |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
57 if (!_initialized) |
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
58 throw new NotInitializedError(name()~": Cipher not initialized"); |
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
59 |
0 | 60 y += state[++x]; |
61 ubyte t = state[x]; | |
62 state[x] = state[y]; | |
63 state[y] = t; | |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
64 |
0 | 65 return (input^state[cast(ubyte)(state[x]+state[y])]); |
66 } | |
67 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
68 uint update(void[] input_, void[] output_) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
69 { |
14
5ce3012f1def
Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
Thomas Dixon <reikon@reikon.us>
parents:
12
diff
changeset
|
70 if (!_initialized) |
0 | 71 throw new NotInitializedError(name()~": Cipher not initialized"); |
72 | |
8
23c62e28b3a4
Reworked symmetric cipher classes to have SymmetricCipher as their superclass, and follow the general interface of init(), process(), etc. Made sure everything still passed test vectors. Removed Cipher class. I'll worry about that shit when we support something other than symmetric ciphers.
Thomas Dixon <reikon@reikon.us>
parents:
6
diff
changeset
|
73 ubyte[] input = cast(ubyte[]) input_, |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
74 output = cast(ubyte[]) output_; |
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
75 |
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
76 if (input.length > output.length) |
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
77 throw new ShortBufferError(name()~": Output buffer too short"); |
0 | 78 |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
79 for (int i = 0; i < input.length; i++) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
80 { |
0 | 81 y += state[++x]; |
82 ubyte t = state[x]; | |
83 state[x] = state[y]; | |
84 state[y] = t; | |
8
23c62e28b3a4
Reworked symmetric cipher classes to have SymmetricCipher as their superclass, and follow the general interface of init(), process(), etc. Made sure everything still passed test vectors. Removed Cipher class. I'll worry about that shit when we support something other than symmetric ciphers.
Thomas Dixon <reikon@reikon.us>
parents:
6
diff
changeset
|
85 output[i] = input[i] ^ state[cast(ubyte)(state[x]+state[y])]; |
0 | 86 } |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
87 |
12
8c7f8fecdd75
Added ManagedBlockCipher, changed Crypto to just import everything, made Hash.update() return itself (for chaining) and ditched BlockCipherWrapper.
Thomas Dixon <reikon@reikon.us>
parents:
8
diff
changeset
|
88 return input.length; |
0 | 89 } |
90 | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
91 void reset() |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
92 { |
0 | 93 setup(workingKey); |
94 } | |
95 | |
96 // Do RC4's key setup in a separate method to ease resetting | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
97 private void setup(ubyte[] key) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
98 { |
0 | 99 for (int i = 0; i < 256; i++) |
100 state[i] = cast(ubyte)i; | |
101 | |
102 x = 0; | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
103 for (int i = 0; i < 256; i++) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
104 { |
0 | 105 x += key[i % key.length] + state[i]; |
106 ubyte t = state[i]; | |
107 state[i] = state[x]; | |
108 state[x] = t; | |
109 } | |
24
6428dfd7fede
Implemented Salsa20. Added some error checking to RC4's returnByte. Fixed copyright year in Bitwise.d and ByteConverter.d. Added Robert Smith to contributors file. Thanks buddy :)
Thomas Dixon <reikon@reikon.us>
parents:
23
diff
changeset
|
110 |
0 | 111 x = y = 0; |
112 } | |
113 | |
114 /** Some RC4 test vectors. */ | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
115 debug (UnitTest) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
116 { |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
117 unittest |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
118 { |
0 | 119 static const char[][] test_keys = [ |
120 "0123456789abcdef", | |
121 "0123456789abcdef", | |
122 "0000000000000000", | |
123 "ef012345", | |
124 "0123456789abcdef" | |
125 ]; | |
126 | |
127 static const char[][] test_plaintexts = [ | |
128 "0123456789abcdef", | |
129 "0000000000000000", | |
130 "0000000000000000", | |
131 "00000000000000000000", | |
132 "01010101010101010101010101010101"~ | |
133 "01010101010101010101010101010101"~ | |
134 "01010101010101010101010101010101"~ | |
135 "01010101010101010101010101010101"~ | |
136 "01010101010101010101010101010101"~ | |
137 "01010101010101010101010101010101"~ | |
138 "01010101010101010101010101010101"~ | |
139 "01010101010101010101010101010101"~ | |
140 "01010101010101010101010101010101"~ | |
141 "01010101010101010101010101010101"~ | |
142 "01010101010101010101010101010101"~ | |
143 "01010101010101010101010101010101"~ | |
144 "01010101010101010101010101010101"~ | |
145 "01010101010101010101010101010101"~ | |
146 "01010101010101010101010101010101"~ | |
147 "01010101010101010101010101010101"~ | |
148 "01010101010101010101010101010101"~ | |
149 "01010101010101010101010101010101"~ | |
150 "01010101010101010101010101010101"~ | |
151 "01010101010101010101010101010101"~ | |
152 "01010101010101010101010101010101"~ | |
153 "01010101010101010101010101010101"~ | |
154 "01010101010101010101010101010101"~ | |
155 "01010101010101010101010101010101"~ | |
156 "01010101010101010101010101010101"~ | |
157 "01010101010101010101010101010101"~ | |
158 "01010101010101010101010101010101"~ | |
159 "01010101010101010101010101010101"~ | |
160 "01010101010101010101010101010101"~ | |
161 "01010101010101010101010101010101"~ | |
162 "01010101010101010101010101010101"~ | |
163 "01010101010101010101010101010101" | |
164 ]; | |
165 | |
166 static const char[][] test_ciphertexts = [ | |
167 "75b7878099e0c596", | |
168 "7494c2e7104b0879", | |
169 "de188941a3375d3a", | |
170 "d6a141a7ec3c38dfbd61", | |
171 "7595c3e6114a09780c4ad452338e1ffd"~ | |
172 "9a1be9498f813d76533449b6778dcad8"~ | |
173 "c78a8d2ba9ac66085d0e53d59c26c2d1"~ | |
174 "c490c1ebbe0ce66d1b6b1b13b6b919b8"~ | |
175 "47c25a91447a95e75e4ef16779cde8bf"~ | |
176 "0a95850e32af9689444fd377108f98fd"~ | |
177 "cbd4e726567500990bcc7e0ca3c4aaa3"~ | |
178 "04a387d20f3b8fbbcd42a1bd311d7a43"~ | |
179 "03dda5ab078896ae80c18b0af66dff31"~ | |
180 "9616eb784e495ad2ce90d7f772a81747"~ | |
181 "b65f62093b1e0db9e5ba532fafec4750"~ | |
182 "8323e671327df9444432cb7367cec82f"~ | |
183 "5d44c0d00b67d650a075cd4b70dedd77"~ | |
184 "eb9b10231b6b5b741347396d62897421"~ | |
185 "d43df9b42e446e358e9c11a9b2184ecb"~ | |
186 "ef0cd8e7a877ef968f1390ec9b3d35a5"~ | |
187 "585cb009290e2fcde7b5ec66d9084be4"~ | |
188 "4055a619d9dd7fc3166f9487f7cb2729"~ | |
189 "12426445998514c15d53a18c864ce3a2"~ | |
190 "b7555793988126520eacf2e3066e230c"~ | |
191 "91bee4dd5304f5fd0405b35bd99c7313"~ | |
192 "5d3d9bc335ee049ef69b3867bf2d7bd1"~ | |
193 "eaa595d8bfc0066ff8d31509eb0c6caa"~ | |
194 "006c807a623ef84c3d33c195d23ee320"~ | |
195 "c40de0558157c822d4b8c569d849aed5"~ | |
196 "9d4e0fd7f379586b4b7ff684ed6a189f"~ | |
197 "7486d49b9c4bad9ba24b96abf924372c"~ | |
198 "8a8fffb10d55354900a77a3db5f205e1"~ | |
199 "b99fcd8660863a159ad4abe40fa48934"~ | |
200 "163ddde542a6585540fd683cbfd8c00f"~ | |
201 "12129a284deacc4cdefe58be7137541c"~ | |
202 "047126c8d49e2755ab181ab7e940b0c0" | |
203 ]; | |
204 | |
205 RC4 r = new RC4(); | |
27
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
206 foreach (uint i, char[] test_key; test_keys) |
8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
Thomas Dixon <reikon@reikon.us>
parents:
26
diff
changeset
|
207 { |
0 | 208 ubyte[] buffer = new ubyte[test_plaintexts[i].length>>1]; |
209 char[] result; | |
210 | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
211 r.init(true, new SymmetricKey(ByteConverter.hexDecode(test_key))); |
0 | 212 |
213 // Encryption | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
214 r.update(ByteConverter.hexDecode(test_plaintexts[i]), buffer); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
215 result = ByteConverter.hexEncode(buffer); |
0 | 216 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
|
217 r.name~": ("~result~") != ("~test_ciphertexts[i]~")"); |
0 | 218 |
219 r.reset(); | |
220 | |
221 // Decryption | |
23
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
222 r.update(ByteConverter.hexDecode(test_ciphertexts[i]), buffer); |
4589f8c5eb3c
Replaced dcrypt.crypto.Util with dcrypt.misc.Bitwise and dcrypt.misc.ByteConverter. Altered all dependent files to reflect changes.
Thomas Dixon <reikon@reikon.us>
parents:
14
diff
changeset
|
223 result = ByteConverter.hexEncode(buffer); |
0 | 224 assert(result == test_plaintexts[i], |
6
5cb17e09d685
Minor edits to the unittests of hash functions and ciphers. Added AES and test vectors.
Thomas Dixon <reikon@reikon.us>
parents:
2
diff
changeset
|
225 r.name~": ("~result~") != ("~test_plaintexts[i]~")"); |
0 | 226 } |
227 } | |
228 } | |
229 } |