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