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