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