The OpenD Programming Language

1 // Written in the D programming language.
2 /**
3  * Computes SHA1 and SHA2 hashes of arbitrary data. SHA hashes are 20 to 64 byte
4  * quantities (depending on the SHA algorithm) that are like a checksum or CRC,
5  * but are more robust.
6  *
7 $(SCRIPT inhibitQuickIndex = 1;)
8 
9 $(DIVC quickindex,
10 $(BOOKTABLE ,
11 $(TR $(TH Category) $(TH Functions)
12 )
13 $(TR $(TDNW Template API) $(TD $(MYREF SHA1)
14 )
15 )
16 $(TR $(TDNW OOP API) $(TD $(MYREF SHA1Digest))
17 )
18 $(TR $(TDNW Helpers) $(TD $(MYREF sha1Of))
19 )
20 )
21 )
22 
23  * SHA2 comes in several different versions, all supported by this module:
24  * SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 and SHA-512/256.
25  *
26  * This module conforms to the APIs defined in $(MREF std, digest). To understand the
27  * differences between the template and the OOP API, see $(MREF std, digest).
28  *
29  * This module publicly imports `std.digest` and can be used as a stand-alone
30  * module.
31  *
32  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
33  *
34  * CTFE:
35  * Digests do not work in CTFE
36  *
37  * Authors:
38  * The routines and algorithms are derived from the
39  * $(I Secure Hash Signature Standard (SHS) (FIPS PUB 180-2)). $(BR )
40  * Kai Nacke, Johannes Pfau, Nick Sabalausky
41  *
42  * References:
43  * $(UL
44  * $(LI $(LINK2 http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf, FIPS PUB180-2))
45  * $(LI $(LINK2 http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/, Fast implementation of SHA1))
46  * $(LI $(LINK2 http://en.wikipedia.org/wiki/Secure_Hash_Algorithm, Wikipedia article about SHA))
47  * )
48  *
49  * Source: $(PHOBOSSRC std/digest/sha.d)
50  *
51  */
52 
53 /*          Copyright Kai Nacke 2012.
54  * Distributed under the Boost Software License, Version 1.0.
55  *    (See accompanying file LICENSE_1_0.txt or copy at
56  *          http://www.boost.org/LICENSE_1_0.txt)
57  */
58 module std.digest.sha;
59 
60 ///
61 @safe unittest
62 {
63     //Template API
64     import std.digest.sha;
65 
66     ubyte[20] hash1 = sha1Of("abc");
67     assert(toHexString(hash1) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
68 
69     ubyte[28] hash224 = sha224Of("abc");
70     assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
71 
72     //Feeding data
73     ubyte[1024] data;
74     SHA1 sha1;
75     sha1.start();
76     sha1.put(data[]);
77     sha1.start(); //Start again
78     sha1.put(data[]);
79     hash1 = sha1.finish();
80 }
81 
82 ///
83 @safe unittest
84 {
85     //OOP API
86     import std.digest.sha;
87 
88     auto sha1 = new SHA1Digest();
89     ubyte[] hash1 = sha1.digest("abc");
90     assert(toHexString(hash1) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
91 
92     auto sha224 = new SHA224Digest();
93     ubyte[] hash224 = sha224.digest("abc");
94     assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
95 
96     //Feeding data
97     ubyte[1024] data;
98     sha1.put(data[]);
99     sha1.reset(); //Start again
100     sha1.put(data[]);
101     hash1 = sha1.finish();
102 }
103 
104 version(LDC) {
105 	// we took in a LDC patch that broke the asm on dmd
106 	// so just not gonna use it except on ldc
107 
108 version (D_InlineAsm_X86)
109 {
110     version (D_PIC) {} // https://issues.dlang.org/show_bug.cgi?id=9378
111     else private version = USE_SSSE3;
112 }
113 else version (D_InlineAsm_X86_64)
114 {
115     private version = USE_SSSE3;
116 }
117 
118 }
119 
120 import core.bitop;
121 
122 public import std.digest;
123 
124 /*
125  * Helper methods for encoding the buffer.
126  * Can be removed if the optimizer can inline the methods from std.bitmanip.
127  */
128 version (LittleEndian)
129 {
130     private alias nativeToBigEndian = bswap;
131     private alias bigEndianToNative = bswap;
132 }
133 else pragma(inline, true) private pure @nogc nothrow @safe
134 {
135     uint nativeToBigEndian(uint val) { return val; }
136     ulong nativeToBigEndian(ulong val) { return val; }
137     alias bigEndianToNative = nativeToBigEndian;
138 }
139 
140 /**
141  * Template API SHA1/SHA2 implementation. Supports: SHA-1, SHA-224, SHA-256,
142  * SHA-384, SHA-512, SHA-512/224 and SHA-512/256.
143  *
144  * The hashBlockSize and digestSize are in bits. However, it's likely easier to
145  * simply use the convenience aliases: SHA1, SHA224, SHA256, SHA384, SHA512,
146  * SHA512_224 and SHA512_256.
147  *
148  * See `std.digest` for differences between template and OOP API.
149  */
150 struct SHA(uint hashBlockSize, uint digestSize)
151 {
152     enum blockSize = hashBlockSize;
153 
154     static assert(blockSize == 512 || blockSize == 1024,
155         "Invalid SHA blockSize, must be 512 or 1024");
156     static assert(digestSize == 160 || digestSize == 224 || digestSize == 256 || digestSize == 384 || digestSize == 512,
157         "Invalid SHA digestSize, must be 224, 256, 384 or 512");
158     static assert(!(blockSize == 512 && digestSize > 256),
159         "Invalid SHA digestSize for a blockSize of 512. The digestSize must be 160, 224 or 256.");
160     static assert(!(blockSize == 1024 && digestSize < 224),
161         "Invalid SHA digestSize for a blockSize of 1024. The digestSize must be 224, 256, 384 or 512.");
162 
163     static if (digestSize == 160) /* SHA-1 */
164     {
165         version (USE_SSSE3)
166         {
167             import core.cpuid : ssse3;
168             import std.internal.digest.sha_SSSE3 : sse3_constants=constants, transformSSSE3;
169 
170             static void transform(uint[5]* state, const(ubyte[64])* block) pure nothrow @nogc
171             {
172                 if (ssse3)
173                 {
174                     version (D_InlineAsm_X86_64)
175                         // constants as extra argument for PIC
176                         // see https://issues.dlang.org/show_bug.cgi?id=9378
177                         transformSSSE3(state, block, &sse3_constants);
178                     else
179                         transformSSSE3(state, block);
180                 }
181                 else
182                     transformX86(state, block);
183             }
184         }
185         else
186         {
187             alias transform = transformX86;
188         }
189     }
190     else static if (blockSize == 512) /* SHA-224, SHA-256 */
191         alias transform = transformSHA2!uint;
192     else static if (blockSize == 1024) /* SHA-384, SHA-512, SHA-512/224, SHA-512/256 */
193         alias transform = transformSHA2!ulong;
194     else
195         static assert(0);
196 
197     private:
198         /* magic initialization constants - state (ABCDEFGH) */
199         static if (blockSize == 512 && digestSize == 160) /* SHA-1 */
200         {
201             uint[5] state =
202             [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0];
203         }
204         else static if (blockSize == 512 && digestSize == 224) /* SHA-224 */
205         {
206             uint[8] state = [
207                 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
208                 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
209             ];
210         }
211         else static if (blockSize == 512 && digestSize == 256) /* SHA-256 */
212         {
213             uint[8] state = [
214                 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
215                 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
216             ];
217         }
218         else static if (blockSize == 1024 && digestSize == 224) /* SHA-512/224 */
219         {
220             ulong[8] state = [
221                 0x8C3D37C8_19544DA2, 0x73E19966_89DCD4D6,
222                 0x1DFAB7AE_32FF9C82, 0x679DD514_582F9FCF,
223                 0x0F6D2B69_7BD44DA8, 0x77E36F73_04C48942,
224                 0x3F9D85A8_6A1D36C8, 0x1112E6AD_91D692A1,
225             ];
226         }
227         else static if (blockSize == 1024 && digestSize == 256) /* SHA-512/256 */
228         {
229             ulong[8] state = [
230                 0x22312194_FC2BF72C, 0x9F555FA3_C84C64C2,
231                 0x2393B86B_6F53B151, 0x96387719_5940EABD,
232                 0x96283EE2_A88EFFE3, 0xBE5E1E25_53863992,
233                 0x2B0199FC_2C85B8AA, 0x0EB72DDC_81C52CA2,
234             ];
235         }
236         else static if (blockSize == 1024 && digestSize == 384) /* SHA-384 */
237         {
238             ulong[8] state = [
239                 0xcbbb9d5d_c1059ed8, 0x629a292a_367cd507,
240                 0x9159015a_3070dd17, 0x152fecd8_f70e5939,
241                 0x67332667_ffc00b31, 0x8eb44a87_68581511,
242                 0xdb0c2e0d_64f98fa7, 0x47b5481d_befa4fa4,
243             ];
244         }
245         else static if (blockSize == 1024 && digestSize == 512) /* SHA-512 */
246         {
247             ulong[8] state = [
248                 0x6a09e667_f3bcc908, 0xbb67ae85_84caa73b,
249                 0x3c6ef372_fe94f82b, 0xa54ff53a_5f1d36f1,
250                 0x510e527f_ade682d1, 0x9b05688c_2b3e6c1f,
251                 0x1f83d9ab_fb41bd6b, 0x5be0cd19_137e2179,
252             ];
253         }
254         else
255             static assert(0);
256 
257         /* constants */
258         static if (blockSize == 512)
259         {
260             static immutable uint[64] constants = [
261                 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
262                 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
263                 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
264                 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
265                 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
266                 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
267                 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
268                 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
269             ];
270         }
271         else static if (blockSize == 1024)
272         {
273             static immutable ulong[80] constants = [
274                 0x428a2f98_d728ae22, 0x71374491_23ef65cd, 0xb5c0fbcf_ec4d3b2f, 0xe9b5dba5_8189dbbc,
275                 0x3956c25b_f348b538, 0x59f111f1_b605d019, 0x923f82a4_af194f9b, 0xab1c5ed5_da6d8118,
276                 0xd807aa98_a3030242, 0x12835b01_45706fbe, 0x243185be_4ee4b28c, 0x550c7dc3_d5ffb4e2,
277                 0x72be5d74_f27b896f, 0x80deb1fe_3b1696b1, 0x9bdc06a7_25c71235, 0xc19bf174_cf692694,
278                 0xe49b69c1_9ef14ad2, 0xefbe4786_384f25e3, 0x0fc19dc6_8b8cd5b5, 0x240ca1cc_77ac9c65,
279                 0x2de92c6f_592b0275, 0x4a7484aa_6ea6e483, 0x5cb0a9dc_bd41fbd4, 0x76f988da_831153b5,
280                 0x983e5152_ee66dfab, 0xa831c66d_2db43210, 0xb00327c8_98fb213f, 0xbf597fc7_beef0ee4,
281                 0xc6e00bf3_3da88fc2, 0xd5a79147_930aa725, 0x06ca6351_e003826f, 0x14292967_0a0e6e70,
282                 0x27b70a85_46d22ffc, 0x2e1b2138_5c26c926, 0x4d2c6dfc_5ac42aed, 0x53380d13_9d95b3df,
283                 0x650a7354_8baf63de, 0x766a0abb_3c77b2a8, 0x81c2c92e_47edaee6, 0x92722c85_1482353b,
284                 0xa2bfe8a1_4cf10364, 0xa81a664b_bc423001, 0xc24b8b70_d0f89791, 0xc76c51a3_0654be30,
285                 0xd192e819_d6ef5218, 0xd6990624_5565a910, 0xf40e3585_5771202a, 0x106aa070_32bbd1b8,
286                 0x19a4c116_b8d2d0c8, 0x1e376c08_5141ab53, 0x2748774c_df8eeb99, 0x34b0bcb5_e19b48a8,
287                 0x391c0cb3_c5c95a63, 0x4ed8aa4a_e3418acb, 0x5b9cca4f_7763e373, 0x682e6ff3_d6b2b8a3,
288                 0x748f82ee_5defb2fc, 0x78a5636f_43172f60, 0x84c87814_a1f0ab72, 0x8cc70208_1a6439ec,
289                 0x90befffa_23631e28, 0xa4506ceb_de82bde9, 0xbef9a3f7_b2c67915, 0xc67178f2_e372532b,
290                 0xca273ece_ea26619c, 0xd186b8c7_21c0c207, 0xeada7dd6_cde0eb1e, 0xf57d4f7f_ee6ed178,
291                 0x06f067aa_72176fba, 0x0a637dc5_a2c898a6, 0x113f9804_bef90dae, 0x1b710b35_131c471b,
292                 0x28db77f5_23047d84, 0x32caab7b_40c72493, 0x3c9ebe0a_15c9bebc, 0x431d67c4_9c100d4c,
293                 0x4cc5d4be_cb3e42b6, 0x597f299c_fc657e2a, 0x5fcb6fab_3ad6faec, 0x6c44198c_4a475817,
294             ];
295         }
296         else
297             static assert(0);
298 
299         /*
300          * number of bits, modulo 2^64 (ulong[1]) or 2^128 (ulong[2]),
301          * should just use ucent instead of ulong[2] once it's available
302          */
303         ulong[blockSize/512] count;
304         ubyte[blockSize/8]   buffer; /* input buffer */
305 
306         static immutable ubyte[128] padding =
307         [
308           0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
309           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
310           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
311 
312           0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
313           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
314           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
315         ];
316 
317         /*
318          * Basic SHA1/SHA2 functions.
319          */
320         pragma(inline, true)
321         static @safe pure nothrow @nogc
322         {
323             /* All SHA1/SHA2 */
324             T Ch(T)(T x, T y, T z) { return z ^ (x & (y ^ z)); }
325             T Maj(T)(T x, T y, T z) { return (x & y) | (z & (x ^ y)); }
326 
327             /* SHA-1 */
328             uint Parity(uint x, uint y, uint z) { return x ^ y ^ z; }
329 
330             /* SHA-224, SHA-256 */
331             uint BigSigma0(uint x) { return core.bitop.ror(x, 2) ^ core.bitop.ror(x, 13) ^ core.bitop.ror(x, 22); }
332             uint BigSigma1(uint x) { return core.bitop.ror(x, 6) ^ core.bitop.ror(x, 11) ^ core.bitop.ror(x, 25); }
333             uint SmSigma0(uint x) { return core.bitop.ror(x, 7) ^ core.bitop.ror(x, 18) ^ x >> 3; }
334             uint SmSigma1(uint x) { return core.bitop.ror(x, 17) ^ core.bitop.ror(x, 19) ^ x >> 10; }
335 
336             /* SHA-384, SHA-512, SHA-512/224, SHA-512/256 */
337             ulong BigSigma0(ulong x) { return core.bitop.ror(x, 28) ^ core.bitop.ror(x, 34) ^ core.bitop.ror(x, 39); }
338             ulong BigSigma1(ulong x) { return core.bitop.ror(x, 14) ^ core.bitop.ror(x, 18) ^ core.bitop.ror(x, 41); }
339             ulong SmSigma0(ulong x) { return core.bitop.ror(x, 1) ^ core.bitop.ror(x, 8) ^ x >> 7; }
340             ulong SmSigma1(ulong x) { return core.bitop.ror(x, 19) ^ core.bitop.ror(x, 61) ^ x >> 6; }
341         }
342 
343         /*
344          * SHA1 basic transformation. Transforms state based on block.
345          */
346         static void T_0_15(int i, const(ubyte[64])* input, ref uint[16] W, uint A, ref uint B, uint C, uint D,
347             uint E, ref uint T) pure nothrow @nogc
348         {
349             uint Wi = W[i] = bigEndianToNative(*cast(uint*) &((*input)[i*4]));
350             T = Ch(B, C, D) + E + core.bitop.rol(A, 5) + Wi + 0x5a827999;
351             B = core.bitop.rol(B, 30);
352         }
353 
354         static void T_16_19(int i, ref uint[16] W, uint A, ref uint B, uint C, uint D, uint E, ref uint T)
355             pure nothrow @nogc
356         {
357             W[i&15] = core.bitop.rol(W[(i-3)&15] ^ W[(i-8)&15] ^ W[(i-14)&15] ^ W[(i-16)&15], 1);
358             T = Ch(B, C, D) + E + core.bitop.rol(A, 5) + W[i&15] + 0x5a827999;
359             B = core.bitop.rol(B, 30);
360         }
361 
362         static void T_20_39(int i, ref uint[16] W, uint A, ref uint B, uint C, uint D, uint E,
363             ref uint T) pure nothrow @nogc
364         {
365             W[i&15] = core.bitop.rol(W[(i-3)&15] ^ W[(i-8)&15] ^ W[(i-14)&15] ^ W[(i-16)&15], 1);
366             T = Parity(B, C, D) + E + core.bitop.rol(A, 5) + W[i&15] + 0x6ed9eba1;
367             B = core.bitop.rol(B, 30);
368         }
369 
370         static void T_40_59(int i, ref uint[16] W, uint A, ref uint B, uint C, uint D, uint E,
371             ref uint T) pure nothrow @nogc
372         {
373             W[i&15] = core.bitop.rol(W[(i-3)&15] ^ W[(i-8)&15] ^ W[(i-14)&15] ^ W[(i-16)&15], 1);
374             T = Maj(B, C, D) + E + core.bitop.rol(A, 5) + W[i&15] + 0x8f1bbcdc;
375             B = core.bitop.rol(B, 30);
376         }
377 
378         static void T_60_79(int i, ref uint[16] W, uint A, ref uint B, uint C, uint D, uint E,
379             ref uint T) pure nothrow @nogc
380         {
381             W[i&15] = core.bitop.rol(W[(i-3)&15] ^ W[(i-8)&15] ^ W[(i-14)&15] ^ W[(i-16)&15], 1);
382             T = Parity(B, C, D) + E + core.bitop.rol(A, 5) + W[i&15] + 0xca62c1d6;
383             B = core.bitop.rol(B, 30);
384         }
385 
386         private static void transformX86(uint[5]* state, const(ubyte[64])* block) pure nothrow @nogc
387         {
388             uint A, B, C, D, E, T;
389             uint[16] W = void;
390 
391             A = (*state)[0];
392             B = (*state)[1];
393             C = (*state)[2];
394             D = (*state)[3];
395             E = (*state)[4];
396 
397             T_0_15 ( 0, block, W, A, B, C, D, E, T);
398             T_0_15 ( 1, block, W, T, A, B, C, D, E);
399             T_0_15 ( 2, block, W, E, T, A, B, C, D);
400             T_0_15 ( 3, block, W, D, E, T, A, B, C);
401             T_0_15 ( 4, block, W, C, D, E, T, A, B);
402             T_0_15 ( 5, block, W, B, C, D, E, T, A);
403             T_0_15 ( 6, block, W, A, B, C, D, E, T);
404             T_0_15 ( 7, block, W, T, A, B, C, D, E);
405             T_0_15 ( 8, block, W, E, T, A, B, C, D);
406             T_0_15 ( 9, block, W, D, E, T, A, B, C);
407             T_0_15 (10, block, W, C, D, E, T, A, B);
408             T_0_15 (11, block, W, B, C, D, E, T, A);
409             T_0_15 (12, block, W, A, B, C, D, E, T);
410             T_0_15 (13, block, W, T, A, B, C, D, E);
411             T_0_15 (14, block, W, E, T, A, B, C, D);
412             T_0_15 (15, block, W, D, E, T, A, B, C);
413             T_16_19(16, W, C, D, E, T, A, B);
414             T_16_19(17, W, B, C, D, E, T, A);
415             T_16_19(18, W, A, B, C, D, E, T);
416             T_16_19(19, W, T, A, B, C, D, E);
417             T_20_39(20, W, E, T, A, B, C, D);
418             T_20_39(21, W, D, E, T, A, B, C);
419             T_20_39(22, W, C, D, E, T, A, B);
420             T_20_39(23, W, B, C, D, E, T, A);
421             T_20_39(24, W, A, B, C, D, E, T);
422             T_20_39(25, W, T, A, B, C, D, E);
423             T_20_39(26, W, E, T, A, B, C, D);
424             T_20_39(27, W, D, E, T, A, B, C);
425             T_20_39(28, W, C, D, E, T, A, B);
426             T_20_39(29, W, B, C, D, E, T, A);
427             T_20_39(30, W, A, B, C, D, E, T);
428             T_20_39(31, W, T, A, B, C, D, E);
429             T_20_39(32, W, E, T, A, B, C, D);
430             T_20_39(33, W, D, E, T, A, B, C);
431             T_20_39(34, W, C, D, E, T, A, B);
432             T_20_39(35, W, B, C, D, E, T, A);
433             T_20_39(36, W, A, B, C, D, E, T);
434             T_20_39(37, W, T, A, B, C, D, E);
435             T_20_39(38, W, E, T, A, B, C, D);
436             T_20_39(39, W, D, E, T, A, B, C);
437             T_40_59(40, W, C, D, E, T, A, B);
438             T_40_59(41, W, B, C, D, E, T, A);
439             T_40_59(42, W, A, B, C, D, E, T);
440             T_40_59(43, W, T, A, B, C, D, E);
441             T_40_59(44, W, E, T, A, B, C, D);
442             T_40_59(45, W, D, E, T, A, B, C);
443             T_40_59(46, W, C, D, E, T, A, B);
444             T_40_59(47, W, B, C, D, E, T, A);
445             T_40_59(48, W, A, B, C, D, E, T);
446             T_40_59(49, W, T, A, B, C, D, E);
447             T_40_59(50, W, E, T, A, B, C, D);
448             T_40_59(51, W, D, E, T, A, B, C);
449             T_40_59(52, W, C, D, E, T, A, B);
450             T_40_59(53, W, B, C, D, E, T, A);
451             T_40_59(54, W, A, B, C, D, E, T);
452             T_40_59(55, W, T, A, B, C, D, E);
453             T_40_59(56, W, E, T, A, B, C, D);
454             T_40_59(57, W, D, E, T, A, B, C);
455             T_40_59(58, W, C, D, E, T, A, B);
456             T_40_59(59, W, B, C, D, E, T, A);
457             T_60_79(60, W, A, B, C, D, E, T);
458             T_60_79(61, W, T, A, B, C, D, E);
459             T_60_79(62, W, E, T, A, B, C, D);
460             T_60_79(63, W, D, E, T, A, B, C);
461             T_60_79(64, W, C, D, E, T, A, B);
462             T_60_79(65, W, B, C, D, E, T, A);
463             T_60_79(66, W, A, B, C, D, E, T);
464             T_60_79(67, W, T, A, B, C, D, E);
465             T_60_79(68, W, E, T, A, B, C, D);
466             T_60_79(69, W, D, E, T, A, B, C);
467             T_60_79(70, W, C, D, E, T, A, B);
468             T_60_79(71, W, B, C, D, E, T, A);
469             T_60_79(72, W, A, B, C, D, E, T);
470             T_60_79(73, W, T, A, B, C, D, E);
471             T_60_79(74, W, E, T, A, B, C, D);
472             T_60_79(75, W, D, E, T, A, B, C);
473             T_60_79(76, W, C, D, E, T, A, B);
474             T_60_79(77, W, B, C, D, E, T, A);
475             T_60_79(78, W, A, B, C, D, E, T);
476             T_60_79(79, W, T, A, B, C, D, E);
477 
478             (*state)[0] += E;
479             (*state)[1] += T;
480             (*state)[2] += A;
481             (*state)[3] += B;
482             (*state)[4] += C;
483 
484             /* Zeroize sensitive information. */
485             W[] = 0;
486         }
487 
488         /*
489          * SHA2 basic transformation. Transforms state based on block.
490          */
491         pragma(inline, true)
492         static void T_SHA2_0_15(Word)(int i, const(ubyte[blockSize/8])* input, ref Word[16] W,
493             Word A, Word B, Word C, ref Word D, Word E, Word F, Word G, ref Word H, Word K)
494             pure nothrow @nogc
495         {
496             Word Wi = W[i] = bigEndianToNative(*cast(Word*) &((*input)[i*Word.sizeof]));
497             Word T1 = H + BigSigma1(E) + Ch(E, F, G) + K + Wi;
498             Word T2 = BigSigma0(A) + Maj(A, B, C);
499             D += T1;
500             H = T1 + T2;
501         }
502 
503         // Temporarily disable inlining because it increases build speed by 10x.
504         // pragma(inline, true)
505         static void T_SHA2_16_79(Word)(int i, ref Word[16] W,
506             Word A, Word B, Word C, ref Word D, Word E, Word F, Word G, ref Word H, Word K)
507             pure nothrow @nogc
508         {
509             W[i&15] = SmSigma1(W[(i-2)&15]) + W[(i-7)&15] + SmSigma0(W[(i-15)&15]) + W[i&15];
510             Word T1 = H + BigSigma1(E) + Ch(E, F, G) + K + W[i&15];
511             Word T2 = BigSigma0(A) + Maj(A, B, C);
512             D += T1;
513             H = T1 + T2;
514         }
515 
516         private static void transformSHA2(Word)(Word[8]* state, const(ubyte[blockSize/8])* block)
517             pure nothrow @nogc
518         {
519             Word A, B, C, D, E, F, G, H;
520             Word[16] W = void;
521 
522             A = (*state)[0];
523             B = (*state)[1];
524             C = (*state)[2];
525             D = (*state)[3];
526             E = (*state)[4];
527             F = (*state)[5];
528             G = (*state)[6];
529             H = (*state)[7];
530 
531             T_SHA2_0_15!Word ( 0, block, W, A, B, C, D, E, F, G, H, constants[ 0]);
532             T_SHA2_0_15!Word ( 1, block, W, H, A, B, C, D, E, F, G, constants[ 1]);
533             T_SHA2_0_15!Word ( 2, block, W, G, H, A, B, C, D, E, F, constants[ 2]);
534             T_SHA2_0_15!Word ( 3, block, W, F, G, H, A, B, C, D, E, constants[ 3]);
535             T_SHA2_0_15!Word ( 4, block, W, E, F, G, H, A, B, C, D, constants[ 4]);
536             T_SHA2_0_15!Word ( 5, block, W, D, E, F, G, H, A, B, C, constants[ 5]);
537             T_SHA2_0_15!Word ( 6, block, W, C, D, E, F, G, H, A, B, constants[ 6]);
538             T_SHA2_0_15!Word ( 7, block, W, B, C, D, E, F, G, H, A, constants[ 7]);
539             T_SHA2_0_15!Word ( 8, block, W, A, B, C, D, E, F, G, H, constants[ 8]);
540             T_SHA2_0_15!Word ( 9, block, W, H, A, B, C, D, E, F, G, constants[ 9]);
541             T_SHA2_0_15!Word (10, block, W, G, H, A, B, C, D, E, F, constants[10]);
542             T_SHA2_0_15!Word (11, block, W, F, G, H, A, B, C, D, E, constants[11]);
543             T_SHA2_0_15!Word (12, block, W, E, F, G, H, A, B, C, D, constants[12]);
544             T_SHA2_0_15!Word (13, block, W, D, E, F, G, H, A, B, C, constants[13]);
545             T_SHA2_0_15!Word (14, block, W, C, D, E, F, G, H, A, B, constants[14]);
546             T_SHA2_0_15!Word (15, block, W, B, C, D, E, F, G, H, A, constants[15]);
547             T_SHA2_16_79!Word(16, W, A, B, C, D, E, F, G, H, constants[16]);
548             T_SHA2_16_79!Word(17, W, H, A, B, C, D, E, F, G, constants[17]);
549             T_SHA2_16_79!Word(18, W, G, H, A, B, C, D, E, F, constants[18]);
550             T_SHA2_16_79!Word(19, W, F, G, H, A, B, C, D, E, constants[19]);
551             T_SHA2_16_79!Word(20, W, E, F, G, H, A, B, C, D, constants[20]);
552             T_SHA2_16_79!Word(21, W, D, E, F, G, H, A, B, C, constants[21]);
553             T_SHA2_16_79!Word(22, W, C, D, E, F, G, H, A, B, constants[22]);
554             T_SHA2_16_79!Word(23, W, B, C, D, E, F, G, H, A, constants[23]);
555             T_SHA2_16_79!Word(24, W, A, B, C, D, E, F, G, H, constants[24]);
556             T_SHA2_16_79!Word(25, W, H, A, B, C, D, E, F, G, constants[25]);
557             T_SHA2_16_79!Word(26, W, G, H, A, B, C, D, E, F, constants[26]);
558             T_SHA2_16_79!Word(27, W, F, G, H, A, B, C, D, E, constants[27]);
559             T_SHA2_16_79!Word(28, W, E, F, G, H, A, B, C, D, constants[28]);
560             T_SHA2_16_79!Word(29, W, D, E, F, G, H, A, B, C, constants[29]);
561             T_SHA2_16_79!Word(30, W, C, D, E, F, G, H, A, B, constants[30]);
562             T_SHA2_16_79!Word(31, W, B, C, D, E, F, G, H, A, constants[31]);
563             T_SHA2_16_79!Word(32, W, A, B, C, D, E, F, G, H, constants[32]);
564             T_SHA2_16_79!Word(33, W, H, A, B, C, D, E, F, G, constants[33]);
565             T_SHA2_16_79!Word(34, W, G, H, A, B, C, D, E, F, constants[34]);
566             T_SHA2_16_79!Word(35, W, F, G, H, A, B, C, D, E, constants[35]);
567             T_SHA2_16_79!Word(36, W, E, F, G, H, A, B, C, D, constants[36]);
568             T_SHA2_16_79!Word(37, W, D, E, F, G, H, A, B, C, constants[37]);
569             T_SHA2_16_79!Word(38, W, C, D, E, F, G, H, A, B, constants[38]);
570             T_SHA2_16_79!Word(39, W, B, C, D, E, F, G, H, A, constants[39]);
571             T_SHA2_16_79!Word(40, W, A, B, C, D, E, F, G, H, constants[40]);
572             T_SHA2_16_79!Word(41, W, H, A, B, C, D, E, F, G, constants[41]);
573             T_SHA2_16_79!Word(42, W, G, H, A, B, C, D, E, F, constants[42]);
574             T_SHA2_16_79!Word(43, W, F, G, H, A, B, C, D, E, constants[43]);
575             T_SHA2_16_79!Word(44, W, E, F, G, H, A, B, C, D, constants[44]);
576             T_SHA2_16_79!Word(45, W, D, E, F, G, H, A, B, C, constants[45]);
577             T_SHA2_16_79!Word(46, W, C, D, E, F, G, H, A, B, constants[46]);
578             T_SHA2_16_79!Word(47, W, B, C, D, E, F, G, H, A, constants[47]);
579             T_SHA2_16_79!Word(48, W, A, B, C, D, E, F, G, H, constants[48]);
580             T_SHA2_16_79!Word(49, W, H, A, B, C, D, E, F, G, constants[49]);
581             T_SHA2_16_79!Word(50, W, G, H, A, B, C, D, E, F, constants[50]);
582             T_SHA2_16_79!Word(51, W, F, G, H, A, B, C, D, E, constants[51]);
583             T_SHA2_16_79!Word(52, W, E, F, G, H, A, B, C, D, constants[52]);
584             T_SHA2_16_79!Word(53, W, D, E, F, G, H, A, B, C, constants[53]);
585             T_SHA2_16_79!Word(54, W, C, D, E, F, G, H, A, B, constants[54]);
586             T_SHA2_16_79!Word(55, W, B, C, D, E, F, G, H, A, constants[55]);
587             T_SHA2_16_79!Word(56, W, A, B, C, D, E, F, G, H, constants[56]);
588             T_SHA2_16_79!Word(57, W, H, A, B, C, D, E, F, G, constants[57]);
589             T_SHA2_16_79!Word(58, W, G, H, A, B, C, D, E, F, constants[58]);
590             T_SHA2_16_79!Word(59, W, F, G, H, A, B, C, D, E, constants[59]);
591             T_SHA2_16_79!Word(60, W, E, F, G, H, A, B, C, D, constants[60]);
592             T_SHA2_16_79!Word(61, W, D, E, F, G, H, A, B, C, constants[61]);
593             T_SHA2_16_79!Word(62, W, C, D, E, F, G, H, A, B, constants[62]);
594             T_SHA2_16_79!Word(63, W, B, C, D, E, F, G, H, A, constants[63]);
595 
596             static if (is(Word == ulong))
597             {
598                 T_SHA2_16_79!Word(64, W, A, B, C, D, E, F, G, H, constants[64]);
599                 T_SHA2_16_79!Word(65, W, H, A, B, C, D, E, F, G, constants[65]);
600                 T_SHA2_16_79!Word(66, W, G, H, A, B, C, D, E, F, constants[66]);
601                 T_SHA2_16_79!Word(67, W, F, G, H, A, B, C, D, E, constants[67]);
602                 T_SHA2_16_79!Word(68, W, E, F, G, H, A, B, C, D, constants[68]);
603                 T_SHA2_16_79!Word(69, W, D, E, F, G, H, A, B, C, constants[69]);
604                 T_SHA2_16_79!Word(70, W, C, D, E, F, G, H, A, B, constants[70]);
605                 T_SHA2_16_79!Word(71, W, B, C, D, E, F, G, H, A, constants[71]);
606                 T_SHA2_16_79!Word(72, W, A, B, C, D, E, F, G, H, constants[72]);
607                 T_SHA2_16_79!Word(73, W, H, A, B, C, D, E, F, G, constants[73]);
608                 T_SHA2_16_79!Word(74, W, G, H, A, B, C, D, E, F, constants[74]);
609                 T_SHA2_16_79!Word(75, W, F, G, H, A, B, C, D, E, constants[75]);
610                 T_SHA2_16_79!Word(76, W, E, F, G, H, A, B, C, D, constants[76]);
611                 T_SHA2_16_79!Word(77, W, D, E, F, G, H, A, B, C, constants[77]);
612                 T_SHA2_16_79!Word(78, W, C, D, E, F, G, H, A, B, constants[78]);
613                 T_SHA2_16_79!Word(79, W, B, C, D, E, F, G, H, A, constants[79]);
614             }
615 
616             (*state)[0] += A;
617             (*state)[1] += B;
618             (*state)[2] += C;
619             (*state)[3] += D;
620             (*state)[4] += E;
621             (*state)[5] += F;
622             (*state)[6] += G;
623             (*state)[7] += H;
624 
625             /* Zeroize sensitive information. */
626             W[] = 0;
627         }
628 
629     public:
630         /**
631          * SHA initialization. Begins an SHA1/SHA2 operation.
632          *
633          * Note:
634          * For this SHA Digest implementation calling start after default construction
635          * is not necessary. Calling start is only necessary to reset the Digest.
636          *
637          * Generic code which deals with different Digest types should always call start though.
638          *
639          * Example:
640          * --------
641          * SHA1 digest;
642          * //digest.start(); //Not necessary
643          * digest.put(0);
644          * --------
645          */
646         void start() @safe pure nothrow @nogc
647         {
648             this = typeof(this).init;
649         }
650 
651         /**
652          * Use this to feed the digest with data.
653          * Also implements the $(REF isOutputRange, std,range,primitives)
654          * interface for `ubyte` and `const(ubyte)[]`.
655          */
656         void put(scope const(ubyte)[] input...) @trusted pure nothrow @nogc
657         {
658             enum blockSizeInBytes = blockSize/8;
659 
660             size_t i;
661             uint index, partLen;
662             auto inputLen = input.length;
663 
664             /* Compute number of bytes mod block size (64 or 128 bytes) */
665             index = (cast(uint) count[0] >> 3) & (blockSizeInBytes - 1);
666 
667             /* Update number of bits */
668             static if (blockSize == 512)
669                 count[0] += inputLen * 8;
670             else static if (blockSize == 1024)
671             {
672                 /* ugly hack to work around lack of ucent */
673                 auto oldCount0 = count[0];
674                 count[0] += inputLen * 8;
675                 if (count[0] < oldCount0)
676                     count[1]++;
677             }
678             else
679                 static assert(0);
680 
681             partLen = blockSizeInBytes - index;
682 
683             /* Transform as many times as possible. */
684             if (inputLen >= partLen)
685             {
686                 (&buffer[index])[0 .. partLen] = input.ptr[0 .. partLen];
687                 transform (&state, &buffer);
688 
689                 for (i = partLen; i + blockSizeInBytes-1 < inputLen; i += blockSizeInBytes)
690                    transform(&state, cast(ubyte[blockSizeInBytes]*)(input.ptr + i));
691 
692                 index = 0;
693             }
694             else
695                 i = 0;
696 
697             /* Buffer remaining input */
698             if (inputLen - i)
699                 (&buffer[index])[0 .. inputLen-i] = (&input[i])[0 .. inputLen-i];
700         }
701 
702         @safe unittest
703         {
704             typeof(this) dig;
705             dig.put(cast(ubyte) 0); //single ubyte
706             dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
707             ubyte[10] buf;
708             dig.put(buf); //buffer
709         }
710 
711 
712         /**
713          * Returns the finished SHA hash. This also calls $(LREF start) to
714          * reset the internal state.
715          */
716         ubyte[digestSize/8] finish() @trusted pure nothrow @nogc
717         {
718             static if (blockSize == 512)
719             {
720                 uint[8] data = void;
721                 uint index, padLen;
722 
723                 /* Save number of bits */
724                 ulong bits = nativeToBigEndian(count[0]);
725 
726                 /* Pad out to 56 mod 64. */
727                 index = (cast(uint) count[0] >> 3) & (64 - 1);
728                 padLen = (index < 56) ? (56 - index) : (120 - index);
729                 put(padding[0 .. padLen]);
730 
731                 /* Append length (before padding) */
732                 put((cast(ubyte*) &bits)[0 .. bits.sizeof]);
733 
734                 /* Store state in digest */
735                 static foreach (i; 0 .. (digestSize == 160) ? 5 : 8)
736                     data[i] = nativeToBigEndian(state[i]);
737 
738                 /* Zeroize sensitive information. */
739                 start();
740                 return (cast(ubyte*) data.ptr)[0 .. digestSize/8];
741             }
742             else static if (blockSize == 1024)
743             {
744                 ulong[8] data = void;
745                 uint index, padLen;
746 
747                 /* Save number of bits */
748                 ulong[2] bits = [nativeToBigEndian(count[1]), nativeToBigEndian(count[0])];
749 
750                 /* Pad out to 112 mod 128. */
751                 index = (cast(uint) count[0] >> 3) & (128 - 1);
752                 padLen = (index < 112) ? (112 - index) : (240 - index);
753                 put(padding[0 .. padLen]);
754 
755                 /* Append length (before padding) */
756                 put((cast(ubyte*) &bits)[0 .. bits.sizeof]);
757 
758                 /* Store state in digest */
759                 static foreach (i; 0 .. 8)
760                     data[i] = nativeToBigEndian(state[i]);
761 
762                 /* Zeroize sensitive information. */
763                 start();
764                 return (cast(ubyte*) data.ptr)[0 .. digestSize/8];
765             }
766             else
767                 static assert(0);
768         }
769         ///
770         @safe unittest
771         {
772             //Simple example
773             SHA1 hash;
774             hash.start();
775             hash.put(cast(ubyte) 0);
776             ubyte[20] result = hash.finish();
777         }
778 }
779 
780 ///
781 @safe unittest
782 {
783     //Simple example, hashing a string using sha1Of helper function
784     ubyte[20] hash = sha1Of("abc");
785     //Let's get a hash string
786     assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
787 
788     //The same, but using SHA-224
789     ubyte[28] hash224 = sha224Of("abc");
790     assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
791 }
792 
793 ///
794 @safe unittest
795 {
796     //Using the basic API
797     SHA1 hash;
798     hash.start();
799     ubyte[1024] data;
800     //Initialize data here...
801     hash.put(data);
802     ubyte[20] result = hash.finish();
803 }
804 
805 ///
806 @safe unittest
807 {
808     //Let's use the template features:
809     //Note: When passing a SHA1 to a function, it must be passed by reference!
810     void doSomething(T)(ref T hash)
811     if (isDigest!T)
812     {
813       hash.put(cast(ubyte) 0);
814     }
815     SHA1 sha;
816     sha.start();
817     doSomething(sha);
818     assert(toHexString(sha.finish()) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F");
819 }
820 
821 alias SHA1 = SHA!(512, 160);  /// SHA alias for SHA-1, hash is ubyte[20]
822 alias SHA224 = SHA!(512, 224);  /// SHA alias for SHA-224, hash is ubyte[28]
823 alias SHA256 = SHA!(512, 256);  /// SHA alias for SHA-256, hash is ubyte[32]
824 alias SHA384 = SHA!(1024, 384); /// SHA alias for SHA-384, hash is ubyte[48]
825 alias SHA512 = SHA!(1024, 512); /// SHA alias for SHA-512, hash is ubyte[64]
826 alias SHA512_224 = SHA!(1024, 224); /// SHA alias for SHA-512/224, hash is ubyte[28]
827 alias SHA512_256 = SHA!(1024, 256); /// SHA alias for SHA-512/256, hash is ubyte[32]
828 
829 @safe unittest
830 {
831     assert(isDigest!SHA1);
832     assert(isDigest!SHA224);
833     assert(isDigest!SHA256);
834     assert(isDigest!SHA384);
835     assert(isDigest!SHA512);
836     assert(isDigest!SHA512_224);
837     assert(isDigest!SHA512_256);
838 }
839 
840 @system unittest
841 {
842     import std.conv : hexString;
843     import std.range;
844 
845     ubyte[20] digest;
846     ubyte[28] digest224;
847     ubyte[32] digest256;
848     ubyte[48] digest384;
849     ubyte[64] digest512;
850     ubyte[28] digest512_224;
851     ubyte[32] digest512_256;
852 
853     SHA1 sha;
854     sha.put(cast(ubyte[])"abcdef");
855     sha.start();
856     sha.put(cast(ubyte[])"");
857     assert(sha.finish() == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
858 
859     SHA224 sha224;
860     sha224.put(cast(ubyte[])"abcdef");
861     sha224.start();
862     sha224.put(cast(ubyte[])"");
863     assert(sha224.finish() == cast(ubyte[]) hexString!"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
864 
865     SHA256 sha256;
866     sha256.put(cast(ubyte[])"abcdef");
867     sha256.start();
868     sha256.put(cast(ubyte[])"");
869     assert(sha256.finish() == cast(ubyte[])
870             hexString!"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
871 
872     SHA384 sha384;
873     sha384.put(cast(ubyte[])"abcdef");
874     sha384.start();
875     sha384.put(cast(ubyte[])"");
876     assert(sha384.finish() == cast(ubyte[]) hexString!("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c"
877         ~"0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"));
878 
879     SHA512 sha512;
880     sha512.put(cast(ubyte[])"abcdef");
881     sha512.start();
882     sha512.put(cast(ubyte[])"");
883     assert(sha512.finish() == cast(ubyte[])
884             hexString!("cf83e1357eefb8bdf1542850d66d8007d620e4050b571"
885         ~"5dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"));
886 
887     SHA512_224 sha512_224;
888     sha512_224.put(cast(ubyte[])"abcdef");
889     sha512_224.start();
890     sha512_224.put(cast(ubyte[])"");
891     assert(sha512_224.finish() == cast(ubyte[]) hexString!"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
892 
893     SHA512_256 sha512_256;
894     sha512_256.put(cast(ubyte[])"abcdef");
895     sha512_256.start();
896     sha512_256.put(cast(ubyte[])"");
897     assert(sha512_256.finish() == cast(ubyte[])
898             hexString!"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
899 
900     digest        = sha1Of      ("");
901     digest224     = sha224Of    ("");
902     digest256     = sha256Of    ("");
903     digest384     = sha384Of    ("");
904     digest512     = sha512Of    ("");
905     digest512_224 = sha512_224Of("");
906     digest512_256 = sha512_256Of("");
907     assert(digest == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
908     assert(digest224 == cast(ubyte[]) hexString!"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
909     assert(digest256 == cast(ubyte[]) hexString!"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
910     assert(digest384 == cast(ubyte[]) hexString!("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c"
911         ~"0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"));
912     assert(digest512 == cast(ubyte[]) hexString!("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83"
913         ~"f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"));
914     assert(digest512_224 == cast(ubyte[]) hexString!"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
915     assert(digest512_256 == cast(ubyte[]) hexString!"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
916 
917     digest        = sha1Of      ("a");
918     digest224     = sha224Of    ("a");
919     digest256     = sha256Of    ("a");
920     digest384     = sha384Of    ("a");
921     digest512     = sha512Of    ("a");
922     digest512_224 = sha512_224Of("a");
923     digest512_256 = sha512_256Of("a");
924     assert(digest == cast(ubyte[]) hexString!"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
925     assert(digest224 == cast(ubyte[]) hexString!"abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5");
926     assert(digest256 == cast(ubyte[]) hexString!"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb");
927     assert(digest384 == cast(ubyte[]) hexString!("54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9"
928         ~"cd697e85175033caa88e6d57bc35efae0b5afd3145f31"));
929     assert(digest512 == cast(ubyte[]) hexString!("1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05ab"
930         ~"c54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"));
931     assert(digest512_224 == cast(ubyte[]) hexString!"d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327");
932     assert(digest512_256 == cast(ubyte[]) hexString!"455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8");
933 
934     digest        = sha1Of      ("abc");
935     digest224     = sha224Of    ("abc");
936     digest256     = sha256Of    ("abc");
937     digest384     = sha384Of    ("abc");
938     digest512     = sha512Of    ("abc");
939     digest512_224 = sha512_224Of("abc");
940     digest512_256 = sha512_256Of("abc");
941     assert(digest == cast(ubyte[]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d");
942     assert(digest224 == cast(ubyte[]) hexString!"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7");
943     assert(digest256 == cast(ubyte[]) hexString!"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
944     assert(digest384 == cast(ubyte[]) hexString!("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a"
945         ~"8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"));
946     assert(digest512 == cast(ubyte[]) hexString!("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9"
947         ~"eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"));
948     assert(digest512_224 == cast(ubyte[]) hexString!"4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa");
949     assert(digest512_256 == cast(ubyte[]) hexString!"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23");
950 
951     digest        = sha1Of      ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
952     digest224     = sha224Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
953     digest256     = sha256Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
954     digest384     = sha384Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
955     digest512     = sha512Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
956     digest512_224 = sha512_224Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
957     digest512_256 = sha512_256Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
958     assert(digest == cast(ubyte[]) hexString!"84983e441c3bd26ebaae4aa1f95129e5e54670f1");
959     assert(digest224 == cast(ubyte[]) hexString!"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525");
960     assert(digest256 == cast(ubyte[]) hexString!"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
961     assert(digest384 == cast(ubyte[]) hexString!("3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe"
962         ~"8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b"));
963     assert(digest512 == cast(ubyte[]) hexString!("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a827"
964         ~"9be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"));
965     assert(digest512_224 == cast(ubyte[]) hexString!"e5302d6d54bb242275d1e7622d68df6eb02dedd13f564c13dbda2174");
966     assert(digest512_256 == cast(ubyte[]) hexString!"bde8e1f9f19bb9fd3406c90ec6bc47bd36d8ada9f11880dbc8a22a7078b6a461");
967 
968     digest        = sha1Of      ("message digest");
969     digest224     = sha224Of    ("message digest");
970     digest256     = sha256Of    ("message digest");
971     digest384     = sha384Of    ("message digest");
972     digest512     = sha512Of    ("message digest");
973     digest512_224 = sha512_224Of("message digest");
974     digest512_256 = sha512_256Of("message digest");
975     assert(digest == cast(ubyte[]) hexString!"c12252ceda8be8994d5fa0290a47231c1d16aae3");
976     assert(digest224 == cast(ubyte[]) hexString!"2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb");
977     assert(digest256 == cast(ubyte[]) hexString!"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
978     assert(digest384 == cast(ubyte[]) hexString!("473ed35167ec1f5d8e550368a3db39be54639f828868e9454c"
979         ~"239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5"));
980     assert(digest512 == cast(ubyte[]) hexString!("107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c134"
981         ~"92ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c"));
982     assert(digest512_224 == cast(ubyte[]) hexString!"ad1a4db188fe57064f4f24609d2a83cd0afb9b398eb2fcaeaae2c564");
983     assert(digest512_256 == cast(ubyte[]) hexString!"0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb");
984 
985     digest        = sha1Of      ("abcdefghijklmnopqrstuvwxyz");
986     digest224     = sha224Of    ("abcdefghijklmnopqrstuvwxyz");
987     digest256     = sha256Of    ("abcdefghijklmnopqrstuvwxyz");
988     digest384     = sha384Of    ("abcdefghijklmnopqrstuvwxyz");
989     digest512     = sha512Of    ("abcdefghijklmnopqrstuvwxyz");
990     digest512_224 = sha512_224Of("abcdefghijklmnopqrstuvwxyz");
991     digest512_256 = sha512_256Of("abcdefghijklmnopqrstuvwxyz");
992     assert(digest == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
993     assert(digest224 == cast(ubyte[]) hexString!"45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2");
994     assert(digest256 == cast(ubyte[]) hexString!"71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73");
995     assert(digest384 == cast(ubyte[]) hexString!("feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5"
996         ~"f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4"));
997     assert(digest512 == cast(ubyte[]) hexString!("4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034"
998         ~"898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1"));
999     assert(digest512_224 == cast(ubyte[]) hexString!"ff83148aa07ec30655c1b40aff86141c0215fe2a54f767d3f38743d8");
1000     assert(digest512_256 == cast(ubyte[]) hexString!"fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26");
1001 
1002     digest        = sha1Of      ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1003     digest224     = sha224Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1004     digest256     = sha256Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1005     digest384     = sha384Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1006     digest512     = sha512Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1007     digest512_224 = sha512_224Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1008     digest512_256 = sha512_256Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1009     assert(digest == cast(ubyte[]) hexString!"761c457bf73b14d27e9e9265c46f4b4dda11f940");
1010     assert(digest224 == cast(ubyte[]) hexString!"bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9");
1011     assert(digest256 == cast(ubyte[]) hexString!"db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0");
1012     assert(digest384 == cast(ubyte[]) hexString!("1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039"
1013         ~"c1464ee8732f11a5341a6f41e0c202294736ed64db1a84"));
1014     assert(digest512 == cast(ubyte[]) hexString!("1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f"
1015         ~"536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894"));
1016     assert(digest512_224 == cast(ubyte[]) hexString!"a8b4b9174b99ffc67d6f49be9981587b96441051e16e6dd036b140d3");
1017     assert(digest512_256 == cast(ubyte[]) hexString!"cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8");
1018 
1019     digest        = sha1Of      ("1234567890123456789012345678901234567890"~
1020                                  "1234567890123456789012345678901234567890");
1021     digest224     = sha224Of    ("1234567890123456789012345678901234567890"~
1022                                  "1234567890123456789012345678901234567890");
1023     digest256     = sha256Of    ("1234567890123456789012345678901234567890"~
1024                                  "1234567890123456789012345678901234567890");
1025     digest384     = sha384Of    ("1234567890123456789012345678901234567890"~
1026                                  "1234567890123456789012345678901234567890");
1027     digest512     = sha512Of    ("1234567890123456789012345678901234567890"~
1028                                  "1234567890123456789012345678901234567890");
1029     digest512_224 = sha512_224Of("1234567890123456789012345678901234567890"~
1030                                  "1234567890123456789012345678901234567890");
1031     digest512_256 = sha512_256Of("1234567890123456789012345678901234567890"~
1032                                  "1234567890123456789012345678901234567890");
1033     assert(digest == cast(ubyte[]) hexString!"50abf5706a150990a08b2c5ea40fa0e585554732");
1034     assert(digest224 == cast(ubyte[]) hexString!"b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e");
1035     assert(digest256 == cast(ubyte[]) hexString!"f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e");
1036     assert(digest384 == cast(ubyte[]) hexString!("b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b"
1037         ~"9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026"));
1038     assert(digest512 == cast(ubyte[]) hexString!("72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d191"
1039         ~"4042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843"));
1040     assert(digest512_224 == cast(ubyte[]) hexString!"ae988faaa47e401a45f704d1272d99702458fea2ddc6582827556dd2");
1041     assert(digest512_256 == cast(ubyte[]) hexString!"2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148");
1042 
1043     ubyte[] onemilliona = new ubyte[1000000];
1044     onemilliona[] = 'a';
1045     digest = sha1Of(onemilliona);
1046     digest224 = sha224Of(onemilliona);
1047     digest256 = sha256Of(onemilliona);
1048     digest384 = sha384Of(onemilliona);
1049     digest512 = sha512Of(onemilliona);
1050     digest512_224 = sha512_224Of(onemilliona);
1051     digest512_256 = sha512_256Of(onemilliona);
1052     assert(digest == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1053     assert(digest224 == cast(ubyte[]) hexString!"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
1054     assert(digest256 == cast(ubyte[]) hexString!"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
1055     assert(digest384 == cast(ubyte[]) hexString!("9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279"
1056         ~"72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"));
1057     assert(digest512 == cast(ubyte[]) hexString!("e718483d0ce769644e2e42c7bc15b4638e1f98b13b20442856"
1058         ~"32a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"));
1059     assert(digest512_224 == cast(ubyte[]) hexString!"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
1060     assert(digest512_256 == cast(ubyte[]) hexString!"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
1061 
1062     auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
1063     digest = sha1Of(oneMillionRange);
1064     digest224 = sha224Of(oneMillionRange);
1065     digest256 = sha256Of(oneMillionRange);
1066     digest384 = sha384Of(oneMillionRange);
1067     digest512 = sha512Of(oneMillionRange);
1068     digest512_224 = sha512_224Of(oneMillionRange);
1069     digest512_256 = sha512_256Of(oneMillionRange);
1070     assert(digest == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1071     assert(digest224 == cast(ubyte[]) hexString!"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
1072     assert(digest256 == cast(ubyte[]) hexString!"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
1073     assert(digest384 == cast(ubyte[]) hexString!("9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279"
1074         ~"72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"));
1075     assert(digest512 == cast(ubyte[]) hexString!("e718483d0ce769644e2e42c7bc15b4638e1f98b13b20442856"
1076         ~"32a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"));
1077     assert(digest512_224 == cast(ubyte[]) hexString!"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
1078     assert(digest512_256 == cast(ubyte[]) hexString!"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
1079 
1080     enum ubyte[20] input = cast(ubyte[20]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d";
1081     assert(toHexString(input)
1082         == "A9993E364706816ABA3E25717850C26C9CD0D89D");
1083 }
1084 
1085 /**
1086  * These are convenience aliases for $(REF digest, std,digest) using the
1087  * SHA implementation.
1088  */
1089 //simple alias doesn't work here, hope this gets inlined...
1090 auto sha1Of(T...)(T data)
1091 {
1092     return digest!(SHA1, T)(data);
1093 }
1094 ///ditto
1095 auto sha224Of(T...)(T data)
1096 {
1097     return digest!(SHA224, T)(data);
1098 }
1099 ///ditto
1100 auto sha256Of(T...)(T data)
1101 {
1102     return digest!(SHA256, T)(data);
1103 }
1104 ///ditto
1105 auto sha384Of(T...)(T data)
1106 {
1107     return digest!(SHA384, T)(data);
1108 }
1109 ///ditto
1110 auto sha512Of(T...)(T data)
1111 {
1112     return digest!(SHA512, T)(data);
1113 }
1114 ///ditto
1115 auto sha512_224Of(T...)(T data)
1116 {
1117     return digest!(SHA512_224, T)(data);
1118 }
1119 ///ditto
1120 auto sha512_256Of(T...)(T data)
1121 {
1122     return digest!(SHA512_256, T)(data);
1123 }
1124 
1125 ///
1126 @safe unittest
1127 {
1128     ubyte[20] hash = sha1Of("abc");
1129     assert(hash == digest!SHA1("abc"));
1130 
1131     ubyte[28] hash224 = sha224Of("abc");
1132     assert(hash224 == digest!SHA224("abc"));
1133 
1134     ubyte[32] hash256 = sha256Of("abc");
1135     assert(hash256 == digest!SHA256("abc"));
1136 
1137     ubyte[48] hash384 = sha384Of("abc");
1138     assert(hash384 == digest!SHA384("abc"));
1139 
1140     ubyte[64] hash512 = sha512Of("abc");
1141     assert(hash512 == digest!SHA512("abc"));
1142 
1143     ubyte[28] hash512_224 = sha512_224Of("abc");
1144     assert(hash512_224 == digest!SHA512_224("abc"));
1145 
1146     ubyte[32] hash512_256 = sha512_256Of("abc");
1147     assert(hash512_256 == digest!SHA512_256("abc"));
1148 }
1149 
1150 @safe unittest
1151 {
1152     string a = "Mary has ", b = "a little lamb";
1153     int[] c = [ 1, 2, 3, 4, 5 ];
1154     auto d = toHexString(sha1Of(a, b, c));
1155     version (LittleEndian)
1156         assert(d[] == "CDBB611D00AC2387B642D3D7BDF4C3B342237110", d.dup);
1157     else
1158         assert(d[] == "A0F1196C7A379C09390476D9CA4AA11B71FD11C8", d.dup);
1159 }
1160 
1161 /**
1162  * OOP API SHA1 and SHA2 implementations.
1163  * See `std.digest` for differences between template and OOP API.
1164  *
1165  * This is an alias for $(D $(REF WrapperDigest, std,digest)!SHA1), see
1166  * there for more information.
1167  */
1168 alias SHA1Digest = WrapperDigest!SHA1;
1169 alias SHA224Digest = WrapperDigest!SHA224; ///ditto
1170 alias SHA256Digest = WrapperDigest!SHA256; ///ditto
1171 alias SHA384Digest = WrapperDigest!SHA384; ///ditto
1172 alias SHA512Digest = WrapperDigest!SHA512; ///ditto
1173 alias SHA512_224Digest = WrapperDigest!SHA512_224; ///ditto
1174 alias SHA512_256Digest = WrapperDigest!SHA512_256; ///ditto
1175 
1176 ///
1177 @safe unittest
1178 {
1179     //Simple example, hashing a string using Digest.digest helper function
1180     auto sha = new SHA1Digest();
1181     ubyte[] hash = sha.digest("abc");
1182     //Let's get a hash string
1183     assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
1184 
1185     //The same, but using SHA-224
1186     auto sha224 = new SHA224Digest();
1187     ubyte[] hash224 = sha224.digest("abc");
1188     //Let's get a hash string
1189     assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
1190 }
1191 
1192 ///
1193 @system unittest
1194 {
1195     //Let's use the OOP features:
1196     void test(Digest dig)
1197     {
1198       dig.put(cast(ubyte) 0);
1199     }
1200     auto sha = new SHA1Digest();
1201     test(sha);
1202 
1203     //Let's use a custom buffer:
1204     ubyte[20] buf;
1205     ubyte[] result = sha.finish(buf[]);
1206     assert(toHexString(result) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F");
1207 }
1208 
1209 @system unittest
1210 {
1211     import std.conv : hexString;
1212     import std.exception;
1213     auto sha = new SHA1Digest();
1214 
1215     sha.put(cast(ubyte[])"abcdef");
1216     sha.reset();
1217     sha.put(cast(ubyte[])"");
1218     assert(sha.finish() == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
1219 
1220     sha.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
1221     ubyte[22] result;
1222     auto result2 = sha.finish(result[]);
1223     assert(result[0 .. 20] == result2 && result2 == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
1224 
1225     debug
1226         assertThrown!Error(sha.finish(result[0 .. 15]));
1227 
1228     assert(sha.length == 20);
1229 
1230     assert(sha.digest("") == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
1231 
1232     assert(sha.digest("a") == cast(ubyte[]) hexString!"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
1233 
1234     assert(sha.digest("abc") == cast(ubyte[]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d");
1235 
1236     assert(sha.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
1237            == cast(ubyte[]) hexString!"84983e441c3bd26ebaae4aa1f95129e5e54670f1");
1238 
1239     assert(sha.digest("message digest") == cast(ubyte[]) hexString!"c12252ceda8be8994d5fa0290a47231c1d16aae3");
1240 
1241     assert(sha.digest("abcdefghijklmnopqrstuvwxyz")
1242            == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
1243 
1244     assert(sha.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
1245            == cast(ubyte[]) hexString!"761c457bf73b14d27e9e9265c46f4b4dda11f940");
1246 
1247     assert(sha.digest("1234567890123456789012345678901234567890",
1248                                    "1234567890123456789012345678901234567890")
1249            == cast(ubyte[]) hexString!"50abf5706a150990a08b2c5ea40fa0e585554732");
1250 
1251     ubyte[] onemilliona = new ubyte[1000000];
1252     onemilliona[] = 'a';
1253     assert(sha.digest(onemilliona) == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1254 }