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