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             uint i, index, partLen;
654             auto inputLen = input.length;
655 
656             /* Compute number of bytes mod block size (64 or 128 bytes) */
657             index = (cast(uint) count[0] >> 3) & (blockSizeInBytes - 1);
658 
659             /* Update number of bits */
660             static if (blockSize == 512)
661                 count[0] += inputLen * 8;
662             else static if (blockSize == 1024)
663             {
664                 /* ugly hack to work around lack of ucent */
665                 auto oldCount0 = count[0];
666                 count[0] += inputLen * 8;
667                 if (count[0] < oldCount0)
668                     count[1]++;
669             }
670             else
671                 static assert(0);
672 
673             partLen = blockSizeInBytes - index;
674 
675             /* Transform as many times as possible. */
676             if (inputLen >= partLen)
677             {
678                 (&buffer[index])[0 .. partLen] = input.ptr[0 .. partLen];
679                 transform (&state, &buffer);
680 
681                 for (i = partLen; i + blockSizeInBytes-1 < inputLen; i += blockSizeInBytes)
682                    transform(&state, cast(ubyte[blockSizeInBytes]*)(input.ptr + i));
683 
684                 index = 0;
685             }
686             else
687                 i = 0;
688 
689             /* Buffer remaining input */
690             if (inputLen - i)
691                 (&buffer[index])[0 .. inputLen-i] = (&input[i])[0 .. inputLen-i];
692         }
693 
694         @safe unittest
695         {
696             typeof(this) dig;
697             dig.put(cast(ubyte) 0); //single ubyte
698             dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
699             ubyte[10] buf;
700             dig.put(buf); //buffer
701         }
702 
703 
704         /**
705          * Returns the finished SHA hash. This also calls $(LREF start) to
706          * reset the internal state.
707          */
708         ubyte[digestSize/8] finish() @trusted pure nothrow @nogc
709         {
710             static if (blockSize == 512)
711             {
712                 uint[8] data = void;
713                 uint index, padLen;
714 
715                 /* Save number of bits */
716                 ulong bits = nativeToBigEndian(count[0]);
717 
718                 /* Pad out to 56 mod 64. */
719                 index = (cast(uint) count[0] >> 3) & (64 - 1);
720                 padLen = (index < 56) ? (56 - index) : (120 - index);
721                 put(padding[0 .. padLen]);
722 
723                 /* Append length (before padding) */
724                 put((cast(ubyte*) &bits)[0 .. bits.sizeof]);
725 
726                 /* Store state in digest */
727                 static foreach (i; 0 .. (digestSize == 160) ? 5 : 8)
728                     data[i] = nativeToBigEndian(state[i]);
729 
730                 /* Zeroize sensitive information. */
731                 start();
732                 return (cast(ubyte*) data.ptr)[0 .. digestSize/8];
733             }
734             else static if (blockSize == 1024)
735             {
736                 ulong[8] data = void;
737                 uint index, padLen;
738 
739                 /* Save number of bits */
740                 ulong[2] bits = [nativeToBigEndian(count[1]), nativeToBigEndian(count[0])];
741 
742                 /* Pad out to 112 mod 128. */
743                 index = (cast(uint) count[0] >> 3) & (128 - 1);
744                 padLen = (index < 112) ? (112 - index) : (240 - index);
745                 put(padding[0 .. padLen]);
746 
747                 /* Append length (before padding) */
748                 put((cast(ubyte*) &bits)[0 .. bits.sizeof]);
749 
750                 /* Store state in digest */
751                 static foreach (i; 0 .. 8)
752                     data[i] = nativeToBigEndian(state[i]);
753 
754                 /* Zeroize sensitive information. */
755                 start();
756                 return (cast(ubyte*) data.ptr)[0 .. digestSize/8];
757             }
758             else
759                 static assert(0);
760         }
761         ///
762         @safe unittest
763         {
764             //Simple example
765             SHA1 hash;
766             hash.start();
767             hash.put(cast(ubyte) 0);
768             ubyte[20] result = hash.finish();
769         }
770 }
771 
772 ///
773 @safe unittest
774 {
775     //Simple example, hashing a string using sha1Of helper function
776     ubyte[20] hash = sha1Of("abc");
777     //Let's get a hash string
778     assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
779 
780     //The same, but using SHA-224
781     ubyte[28] hash224 = sha224Of("abc");
782     assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
783 }
784 
785 ///
786 @safe unittest
787 {
788     //Using the basic API
789     SHA1 hash;
790     hash.start();
791     ubyte[1024] data;
792     //Initialize data here...
793     hash.put(data);
794     ubyte[20] result = hash.finish();
795 }
796 
797 ///
798 @safe unittest
799 {
800     //Let's use the template features:
801     //Note: When passing a SHA1 to a function, it must be passed by reference!
802     void doSomething(T)(ref T hash)
803     if (isDigest!T)
804     {
805       hash.put(cast(ubyte) 0);
806     }
807     SHA1 sha;
808     sha.start();
809     doSomething(sha);
810     assert(toHexString(sha.finish()) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F");
811 }
812 
813 alias SHA1 = SHA!(512, 160);  /// SHA alias for SHA-1, hash is ubyte[20]
814 alias SHA224 = SHA!(512, 224);  /// SHA alias for SHA-224, hash is ubyte[28]
815 alias SHA256 = SHA!(512, 256);  /// SHA alias for SHA-256, hash is ubyte[32]
816 alias SHA384 = SHA!(1024, 384); /// SHA alias for SHA-384, hash is ubyte[48]
817 alias SHA512 = SHA!(1024, 512); /// SHA alias for SHA-512, hash is ubyte[64]
818 alias SHA512_224 = SHA!(1024, 224); /// SHA alias for SHA-512/224, hash is ubyte[28]
819 alias SHA512_256 = SHA!(1024, 256); /// SHA alias for SHA-512/256, hash is ubyte[32]
820 
821 @safe unittest
822 {
823     assert(isDigest!SHA1);
824     assert(isDigest!SHA224);
825     assert(isDigest!SHA256);
826     assert(isDigest!SHA384);
827     assert(isDigest!SHA512);
828     assert(isDigest!SHA512_224);
829     assert(isDigest!SHA512_256);
830 }
831 
832 @system unittest
833 {
834     import std.conv : hexString;
835     import std.range;
836 
837     ubyte[20] digest;
838     ubyte[28] digest224;
839     ubyte[32] digest256;
840     ubyte[48] digest384;
841     ubyte[64] digest512;
842     ubyte[28] digest512_224;
843     ubyte[32] digest512_256;
844 
845     SHA1 sha;
846     sha.put(cast(ubyte[])"abcdef");
847     sha.start();
848     sha.put(cast(ubyte[])"");
849     assert(sha.finish() == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
850 
851     SHA224 sha224;
852     sha224.put(cast(ubyte[])"abcdef");
853     sha224.start();
854     sha224.put(cast(ubyte[])"");
855     assert(sha224.finish() == cast(ubyte[]) hexString!"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
856 
857     SHA256 sha256;
858     sha256.put(cast(ubyte[])"abcdef");
859     sha256.start();
860     sha256.put(cast(ubyte[])"");
861     assert(sha256.finish() == cast(ubyte[])
862             hexString!"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
863 
864     SHA384 sha384;
865     sha384.put(cast(ubyte[])"abcdef");
866     sha384.start();
867     sha384.put(cast(ubyte[])"");
868     assert(sha384.finish() == cast(ubyte[]) hexString!("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c"
869         ~"0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"));
870 
871     SHA512 sha512;
872     sha512.put(cast(ubyte[])"abcdef");
873     sha512.start();
874     sha512.put(cast(ubyte[])"");
875     assert(sha512.finish() == cast(ubyte[])
876             hexString!("cf83e1357eefb8bdf1542850d66d8007d620e4050b571"
877         ~"5dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"));
878 
879     SHA512_224 sha512_224;
880     sha512_224.put(cast(ubyte[])"abcdef");
881     sha512_224.start();
882     sha512_224.put(cast(ubyte[])"");
883     assert(sha512_224.finish() == cast(ubyte[]) hexString!"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
884 
885     SHA512_256 sha512_256;
886     sha512_256.put(cast(ubyte[])"abcdef");
887     sha512_256.start();
888     sha512_256.put(cast(ubyte[])"");
889     assert(sha512_256.finish() == cast(ubyte[])
890             hexString!"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
891 
892     digest        = sha1Of      ("");
893     digest224     = sha224Of    ("");
894     digest256     = sha256Of    ("");
895     digest384     = sha384Of    ("");
896     digest512     = sha512Of    ("");
897     digest512_224 = sha512_224Of("");
898     digest512_256 = sha512_256Of("");
899     assert(digest == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
900     assert(digest224 == cast(ubyte[]) hexString!"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
901     assert(digest256 == cast(ubyte[]) hexString!"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
902     assert(digest384 == cast(ubyte[]) hexString!("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c"
903         ~"0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"));
904     assert(digest512 == cast(ubyte[]) hexString!("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83"
905         ~"f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"));
906     assert(digest512_224 == cast(ubyte[]) hexString!"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
907     assert(digest512_256 == cast(ubyte[]) hexString!"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
908 
909     digest        = sha1Of      ("a");
910     digest224     = sha224Of    ("a");
911     digest256     = sha256Of    ("a");
912     digest384     = sha384Of    ("a");
913     digest512     = sha512Of    ("a");
914     digest512_224 = sha512_224Of("a");
915     digest512_256 = sha512_256Of("a");
916     assert(digest == cast(ubyte[]) hexString!"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
917     assert(digest224 == cast(ubyte[]) hexString!"abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5");
918     assert(digest256 == cast(ubyte[]) hexString!"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb");
919     assert(digest384 == cast(ubyte[]) hexString!("54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9"
920         ~"cd697e85175033caa88e6d57bc35efae0b5afd3145f31"));
921     assert(digest512 == cast(ubyte[]) hexString!("1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05ab"
922         ~"c54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"));
923     assert(digest512_224 == cast(ubyte[]) hexString!"d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327");
924     assert(digest512_256 == cast(ubyte[]) hexString!"455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8");
925 
926     digest        = sha1Of      ("abc");
927     digest224     = sha224Of    ("abc");
928     digest256     = sha256Of    ("abc");
929     digest384     = sha384Of    ("abc");
930     digest512     = sha512Of    ("abc");
931     digest512_224 = sha512_224Of("abc");
932     digest512_256 = sha512_256Of("abc");
933     assert(digest == cast(ubyte[]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d");
934     assert(digest224 == cast(ubyte[]) hexString!"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7");
935     assert(digest256 == cast(ubyte[]) hexString!"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
936     assert(digest384 == cast(ubyte[]) hexString!("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a"
937         ~"8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"));
938     assert(digest512 == cast(ubyte[]) hexString!("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9"
939         ~"eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"));
940     assert(digest512_224 == cast(ubyte[]) hexString!"4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa");
941     assert(digest512_256 == cast(ubyte[]) hexString!"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23");
942 
943     digest        = sha1Of      ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
944     digest224     = sha224Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
945     digest256     = sha256Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
946     digest384     = sha384Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
947     digest512     = sha512Of    ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
948     digest512_224 = sha512_224Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
949     digest512_256 = sha512_256Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
950     assert(digest == cast(ubyte[]) hexString!"84983e441c3bd26ebaae4aa1f95129e5e54670f1");
951     assert(digest224 == cast(ubyte[]) hexString!"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525");
952     assert(digest256 == cast(ubyte[]) hexString!"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
953     assert(digest384 == cast(ubyte[]) hexString!("3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe"
954         ~"8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b"));
955     assert(digest512 == cast(ubyte[]) hexString!("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a827"
956         ~"9be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"));
957     assert(digest512_224 == cast(ubyte[]) hexString!"e5302d6d54bb242275d1e7622d68df6eb02dedd13f564c13dbda2174");
958     assert(digest512_256 == cast(ubyte[]) hexString!"bde8e1f9f19bb9fd3406c90ec6bc47bd36d8ada9f11880dbc8a22a7078b6a461");
959 
960     digest        = sha1Of      ("message digest");
961     digest224     = sha224Of    ("message digest");
962     digest256     = sha256Of    ("message digest");
963     digest384     = sha384Of    ("message digest");
964     digest512     = sha512Of    ("message digest");
965     digest512_224 = sha512_224Of("message digest");
966     digest512_256 = sha512_256Of("message digest");
967     assert(digest == cast(ubyte[]) hexString!"c12252ceda8be8994d5fa0290a47231c1d16aae3");
968     assert(digest224 == cast(ubyte[]) hexString!"2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb");
969     assert(digest256 == cast(ubyte[]) hexString!"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
970     assert(digest384 == cast(ubyte[]) hexString!("473ed35167ec1f5d8e550368a3db39be54639f828868e9454c"
971         ~"239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5"));
972     assert(digest512 == cast(ubyte[]) hexString!("107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c134"
973         ~"92ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c"));
974     assert(digest512_224 == cast(ubyte[]) hexString!"ad1a4db188fe57064f4f24609d2a83cd0afb9b398eb2fcaeaae2c564");
975     assert(digest512_256 == cast(ubyte[]) hexString!"0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb");
976 
977     digest        = sha1Of      ("abcdefghijklmnopqrstuvwxyz");
978     digest224     = sha224Of    ("abcdefghijklmnopqrstuvwxyz");
979     digest256     = sha256Of    ("abcdefghijklmnopqrstuvwxyz");
980     digest384     = sha384Of    ("abcdefghijklmnopqrstuvwxyz");
981     digest512     = sha512Of    ("abcdefghijklmnopqrstuvwxyz");
982     digest512_224 = sha512_224Of("abcdefghijklmnopqrstuvwxyz");
983     digest512_256 = sha512_256Of("abcdefghijklmnopqrstuvwxyz");
984     assert(digest == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
985     assert(digest224 == cast(ubyte[]) hexString!"45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2");
986     assert(digest256 == cast(ubyte[]) hexString!"71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73");
987     assert(digest384 == cast(ubyte[]) hexString!("feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5"
988         ~"f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4"));
989     assert(digest512 == cast(ubyte[]) hexString!("4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034"
990         ~"898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1"));
991     assert(digest512_224 == cast(ubyte[]) hexString!"ff83148aa07ec30655c1b40aff86141c0215fe2a54f767d3f38743d8");
992     assert(digest512_256 == cast(ubyte[]) hexString!"fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26");
993 
994     digest        = sha1Of      ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
995     digest224     = sha224Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
996     digest256     = sha256Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
997     digest384     = sha384Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
998     digest512     = sha512Of    ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
999     digest512_224 = sha512_224Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1000     digest512_256 = sha512_256Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
1001     assert(digest == cast(ubyte[]) hexString!"761c457bf73b14d27e9e9265c46f4b4dda11f940");
1002     assert(digest224 == cast(ubyte[]) hexString!"bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9");
1003     assert(digest256 == cast(ubyte[]) hexString!"db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0");
1004     assert(digest384 == cast(ubyte[]) hexString!("1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039"
1005         ~"c1464ee8732f11a5341a6f41e0c202294736ed64db1a84"));
1006     assert(digest512 == cast(ubyte[]) hexString!("1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f"
1007         ~"536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894"));
1008     assert(digest512_224 == cast(ubyte[]) hexString!"a8b4b9174b99ffc67d6f49be9981587b96441051e16e6dd036b140d3");
1009     assert(digest512_256 == cast(ubyte[]) hexString!"cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8");
1010 
1011     digest        = sha1Of      ("1234567890123456789012345678901234567890"~
1012                                  "1234567890123456789012345678901234567890");
1013     digest224     = sha224Of    ("1234567890123456789012345678901234567890"~
1014                                  "1234567890123456789012345678901234567890");
1015     digest256     = sha256Of    ("1234567890123456789012345678901234567890"~
1016                                  "1234567890123456789012345678901234567890");
1017     digest384     = sha384Of    ("1234567890123456789012345678901234567890"~
1018                                  "1234567890123456789012345678901234567890");
1019     digest512     = sha512Of    ("1234567890123456789012345678901234567890"~
1020                                  "1234567890123456789012345678901234567890");
1021     digest512_224 = sha512_224Of("1234567890123456789012345678901234567890"~
1022                                  "1234567890123456789012345678901234567890");
1023     digest512_256 = sha512_256Of("1234567890123456789012345678901234567890"~
1024                                  "1234567890123456789012345678901234567890");
1025     assert(digest == cast(ubyte[]) hexString!"50abf5706a150990a08b2c5ea40fa0e585554732");
1026     assert(digest224 == cast(ubyte[]) hexString!"b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e");
1027     assert(digest256 == cast(ubyte[]) hexString!"f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e");
1028     assert(digest384 == cast(ubyte[]) hexString!("b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b"
1029         ~"9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026"));
1030     assert(digest512 == cast(ubyte[]) hexString!("72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d191"
1031         ~"4042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843"));
1032     assert(digest512_224 == cast(ubyte[]) hexString!"ae988faaa47e401a45f704d1272d99702458fea2ddc6582827556dd2");
1033     assert(digest512_256 == cast(ubyte[]) hexString!"2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148");
1034 
1035     ubyte[] onemilliona = new ubyte[1000000];
1036     onemilliona[] = 'a';
1037     digest = sha1Of(onemilliona);
1038     digest224 = sha224Of(onemilliona);
1039     digest256 = sha256Of(onemilliona);
1040     digest384 = sha384Of(onemilliona);
1041     digest512 = sha512Of(onemilliona);
1042     digest512_224 = sha512_224Of(onemilliona);
1043     digest512_256 = sha512_256Of(onemilliona);
1044     assert(digest == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1045     assert(digest224 == cast(ubyte[]) hexString!"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
1046     assert(digest256 == cast(ubyte[]) hexString!"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
1047     assert(digest384 == cast(ubyte[]) hexString!("9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279"
1048         ~"72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"));
1049     assert(digest512 == cast(ubyte[]) hexString!("e718483d0ce769644e2e42c7bc15b4638e1f98b13b20442856"
1050         ~"32a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"));
1051     assert(digest512_224 == cast(ubyte[]) hexString!"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
1052     assert(digest512_256 == cast(ubyte[]) hexString!"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
1053 
1054     auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
1055     digest = sha1Of(oneMillionRange);
1056     digest224 = sha224Of(oneMillionRange);
1057     digest256 = sha256Of(oneMillionRange);
1058     digest384 = sha384Of(oneMillionRange);
1059     digest512 = sha512Of(oneMillionRange);
1060     digest512_224 = sha512_224Of(oneMillionRange);
1061     digest512_256 = sha512_256Of(oneMillionRange);
1062     assert(digest == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1063     assert(digest224 == cast(ubyte[]) hexString!"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
1064     assert(digest256 == cast(ubyte[]) hexString!"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
1065     assert(digest384 == cast(ubyte[]) hexString!("9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279"
1066         ~"72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"));
1067     assert(digest512 == cast(ubyte[]) hexString!("e718483d0ce769644e2e42c7bc15b4638e1f98b13b20442856"
1068         ~"32a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"));
1069     assert(digest512_224 == cast(ubyte[]) hexString!"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
1070     assert(digest512_256 == cast(ubyte[]) hexString!"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
1071 
1072     enum ubyte[20] input = cast(ubyte[20]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d";
1073     assert(toHexString(input)
1074         == "A9993E364706816ABA3E25717850C26C9CD0D89D");
1075 }
1076 
1077 /**
1078  * These are convenience aliases for $(REF digest, std,digest) using the
1079  * SHA implementation.
1080  */
1081 //simple alias doesn't work here, hope this gets inlined...
1082 auto sha1Of(T...)(T data)
1083 {
1084     return digest!(SHA1, T)(data);
1085 }
1086 ///ditto
1087 auto sha224Of(T...)(T data)
1088 {
1089     return digest!(SHA224, T)(data);
1090 }
1091 ///ditto
1092 auto sha256Of(T...)(T data)
1093 {
1094     return digest!(SHA256, T)(data);
1095 }
1096 ///ditto
1097 auto sha384Of(T...)(T data)
1098 {
1099     return digest!(SHA384, T)(data);
1100 }
1101 ///ditto
1102 auto sha512Of(T...)(T data)
1103 {
1104     return digest!(SHA512, T)(data);
1105 }
1106 ///ditto
1107 auto sha512_224Of(T...)(T data)
1108 {
1109     return digest!(SHA512_224, T)(data);
1110 }
1111 ///ditto
1112 auto sha512_256Of(T...)(T data)
1113 {
1114     return digest!(SHA512_256, T)(data);
1115 }
1116 
1117 ///
1118 @safe unittest
1119 {
1120     ubyte[20] hash = sha1Of("abc");
1121     assert(hash == digest!SHA1("abc"));
1122 
1123     ubyte[28] hash224 = sha224Of("abc");
1124     assert(hash224 == digest!SHA224("abc"));
1125 
1126     ubyte[32] hash256 = sha256Of("abc");
1127     assert(hash256 == digest!SHA256("abc"));
1128 
1129     ubyte[48] hash384 = sha384Of("abc");
1130     assert(hash384 == digest!SHA384("abc"));
1131 
1132     ubyte[64] hash512 = sha512Of("abc");
1133     assert(hash512 == digest!SHA512("abc"));
1134 
1135     ubyte[28] hash512_224 = sha512_224Of("abc");
1136     assert(hash512_224 == digest!SHA512_224("abc"));
1137 
1138     ubyte[32] hash512_256 = sha512_256Of("abc");
1139     assert(hash512_256 == digest!SHA512_256("abc"));
1140 }
1141 
1142 @safe unittest
1143 {
1144     string a = "Mary has ", b = "a little lamb";
1145     int[] c = [ 1, 2, 3, 4, 5 ];
1146     auto d = toHexString(sha1Of(a, b, c));
1147     version (LittleEndian)
1148         assert(d[] == "CDBB611D00AC2387B642D3D7BDF4C3B342237110", d.dup);
1149     else
1150         assert(d[] == "A0F1196C7A379C09390476D9CA4AA11B71FD11C8", d.dup);
1151 }
1152 
1153 /**
1154  * OOP API SHA1 and SHA2 implementations.
1155  * See `std.digest` for differences between template and OOP API.
1156  *
1157  * This is an alias for $(D $(REF WrapperDigest, std,digest)!SHA1), see
1158  * there for more information.
1159  */
1160 alias SHA1Digest = WrapperDigest!SHA1;
1161 alias SHA224Digest = WrapperDigest!SHA224; ///ditto
1162 alias SHA256Digest = WrapperDigest!SHA256; ///ditto
1163 alias SHA384Digest = WrapperDigest!SHA384; ///ditto
1164 alias SHA512Digest = WrapperDigest!SHA512; ///ditto
1165 alias SHA512_224Digest = WrapperDigest!SHA512_224; ///ditto
1166 alias SHA512_256Digest = WrapperDigest!SHA512_256; ///ditto
1167 
1168 ///
1169 @safe unittest
1170 {
1171     //Simple example, hashing a string using Digest.digest helper function
1172     auto sha = new SHA1Digest();
1173     ubyte[] hash = sha.digest("abc");
1174     //Let's get a hash string
1175     assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
1176 
1177     //The same, but using SHA-224
1178     auto sha224 = new SHA224Digest();
1179     ubyte[] hash224 = sha224.digest("abc");
1180     //Let's get a hash string
1181     assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
1182 }
1183 
1184 ///
1185 @system unittest
1186 {
1187     //Let's use the OOP features:
1188     void test(Digest dig)
1189     {
1190       dig.put(cast(ubyte) 0);
1191     }
1192     auto sha = new SHA1Digest();
1193     test(sha);
1194 
1195     //Let's use a custom buffer:
1196     ubyte[20] buf;
1197     ubyte[] result = sha.finish(buf[]);
1198     assert(toHexString(result) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F");
1199 }
1200 
1201 @system unittest
1202 {
1203     import std.conv : hexString;
1204     import std.exception;
1205     auto sha = new SHA1Digest();
1206 
1207     sha.put(cast(ubyte[])"abcdef");
1208     sha.reset();
1209     sha.put(cast(ubyte[])"");
1210     assert(sha.finish() == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
1211 
1212     sha.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
1213     ubyte[22] result;
1214     auto result2 = sha.finish(result[]);
1215     assert(result[0 .. 20] == result2 && result2 == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
1216 
1217     debug
1218         assertThrown!Error(sha.finish(result[0 .. 15]));
1219 
1220     assert(sha.length == 20);
1221 
1222     assert(sha.digest("") == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
1223 
1224     assert(sha.digest("a") == cast(ubyte[]) hexString!"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
1225 
1226     assert(sha.digest("abc") == cast(ubyte[]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d");
1227 
1228     assert(sha.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
1229            == cast(ubyte[]) hexString!"84983e441c3bd26ebaae4aa1f95129e5e54670f1");
1230 
1231     assert(sha.digest("message digest") == cast(ubyte[]) hexString!"c12252ceda8be8994d5fa0290a47231c1d16aae3");
1232 
1233     assert(sha.digest("abcdefghijklmnopqrstuvwxyz")
1234            == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
1235 
1236     assert(sha.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
1237            == cast(ubyte[]) hexString!"761c457bf73b14d27e9e9265c46f4b4dda11f940");
1238 
1239     assert(sha.digest("1234567890123456789012345678901234567890",
1240                                    "1234567890123456789012345678901234567890")
1241            == cast(ubyte[]) hexString!"50abf5706a150990a08b2c5ea40fa0e585554732");
1242 
1243     ubyte[] onemilliona = new ubyte[1000000];
1244     onemilliona[] = 'a';
1245     assert(sha.digest(onemilliona) == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1246 }
Suggestion Box / Bug Report