]> git.ipfire.org Git - thirdparty/gcc.git/blame - libphobos/src/std/digest/sha.d
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
[thirdparty/gcc.git] / libphobos / src / std / digest / sha.d
CommitLineData
b4c522fa
IB
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 *
5fee5ec3 29 * This module publicly imports `std.digest` and can be used as a stand-alone
b4c522fa
IB
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 *
5fee5ec3 49 * Source: $(PHOBOSSRC std/digest/sha.d)
b4c522fa
IB
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 */
58module 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
5fee5ec3 104version (D_InlineAsm_X86)
b4c522fa 105{
5fee5ec3 106 version (D_PIC) {} // https://issues.dlang.org/show_bug.cgi?id=9378
b4c522fa
IB
107 else private version = USE_SSSE3;
108}
109else version (D_InlineAsm_X86_64)
110{
111 private version = USE_SSSE3;
112}
113
5fee5ec3 114import core.bitop;
b4c522fa
IB
115
116public 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 */
5fee5ec3 122version (LittleEndian)
b4c522fa 123{
5fee5ec3
IB
124 private alias nativeToBigEndian = bswap;
125 private alias bigEndianToNative = bswap;
b4c522fa 126}
5fee5ec3 127else pragma(inline, true) private pure @nogc nothrow @safe
b4c522fa 128{
5fee5ec3
IB
129 uint nativeToBigEndian(uint val) { return val; }
130 ulong nativeToBigEndian(ulong val) { return val; }
131 alias bigEndianToNative = nativeToBigEndian;
b4c522fa
IB
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 *
5fee5ec3 142 * See `std.digest` for differences between template and OOP API.
b4c522fa
IB
143 */
144struct 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)
5fee5ec3
IB
169 // constants as extra argument for PIC
170 // see https://issues.dlang.org/show_bug.cgi?id=9378
b4c522fa
IB
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 */
5fee5ec3 314 pragma(inline, true)
b4c522fa
IB
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 */
5fee5ec3
IB
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; }
b4c522fa
IB
329
330 /* SHA-384, SHA-512, SHA-512/224, SHA-512/256 */
5fee5ec3
IB
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; }
b4c522fa
IB
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 {
5fee5ec3
IB
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);
b4c522fa
IB
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 {
5fee5ec3
IB
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);
b4c522fa
IB
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 {
5fee5ec3
IB
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);
b4c522fa
IB
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 {
5fee5ec3
IB
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);
b4c522fa
IB
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 {
5fee5ec3
IB
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);
b4c522fa
IB
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 */
5fee5ec3 485 pragma(inline, true)
b4c522fa
IB
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 {
5fee5ec3 490 Word Wi = W[i] = bigEndianToNative(*cast(Word*) &((*input)[i*Word.sizeof]));
b4c522fa
IB
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
5fee5ec3
IB
497 // Temporarily disable inlining because it increases build speed by 10x.
498 // pragma(inline, true)
b4c522fa
IB
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)
5fee5ec3 648 * interface for `ubyte` and `const(ubyte)[]`.
b4c522fa
IB
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 {
5fee5ec3 712 uint[8] data = void;
b4c522fa
IB
713 uint index, padLen;
714
715 /* Save number of bits */
5fee5ec3 716 ulong bits = nativeToBigEndian(count[0]);
b4c522fa
IB
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) */
5fee5ec3 724 put((cast(ubyte*) &bits)[0 .. bits.sizeof]);
b4c522fa
IB
725
726 /* Store state in digest */
5fee5ec3
IB
727 static foreach (i; 0 .. (digestSize == 160) ? 5 : 8)
728 data[i] = nativeToBigEndian(state[i]);
b4c522fa
IB
729
730 /* Zeroize sensitive information. */
731 start();
5fee5ec3 732 return (cast(ubyte*) data.ptr)[0 .. digestSize/8];
b4c522fa
IB
733 }
734 else static if (blockSize == 1024)
735 {
5fee5ec3 736 ulong[8] data = void;
b4c522fa
IB
737 uint index, padLen;
738
739 /* Save number of bits */
5fee5ec3 740 ulong[2] bits = [nativeToBigEndian(count[1]), nativeToBigEndian(count[0])];
b4c522fa
IB
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) */
5fee5ec3 748 put((cast(ubyte*) &bits)[0 .. bits.sizeof]);
b4c522fa
IB
749
750 /* Store state in digest */
5fee5ec3
IB
751 static foreach (i; 0 .. 8)
752 data[i] = nativeToBigEndian(state[i]);
b4c522fa
IB
753
754 /* Zeroize sensitive information. */
755 start();
5fee5ec3 756 return (cast(ubyte*) data.ptr)[0 .. digestSize/8];
b4c522fa
IB
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
b4c522fa
IB
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
5fee5ec3
IB
813alias SHA1 = SHA!(512, 160); /// SHA alias for SHA-1, hash is ubyte[20]
814alias SHA224 = SHA!(512, 224); /// SHA alias for SHA-224, hash is ubyte[28]
815alias SHA256 = SHA!(512, 256); /// SHA alias for SHA-256, hash is ubyte[32]
816alias SHA384 = SHA!(1024, 384); /// SHA alias for SHA-384, hash is ubyte[48]
817alias SHA512 = SHA!(1024, 512); /// SHA alias for SHA-512, hash is ubyte[64]
818alias SHA512_224 = SHA!(1024, 224); /// SHA alias for SHA-512/224, hash is ubyte[28]
819alias SHA512_256 = SHA!(1024, 256); /// SHA alias for SHA-512/256, hash is ubyte[32]
820
b4c522fa
IB
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[])"");
5fee5ec3 849 assert(sha.finish() == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
b4c522fa
IB
850
851 SHA224 sha224;
852 sha224.put(cast(ubyte[])"abcdef");
853 sha224.start();
854 sha224.put(cast(ubyte[])"");
5fee5ec3 855 assert(sha224.finish() == cast(ubyte[]) hexString!"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
b4c522fa
IB
856
857 SHA256 sha256;
858 sha256.put(cast(ubyte[])"abcdef");
859 sha256.start();
860 sha256.put(cast(ubyte[])"");
5fee5ec3
IB
861 assert(sha256.finish() == cast(ubyte[])
862 hexString!"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
b4c522fa
IB
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[])"");
5fee5ec3
IB
875 assert(sha512.finish() == cast(ubyte[])
876 hexString!("cf83e1357eefb8bdf1542850d66d8007d620e4050b571"
b4c522fa
IB
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[])"");
5fee5ec3 883 assert(sha512_224.finish() == cast(ubyte[]) hexString!"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
b4c522fa
IB
884
885 SHA512_256 sha512_256;
886 sha512_256.put(cast(ubyte[])"abcdef");
887 sha512_256.start();
888 sha512_256.put(cast(ubyte[])"");
5fee5ec3
IB
889 assert(sha512_256.finish() == cast(ubyte[])
890 hexString!"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
b4c522fa
IB
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("");
5fee5ec3
IB
899 assert(digest == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
900 assert(digest224 == cast(ubyte[]) hexString!"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
901 assert(digest256 == cast(ubyte[]) hexString!"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
b4c522fa
IB
902 assert(digest384 == cast(ubyte[]) hexString!("38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c"
903 ~"0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"));
904 assert(digest512 == cast(ubyte[]) hexString!("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83"
905 ~"f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"));
5fee5ec3
IB
906 assert(digest512_224 == cast(ubyte[]) hexString!"6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
907 assert(digest512_256 == cast(ubyte[]) hexString!"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
b4c522fa
IB
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");
5fee5ec3
IB
916 assert(digest == cast(ubyte[]) hexString!"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
917 assert(digest224 == cast(ubyte[]) hexString!"abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5");
918 assert(digest256 == cast(ubyte[]) hexString!"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb");
b4c522fa
IB
919 assert(digest384 == cast(ubyte[]) hexString!("54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9"
920 ~"cd697e85175033caa88e6d57bc35efae0b5afd3145f31"));
921 assert(digest512 == cast(ubyte[]) hexString!("1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05ab"
922 ~"c54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"));
5fee5ec3
IB
923 assert(digest512_224 == cast(ubyte[]) hexString!"d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327");
924 assert(digest512_256 == cast(ubyte[]) hexString!"455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8");
b4c522fa
IB
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");
5fee5ec3
IB
933 assert(digest == cast(ubyte[]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d");
934 assert(digest224 == cast(ubyte[]) hexString!"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7");
935 assert(digest256 == cast(ubyte[]) hexString!"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
b4c522fa
IB
936 assert(digest384 == cast(ubyte[]) hexString!("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a"
937 ~"8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"));
938 assert(digest512 == cast(ubyte[]) hexString!("ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9"
939 ~"eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"));
5fee5ec3
IB
940 assert(digest512_224 == cast(ubyte[]) hexString!"4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa");
941 assert(digest512_256 == cast(ubyte[]) hexString!"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23");
b4c522fa
IB
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");
5fee5ec3
IB
950 assert(digest == cast(ubyte[]) hexString!"84983e441c3bd26ebaae4aa1f95129e5e54670f1");
951 assert(digest224 == cast(ubyte[]) hexString!"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525");
952 assert(digest256 == cast(ubyte[]) hexString!"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
b4c522fa
IB
953 assert(digest384 == cast(ubyte[]) hexString!("3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe"
954 ~"8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b"));
955 assert(digest512 == cast(ubyte[]) hexString!("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a827"
956 ~"9be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"));
5fee5ec3
IB
957 assert(digest512_224 == cast(ubyte[]) hexString!"e5302d6d54bb242275d1e7622d68df6eb02dedd13f564c13dbda2174");
958 assert(digest512_256 == cast(ubyte[]) hexString!"bde8e1f9f19bb9fd3406c90ec6bc47bd36d8ada9f11880dbc8a22a7078b6a461");
b4c522fa
IB
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");
5fee5ec3
IB
967 assert(digest == cast(ubyte[]) hexString!"c12252ceda8be8994d5fa0290a47231c1d16aae3");
968 assert(digest224 == cast(ubyte[]) hexString!"2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb");
969 assert(digest256 == cast(ubyte[]) hexString!"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
b4c522fa
IB
970 assert(digest384 == cast(ubyte[]) hexString!("473ed35167ec1f5d8e550368a3db39be54639f828868e9454c"
971 ~"239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5"));
972 assert(digest512 == cast(ubyte[]) hexString!("107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c134"
973 ~"92ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c"));
5fee5ec3
IB
974 assert(digest512_224 == cast(ubyte[]) hexString!"ad1a4db188fe57064f4f24609d2a83cd0afb9b398eb2fcaeaae2c564");
975 assert(digest512_256 == cast(ubyte[]) hexString!"0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb");
b4c522fa
IB
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");
5fee5ec3
IB
984 assert(digest == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
985 assert(digest224 == cast(ubyte[]) hexString!"45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2");
986 assert(digest256 == cast(ubyte[]) hexString!"71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73");
b4c522fa
IB
987 assert(digest384 == cast(ubyte[]) hexString!("feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5"
988 ~"f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4"));
989 assert(digest512 == cast(ubyte[]) hexString!("4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034"
990 ~"898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1"));
5fee5ec3
IB
991 assert(digest512_224 == cast(ubyte[]) hexString!"ff83148aa07ec30655c1b40aff86141c0215fe2a54f767d3f38743d8");
992 assert(digest512_256 == cast(ubyte[]) hexString!"fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26");
b4c522fa
IB
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");
5fee5ec3
IB
1001 assert(digest == cast(ubyte[]) hexString!"761c457bf73b14d27e9e9265c46f4b4dda11f940");
1002 assert(digest224 == cast(ubyte[]) hexString!"bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9");
1003 assert(digest256 == cast(ubyte[]) hexString!"db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0");
b4c522fa
IB
1004 assert(digest384 == cast(ubyte[]) hexString!("1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039"
1005 ~"c1464ee8732f11a5341a6f41e0c202294736ed64db1a84"));
1006 assert(digest512 == cast(ubyte[]) hexString!("1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f"
1007 ~"536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894"));
5fee5ec3
IB
1008 assert(digest512_224 == cast(ubyte[]) hexString!"a8b4b9174b99ffc67d6f49be9981587b96441051e16e6dd036b140d3");
1009 assert(digest512_256 == cast(ubyte[]) hexString!"cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8");
b4c522fa
IB
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");
5fee5ec3
IB
1025 assert(digest == cast(ubyte[]) hexString!"50abf5706a150990a08b2c5ea40fa0e585554732");
1026 assert(digest224 == cast(ubyte[]) hexString!"b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e");
1027 assert(digest256 == cast(ubyte[]) hexString!"f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e");
b4c522fa
IB
1028 assert(digest384 == cast(ubyte[]) hexString!("b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b"
1029 ~"9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026"));
1030 assert(digest512 == cast(ubyte[]) hexString!("72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d191"
1031 ~"4042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843"));
5fee5ec3
IB
1032 assert(digest512_224 == cast(ubyte[]) hexString!"ae988faaa47e401a45f704d1272d99702458fea2ddc6582827556dd2");
1033 assert(digest512_256 == cast(ubyte[]) hexString!"2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148");
b4c522fa
IB
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);
5fee5ec3
IB
1044 assert(digest == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1045 assert(digest224 == cast(ubyte[]) hexString!"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
1046 assert(digest256 == cast(ubyte[]) hexString!"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
b4c522fa
IB
1047 assert(digest384 == cast(ubyte[]) hexString!("9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279"
1048 ~"72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"));
1049 assert(digest512 == cast(ubyte[]) hexString!("e718483d0ce769644e2e42c7bc15b4638e1f98b13b20442856"
1050 ~"32a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"));
5fee5ec3
IB
1051 assert(digest512_224 == cast(ubyte[]) hexString!"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
1052 assert(digest512_256 == cast(ubyte[]) hexString!"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
b4c522fa
IB
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);
5fee5ec3
IB
1062 assert(digest == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
1063 assert(digest224 == cast(ubyte[]) hexString!"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
1064 assert(digest256 == cast(ubyte[]) hexString!"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
b4c522fa
IB
1065 assert(digest384 == cast(ubyte[]) hexString!("9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279"
1066 ~"72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"));
1067 assert(digest512 == cast(ubyte[]) hexString!("e718483d0ce769644e2e42c7bc15b4638e1f98b13b20442856"
1068 ~"32a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"));
5fee5ec3
IB
1069 assert(digest512_224 == cast(ubyte[]) hexString!"37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
1070 assert(digest512_256 == cast(ubyte[]) hexString!"9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
b4c522fa 1071
5fee5ec3
IB
1072 enum ubyte[20] input = cast(ubyte[20]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d";
1073 assert(toHexString(input)
b4c522fa
IB
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...
1082auto sha1Of(T...)(T data)
1083{
1084 return digest!(SHA1, T)(data);
1085}
1086///ditto
1087auto sha224Of(T...)(T data)
1088{
1089 return digest!(SHA224, T)(data);
1090}
1091///ditto
1092auto sha256Of(T...)(T data)
1093{
1094 return digest!(SHA256, T)(data);
1095}
1096///ditto
1097auto sha384Of(T...)(T data)
1098{
1099 return digest!(SHA384, T)(data);
1100}
1101///ditto
1102auto sha512Of(T...)(T data)
1103{
1104 return digest!(SHA512, T)(data);
1105}
1106///ditto
1107auto sha512_224Of(T...)(T data)
1108{
1109 return digest!(SHA512_224, T)(data);
1110}
1111///ditto
1112auto 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 ];
5fee5ec3 1146 auto d = toHexString(sha1Of(a, b, c));
b4c522fa 1147 version (LittleEndian)
5fee5ec3 1148 assert(d[] == "CDBB611D00AC2387B642D3D7BDF4C3B342237110", d.dup);
b4c522fa 1149 else
5fee5ec3 1150 assert(d[] == "A0F1196C7A379C09390476D9CA4AA11B71FD11C8", d.dup);
b4c522fa
IB
1151}
1152
1153/**
1154 * OOP API SHA1 and SHA2 implementations.
5fee5ec3 1155 * See `std.digest` for differences between template and OOP API.
b4c522fa
IB
1156 *
1157 * This is an alias for $(D $(REF WrapperDigest, std,digest)!SHA1), see
1158 * there for more information.
1159 */
1160alias SHA1Digest = WrapperDigest!SHA1;
1161alias SHA224Digest = WrapperDigest!SHA224; ///ditto
1162alias SHA256Digest = WrapperDigest!SHA256; ///ditto
1163alias SHA384Digest = WrapperDigest!SHA384; ///ditto
1164alias SHA512Digest = WrapperDigest!SHA512; ///ditto
1165alias SHA512_224Digest = WrapperDigest!SHA512_224; ///ditto
1166alias 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{
5fee5ec3
IB
1203 import std.conv : hexString;
1204 import std.exception;
b4c522fa
IB
1205 auto sha = new SHA1Digest();
1206
1207 sha.put(cast(ubyte[])"abcdef");
1208 sha.reset();
1209 sha.put(cast(ubyte[])"");
5fee5ec3 1210 assert(sha.finish() == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
b4c522fa
IB
1211
1212 sha.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
1213 ubyte[22] result;
1214 auto result2 = sha.finish(result[]);
5fee5ec3 1215 assert(result[0 .. 20] == result2 && result2 == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
b4c522fa
IB
1216
1217 debug
1218 assertThrown!Error(sha.finish(result[0 .. 15]));
1219
1220 assert(sha.length == 20);
1221
5fee5ec3 1222 assert(sha.digest("") == cast(ubyte[]) hexString!"da39a3ee5e6b4b0d3255bfef95601890afd80709");
b4c522fa 1223
5fee5ec3 1224 assert(sha.digest("a") == cast(ubyte[]) hexString!"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
b4c522fa 1225
5fee5ec3 1226 assert(sha.digest("abc") == cast(ubyte[]) hexString!"a9993e364706816aba3e25717850c26c9cd0d89d");
b4c522fa
IB
1227
1228 assert(sha.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
5fee5ec3 1229 == cast(ubyte[]) hexString!"84983e441c3bd26ebaae4aa1f95129e5e54670f1");
b4c522fa 1230
5fee5ec3 1231 assert(sha.digest("message digest") == cast(ubyte[]) hexString!"c12252ceda8be8994d5fa0290a47231c1d16aae3");
b4c522fa
IB
1232
1233 assert(sha.digest("abcdefghijklmnopqrstuvwxyz")
5fee5ec3 1234 == cast(ubyte[]) hexString!"32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
b4c522fa
IB
1235
1236 assert(sha.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
5fee5ec3 1237 == cast(ubyte[]) hexString!"761c457bf73b14d27e9e9265c46f4b4dda11f940");
b4c522fa
IB
1238
1239 assert(sha.digest("1234567890123456789012345678901234567890",
1240 "1234567890123456789012345678901234567890")
5fee5ec3 1241 == cast(ubyte[]) hexString!"50abf5706a150990a08b2c5ea40fa0e585554732");
b4c522fa
IB
1242
1243 ubyte[] onemilliona = new ubyte[1000000];
1244 onemilliona[] = 'a';
5fee5ec3 1245 assert(sha.digest(onemilliona) == cast(ubyte[]) hexString!"34aa973cd4c4daa4f61eeb2bdbad27316534016f");
b4c522fa 1246}