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