Mercurial > projects > dcrypt
comparison 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 |
comparison
equal
deleted
inserted
replaced
26:176c933827a8 | 27:8b5eaf3c2979 |
---|---|
13 debug (UnitTest) { | 13 debug (UnitTest) { |
14 import dcrypt.misc.ByteConverter; | 14 import dcrypt.misc.ByteConverter; |
15 } | 15 } |
16 | 16 |
17 /** Implementation of RC4 designed by Ron Rivest of RSA Security. */ | 17 /** Implementation of RC4 designed by Ron Rivest of RSA Security. */ |
18 class RC4 : StreamCipher { | 18 class RC4 : StreamCipher |
19 private { | 19 { |
20 private | |
21 { | |
20 ubyte[] state, | 22 ubyte[] state, |
21 workingKey; | 23 workingKey; |
22 ubyte x, y; | 24 ubyte x, y; |
23 } | 25 } |
24 | 26 |
25 this() { | 27 this() |
28 { | |
26 state = new ubyte[256]; | 29 state = new ubyte[256]; |
27 } | 30 } |
28 | 31 |
29 void init(bool encrypt, CipherParameters params) { | 32 void init(bool encrypt, CipherParameters params) |
33 { | |
30 SymmetricKey keyParams = cast(SymmetricKey)params; | 34 SymmetricKey keyParams = cast(SymmetricKey)params; |
31 | 35 |
32 if (!keyParams) | 36 if (!keyParams) |
33 throw new InvalidParameterError( | 37 throw new InvalidParameterError( |
34 name()~": Invalid parameter passed to init"); | 38 name()~": Invalid parameter passed to init"); |
41 setup(workingKey); | 45 setup(workingKey); |
42 | 46 |
43 _encrypt = _initialized = true; | 47 _encrypt = _initialized = true; |
44 } | 48 } |
45 | 49 |
46 char[] name() { | 50 char[] name() |
51 { | |
47 return "RC4"; | 52 return "RC4"; |
48 } | 53 } |
49 | 54 |
50 ubyte returnByte(ubyte input) { | 55 ubyte returnByte(ubyte input) |
56 { | |
51 if (!_initialized) | 57 if (!_initialized) |
52 throw new NotInitializedError(name()~": Cipher not initialized"); | 58 throw new NotInitializedError(name()~": Cipher not initialized"); |
53 | 59 |
54 y += state[++x]; | 60 y += state[++x]; |
55 ubyte t = state[x]; | 61 ubyte t = state[x]; |
57 state[y] = t; | 63 state[y] = t; |
58 | 64 |
59 return (input^state[cast(ubyte)(state[x]+state[y])]); | 65 return (input^state[cast(ubyte)(state[x]+state[y])]); |
60 } | 66 } |
61 | 67 |
62 uint update(void[] input_, void[] output_) { | 68 uint update(void[] input_, void[] output_) |
69 { | |
63 if (!_initialized) | 70 if (!_initialized) |
64 throw new NotInitializedError(name()~": Cipher not initialized"); | 71 throw new NotInitializedError(name()~": Cipher not initialized"); |
65 | 72 |
66 ubyte[] input = cast(ubyte[]) input_, | 73 ubyte[] input = cast(ubyte[]) input_, |
67 output = cast(ubyte[]) output_; | 74 output = cast(ubyte[]) output_; |
68 | 75 |
69 if (input.length > output.length) | 76 if (input.length > output.length) |
70 throw new ShortBufferError(name()~": Output buffer too short"); | 77 throw new ShortBufferError(name()~": Output buffer too short"); |
71 | 78 |
72 for (int i = 0; i < input.length; i++) { | 79 for (int i = 0; i < input.length; i++) |
80 { | |
73 y += state[++x]; | 81 y += state[++x]; |
74 ubyte t = state[x]; | 82 ubyte t = state[x]; |
75 state[x] = state[y]; | 83 state[x] = state[y]; |
76 state[y] = t; | 84 state[y] = t; |
77 output[i] = input[i] ^ state[cast(ubyte)(state[x]+state[y])]; | 85 output[i] = input[i] ^ state[cast(ubyte)(state[x]+state[y])]; |
78 } | 86 } |
79 | 87 |
80 return input.length; | 88 return input.length; |
81 } | 89 } |
82 | 90 |
83 void reset() { | 91 void reset() |
92 { | |
84 setup(workingKey); | 93 setup(workingKey); |
85 } | 94 } |
86 | 95 |
87 // Do RC4's key setup in a separate method to ease resetting | 96 // Do RC4's key setup in a separate method to ease resetting |
88 private void setup(ubyte[] key) { | 97 private void setup(ubyte[] key) |
98 { | |
89 for (int i = 0; i < 256; i++) | 99 for (int i = 0; i < 256; i++) |
90 state[i] = cast(ubyte)i; | 100 state[i] = cast(ubyte)i; |
91 | 101 |
92 x = 0; | 102 x = 0; |
93 for (int i = 0; i < 256; i++) { | 103 for (int i = 0; i < 256; i++) |
104 { | |
94 x += key[i % key.length] + state[i]; | 105 x += key[i % key.length] + state[i]; |
95 ubyte t = state[i]; | 106 ubyte t = state[i]; |
96 state[i] = state[x]; | 107 state[i] = state[x]; |
97 state[x] = t; | 108 state[x] = t; |
98 } | 109 } |
99 | 110 |
100 x = y = 0; | 111 x = y = 0; |
101 } | 112 } |
102 | 113 |
103 /** Some RC4 test vectors. */ | 114 /** Some RC4 test vectors. */ |
104 debug (UnitTest) { | 115 debug (UnitTest) |
105 unittest { | 116 { |
117 unittest | |
118 { | |
106 static const char[][] test_keys = [ | 119 static const char[][] test_keys = [ |
107 "0123456789abcdef", | 120 "0123456789abcdef", |
108 "0123456789abcdef", | 121 "0123456789abcdef", |
109 "0000000000000000", | 122 "0000000000000000", |
110 "ef012345", | 123 "ef012345", |
188 "12129a284deacc4cdefe58be7137541c"~ | 201 "12129a284deacc4cdefe58be7137541c"~ |
189 "047126c8d49e2755ab181ab7e940b0c0" | 202 "047126c8d49e2755ab181ab7e940b0c0" |
190 ]; | 203 ]; |
191 | 204 |
192 RC4 r = new RC4(); | 205 RC4 r = new RC4(); |
193 foreach (uint i, char[] test_key; test_keys) { | 206 foreach (uint i, char[] test_key; test_keys) |
207 { | |
194 ubyte[] buffer = new ubyte[test_plaintexts[i].length>>1]; | 208 ubyte[] buffer = new ubyte[test_plaintexts[i].length>>1]; |
195 char[] result; | 209 char[] result; |
196 | 210 |
197 r.init(true, new SymmetricKey(ByteConverter.hexDecode(test_key))); | 211 r.init(true, new SymmetricKey(ByteConverter.hexDecode(test_key))); |
198 | 212 |