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