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