Mercurial > projects > dcrypt
comparison dcrypt/crypto/ciphers/RC6.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 |
---|---|
23 * | 23 * |
24 * This algorithm is patented and trademarked. | 24 * This algorithm is patented and trademarked. |
25 * | 25 * |
26 * References: http://people.csail.mit.edu/rivest/Rc6.pdf | 26 * References: http://people.csail.mit.edu/rivest/Rc6.pdf |
27 */ | 27 */ |
28 class RC6 : BlockCipher { | 28 class RC6 : BlockCipher |
29 private { | 29 { |
30 private | |
31 { | |
30 const uint ROUNDS = 20, | 32 const uint ROUNDS = 20, |
31 BLOCK_SIZE = 16, | 33 BLOCK_SIZE = 16, |
32 // Magic constants for a 32 bit word size | 34 // Magic constants for a 32 bit word size |
33 P = 0xb7e15163, | 35 P = 0xb7e15163, |
34 Q = 0x9e3779b9; | 36 Q = 0x9e3779b9; |
35 uint[] S; | 37 uint[] S; |
36 ubyte[] workingKey; | 38 ubyte[] workingKey; |
37 } | 39 } |
38 | 40 |
39 char[] name() { | 41 char[] name() |
42 { | |
40 return "RC6"; | 43 return "RC6"; |
41 } | 44 } |
42 | 45 |
43 uint blockSize() { | 46 uint blockSize() |
47 { | |
44 return BLOCK_SIZE; | 48 return BLOCK_SIZE; |
45 } | 49 } |
46 | 50 |
47 void init(bool encrypt, CipherParameters params) { | 51 void init(bool encrypt, CipherParameters params) |
52 { | |
48 SymmetricKey keyParams = cast(SymmetricKey)params; | 53 SymmetricKey keyParams = cast(SymmetricKey)params; |
49 if (!keyParams) | 54 if (!keyParams) |
50 throw new InvalidParameterError( | 55 throw new InvalidParameterError( |
51 name()~": Invalid parameter passed to init"); | 56 name()~": Invalid parameter passed to init"); |
57 | |
52 _encrypt = encrypt; | 58 _encrypt = encrypt; |
53 | 59 |
54 uint len = keyParams.key.length; | 60 uint len = keyParams.key.length; |
55 if (len != 16 && len != 24 && len != 32) | 61 if (len != 16 && len != 24 && len != 32) |
56 throw new InvalidKeyError( | 62 throw new InvalidKeyError( |
82 C = ByteConverter.LittleEndian.to!(uint)(input[8..12]), | 88 C = ByteConverter.LittleEndian.to!(uint)(input[8..12]), |
83 D = ByteConverter.LittleEndian.to!(uint)(input[12..16]), | 89 D = ByteConverter.LittleEndian.to!(uint)(input[12..16]), |
84 t, | 90 t, |
85 u; | 91 u; |
86 | 92 |
87 if (_encrypt) { | 93 if (_encrypt) |
94 { | |
88 B += S[0]; | 95 B += S[0]; |
89 D += S[1]; | 96 D += S[1]; |
90 for (int i = 1; i <= ROUNDS; i++) { | 97 |
98 for (int i = 1; i <= ROUNDS; i++) | |
99 { | |
91 t = Bitwise.rotateLeft(B*((B<<1)+1), 5); | 100 t = Bitwise.rotateLeft(B*((B<<1)+1), 5); |
92 u = Bitwise.rotateLeft(D*((D<<1)+1), 5); | 101 u = Bitwise.rotateLeft(D*((D<<1)+1), 5); |
93 A = Bitwise.rotateLeft(A^t, u) + S[i<<1]; | 102 A = Bitwise.rotateLeft(A^t, u) + S[i<<1]; |
94 C = Bitwise.rotateLeft(C^u, t) + S[(i<<1)+1]; | 103 C = Bitwise.rotateLeft(C^u, t) + S[(i<<1)+1]; |
95 t = A; | 104 t = A; |
96 A = B; | 105 A = B; |
97 B = C; | 106 B = C; |
98 C = D; | 107 C = D; |
99 D = t; | 108 D = t; |
100 } | 109 } |
110 | |
101 A += S[2*ROUNDS+2]; | 111 A += S[2*ROUNDS+2]; |
102 C += S[2*ROUNDS+3]; | 112 C += S[2*ROUNDS+3]; |
103 } else { | 113 } |
114 else | |
115 { | |
104 C -= S[2*ROUNDS+3]; | 116 C -= S[2*ROUNDS+3]; |
105 A -= S[2*ROUNDS+2]; | 117 A -= S[2*ROUNDS+2]; |
106 for (int i = ROUNDS; i >= 1; i--) { | 118 |
119 for (int i = ROUNDS; i >= 1; i--) | |
120 { | |
107 t = D; | 121 t = D; |
108 D = C; | 122 D = C; |
109 C = B; | 123 C = B; |
110 B = A; | 124 B = A; |
111 A = t; | 125 A = t; |
112 u = Bitwise.rotateLeft(D*((D<<1)+1), 5); | 126 u = Bitwise.rotateLeft(D*((D<<1)+1), 5); |
113 t = Bitwise.rotateLeft(B*((B<<1)+1), 5); | 127 t = Bitwise.rotateLeft(B*((B<<1)+1), 5); |
114 C = Bitwise.rotateRight(C-S[(i<<1)+1], t) ^ u; | 128 C = Bitwise.rotateRight(C-S[(i<<1)+1], t) ^ u; |
115 A = Bitwise.rotateRight(A-S[i<<1], u) ^ t; | 129 A = Bitwise.rotateRight(A-S[i<<1], u) ^ t; |
116 } | 130 } |
131 | |
117 D -= S[1]; | 132 D -= S[1]; |
118 B -= S[0]; | 133 B -= S[0]; |
119 } | 134 } |
120 | 135 |
121 output[0..4] = ByteConverter.LittleEndian.from!(uint)(A); | 136 output[0..4] = ByteConverter.LittleEndian.from!(uint)(A); |
124 output[12..16] = ByteConverter.LittleEndian.from!(uint)(D); | 139 output[12..16] = ByteConverter.LittleEndian.from!(uint)(D); |
125 | 140 |
126 return BLOCK_SIZE; | 141 return BLOCK_SIZE; |
127 } | 142 } |
128 | 143 |
129 void reset() { | 144 void reset() |
145 { | |
130 setup(workingKey); | 146 setup(workingKey); |
131 } | 147 } |
132 | 148 |
133 void setup(ubyte[] key) { | 149 void setup(ubyte[] key) |
150 { | |
134 uint c = key.length/4; | 151 uint c = key.length/4; |
135 uint[] L = new uint[c]; | 152 uint[] L = new uint[c]; |
136 for (int i = 0, j = 0; i < c; i++, j+=4) | 153 for (int i = 0, j = 0; i < c; i++, j+=4) |
137 L[i] = ByteConverter.LittleEndian.to!(uint)(key[j..j+int.sizeof]); | 154 L[i] = ByteConverter.LittleEndian.to!(uint)(key[j..j+int.sizeof]); |
138 | 155 |
139 S[0] = P; | 156 S[0] = P; |
140 for (int i = 1; i <= 2*ROUNDS+3; i++) | 157 for (int i = 1; i <= 2*ROUNDS+3; i++) |
141 S[i] = S[i-1] + Q; | 158 S[i] = S[i-1] + Q; |
142 | 159 |
143 uint A, B, i, j, v = 3*(2*ROUNDS+4); // Relying on ints initializing to 0 | 160 uint A, B, i, j, v = 3*(2*ROUNDS+4); // Relying on ints initializing to 0 |
144 for (int s = 1; s <= v; s++) { | 161 for (int s = 1; s <= v; s++) |
162 { | |
145 A = S[i] = Bitwise.rotateLeft(S[i]+A+B, 3); | 163 A = S[i] = Bitwise.rotateLeft(S[i]+A+B, 3); |
146 B = L[j] = Bitwise.rotateLeft(L[j]+A+B, A+B); | 164 B = L[j] = Bitwise.rotateLeft(L[j]+A+B, A+B); |
147 i = (i + 1) % (2*ROUNDS+4); | 165 i = (i + 1) % (2*ROUNDS+4); |
148 j = (j + 1) % c; | 166 j = (j + 1) % c; |
149 } | 167 } |
150 } | 168 } |
151 | 169 |
152 /** Some RC6 test vectors from the spec. */ | 170 /** Some RC6 test vectors from the spec. */ |
153 debug (UnitTest) { | 171 debug (UnitTest) |
154 unittest { | 172 { |
173 unittest | |
174 { | |
155 static const char[][] test_keys = [ | 175 static const char[][] test_keys = [ |
156 "00000000000000000000000000000000", | 176 "00000000000000000000000000000000", |
157 "0123456789abcdef0112233445566778", | 177 "0123456789abcdef0112233445566778", |
158 "00000000000000000000000000000000"~ | 178 "00000000000000000000000000000000"~ |
159 "0000000000000000", | 179 "0000000000000000", |
182 "8f5fbd0510d15fa893fa3fda6e857ec2", | 202 "8f5fbd0510d15fa893fa3fda6e857ec2", |
183 "c8241816f0d7e48920ad16a1674e5d48" | 203 "c8241816f0d7e48920ad16a1674e5d48" |
184 ]; | 204 ]; |
185 | 205 |
186 RC6 t = new RC6(); | 206 RC6 t = new RC6(); |
187 foreach (uint i, char[] test_key; test_keys) { | 207 foreach (uint i, char[] test_key; test_keys) |
208 { | |
188 ubyte[] buffer = new ubyte[t.blockSize]; | 209 ubyte[] buffer = new ubyte[t.blockSize]; |
189 char[] result; | 210 char[] result; |
190 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); | 211 SymmetricKey key = new SymmetricKey(ByteConverter.hexDecode(test_key)); |
191 | 212 |
192 // Encryption | 213 // Encryption |