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