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