Mercurial > projects > ldc
comparison tango/tango/io/digest/Sha256.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 /******************************************************************************* | |
2 | |
3 copyright: Copyright (c) 2006 Tango. All rights reserved | |
4 | |
5 license: BSD style: see doc/license.txt for details | |
6 | |
7 version: Initial release: Feb 2006 | |
8 | |
9 author: Regan Heath, Oskar Linde | |
10 | |
11 This module implements the SHA-256 Algorithm described by Secure | |
12 Hash Standard, FIPS PUB 180-2 | |
13 | |
14 *******************************************************************************/ | |
15 | |
16 module tango.io.digest.Sha256; | |
17 | |
18 private import tango.core.ByteSwap; | |
19 | |
20 public import tango.io.digest.Digest; | |
21 | |
22 private import tango.io.digest.MerkleDamgard; | |
23 | |
24 /******************************************************************************* | |
25 | |
26 *******************************************************************************/ | |
27 | |
28 final class Sha256 : MerkleDamgard | |
29 { | |
30 private uint[8] context; | |
31 private const uint padChar = 0x80; | |
32 | |
33 /*********************************************************************** | |
34 | |
35 Construct an Sha256 | |
36 | |
37 ***********************************************************************/ | |
38 | |
39 this() { } | |
40 | |
41 /*********************************************************************** | |
42 | |
43 Initialize the cipher | |
44 | |
45 Remarks: | |
46 Returns the cipher state to it's initial value | |
47 | |
48 ***********************************************************************/ | |
49 | |
50 protected override void reset() | |
51 { | |
52 super.reset(); | |
53 context[] = initial[]; | |
54 } | |
55 | |
56 /*********************************************************************** | |
57 | |
58 Obtain the digest | |
59 | |
60 Remarks: | |
61 Returns a digest of the current cipher state, this may be the | |
62 final digest, or a digest of the state between calls to update() | |
63 | |
64 ***********************************************************************/ | |
65 | |
66 protected override void createDigest (ubyte[] buf) | |
67 { | |
68 version (LittleEndian) | |
69 ByteSwap.swap32 (context.ptr, context.length * uint.sizeof); | |
70 | |
71 buf[] = cast(ubyte[]) context; | |
72 } | |
73 | |
74 /*********************************************************************** | |
75 | |
76 The digest size of Sha-256 is 32 bytes | |
77 | |
78 ***********************************************************************/ | |
79 | |
80 uint digestSize() { return 32; } | |
81 | |
82 /*********************************************************************** | |
83 | |
84 Cipher block size | |
85 | |
86 Returns: | |
87 the block size | |
88 | |
89 Remarks: | |
90 Specifies the size (in bytes) of the block of data to pass to | |
91 each call to transform(). For SHA256 the blockSize is 64. | |
92 | |
93 ***********************************************************************/ | |
94 | |
95 protected override uint blockSize() { return 64; } | |
96 | |
97 /*********************************************************************** | |
98 | |
99 Length padding size | |
100 | |
101 Returns: | |
102 the length padding size | |
103 | |
104 Remarks: | |
105 Specifies the size (in bytes) of the padding which uses the | |
106 length of the data which has been ciphered, this padding is | |
107 carried out by the padLength method. For SHA256 the addSize is 8. | |
108 | |
109 ***********************************************************************/ | |
110 | |
111 protected override uint addSize() { return 8; } | |
112 | |
113 /*********************************************************************** | |
114 | |
115 Pads the cipher data | |
116 | |
117 Params: | |
118 data = a slice of the cipher buffer to fill with padding | |
119 | |
120 Remarks: | |
121 Fills the passed buffer slice with the appropriate padding for | |
122 the final call to transform(). This padding will fill the cipher | |
123 buffer up to blockSize()-addSize(). | |
124 | |
125 ***********************************************************************/ | |
126 | |
127 protected override void padMessage(ubyte[] data) | |
128 { | |
129 data[0] = padChar; | |
130 data[1..$] = 0; | |
131 } | |
132 | |
133 /*********************************************************************** | |
134 | |
135 Performs the length padding | |
136 | |
137 Params: | |
138 data = the slice of the cipher buffer to fill with padding | |
139 length = the length of the data which has been ciphered | |
140 | |
141 Remarks: | |
142 Fills the passed buffer slice with addSize() bytes of padding | |
143 based on the length in bytes of the input data which has been | |
144 ciphered. | |
145 | |
146 ***********************************************************************/ | |
147 | |
148 protected override void padLength(ubyte[] data, ulong length) | |
149 { | |
150 length <<= 3; | |
151 for(int j = data.length-1; j >= 0; j--) | |
152 data[$-j-1] = cast(ubyte) (length >> j*8); | |
153 } | |
154 | |
155 /*********************************************************************** | |
156 | |
157 Performs the cipher on a block of data | |
158 | |
159 Params: | |
160 data = the block of data to cipher | |
161 | |
162 Remarks: | |
163 The actual cipher algorithm is carried out by this method on | |
164 the passed block of data. This method is called for every | |
165 blockSize() bytes of input data and once more with the remaining | |
166 data padded to blockSize(). | |
167 | |
168 ***********************************************************************/ | |
169 | |
170 protected override void transform(ubyte[] input) | |
171 { | |
172 uint[64] W; | |
173 uint a,b,c,d,e,f,g,h; | |
174 uint j,t1,t2; | |
175 | |
176 a = context[0]; | |
177 b = context[1]; | |
178 c = context[2]; | |
179 d = context[3]; | |
180 e = context[4]; | |
181 f = context[5]; | |
182 g = context[6]; | |
183 h = context[7]; | |
184 | |
185 bigEndian32(input,W[0..16]); | |
186 for(j = 16; j < 64; j++) { | |
187 W[j] = mix1(W[j-2]) + W[j-7] + mix0(W[j-15]) + W[j-16]; | |
188 } | |
189 | |
190 for(j = 0; j < 64; j++) { | |
191 t1 = h + sum1(e) + Ch(e,f,g) + K[j] + W[j]; | |
192 t2 = sum0(a) + Maj(a,b,c); | |
193 h = g; | |
194 g = f; | |
195 f = e; | |
196 e = d + t1; | |
197 d = c; | |
198 c = b; | |
199 b = a; | |
200 a = t1 + t2; | |
201 } | |
202 | |
203 context[0] += a; | |
204 context[1] += b; | |
205 context[2] += c; | |
206 context[3] += d; | |
207 context[4] += e; | |
208 context[5] += f; | |
209 context[6] += g; | |
210 context[7] += h; | |
211 } | |
212 | |
213 /*********************************************************************** | |
214 | |
215 ***********************************************************************/ | |
216 | |
217 private static uint Ch(uint x, uint y, uint z) | |
218 { | |
219 return (x&y)^(~x&z); | |
220 } | |
221 | |
222 /*********************************************************************** | |
223 | |
224 ***********************************************************************/ | |
225 | |
226 private static uint Maj(uint x, uint y, uint z) | |
227 { | |
228 return (x&y)^(x&z)^(y&z); | |
229 } | |
230 | |
231 /*********************************************************************** | |
232 | |
233 ***********************************************************************/ | |
234 | |
235 private static uint sum0(uint x) | |
236 { | |
237 return rotateRight(x,2)^rotateRight(x,13)^rotateRight(x,22); | |
238 } | |
239 | |
240 /*********************************************************************** | |
241 | |
242 ***********************************************************************/ | |
243 | |
244 private static uint sum1(uint x) | |
245 { | |
246 return rotateRight(x,6)^rotateRight(x,11)^rotateRight(x,25); | |
247 } | |
248 | |
249 /*********************************************************************** | |
250 | |
251 ***********************************************************************/ | |
252 | |
253 private static uint mix0(uint x) | |
254 { | |
255 return rotateRight(x,7)^rotateRight(x,18)^shiftRight(x,3); | |
256 } | |
257 | |
258 /*********************************************************************** | |
259 | |
260 ***********************************************************************/ | |
261 | |
262 private static uint mix1(uint x) | |
263 { | |
264 return rotateRight(x,17)^rotateRight(x,19)^shiftRight(x,10); | |
265 } | |
266 | |
267 /*********************************************************************** | |
268 | |
269 ***********************************************************************/ | |
270 | |
271 private static uint rotateRight(uint x, uint n) | |
272 { | |
273 return (x >> n) | (x << (32-n)); | |
274 } | |
275 | |
276 /*********************************************************************** | |
277 | |
278 ***********************************************************************/ | |
279 | |
280 private static uint shiftRight(uint x, uint n) | |
281 { | |
282 return x >> n; | |
283 } | |
284 } | |
285 | |
286 | |
287 /******************************************************************************* | |
288 | |
289 *******************************************************************************/ | |
290 | |
291 private static uint[] K = | |
292 [ | |
293 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, | |
294 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, | |
295 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | |
296 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, | |
297 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | |
298 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, | |
299 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, | |
300 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 | |
301 ]; | |
302 | |
303 /******************************************************************************* | |
304 | |
305 *******************************************************************************/ | |
306 | |
307 private static const uint[8] initial = | |
308 [ | |
309 0x6a09e667, | |
310 0xbb67ae85, | |
311 0x3c6ef372, | |
312 0xa54ff53a, | |
313 0x510e527f, | |
314 0x9b05688c, | |
315 0x1f83d9ab, | |
316 0x5be0cd19 | |
317 ]; | |
318 | |
319 /******************************************************************************* | |
320 | |
321 *******************************************************************************/ | |
322 | |
323 version (UnitTest) | |
324 { | |
325 unittest | |
326 { | |
327 static char[][] strings = | |
328 [ | |
329 "abc", | |
330 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" | |
331 ]; | |
332 | |
333 static char[][] results = | |
334 [ | |
335 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", | |
336 "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" | |
337 ]; | |
338 | |
339 Sha256 h = new Sha256(); | |
340 | |
341 foreach (int i, char[] s; strings) | |
342 { | |
343 h.update(s); | |
344 char[] d = h.hexDigest(); | |
345 assert(d == results[i],"Cipher:("~s~")("~d~")!=("~results[i]~")"); | |
346 } | |
347 } | |
348 } | |
349 |