diff --git a/sha1.html b/sha1.html index 67dd666..9e91a99 100644 --- a/sha1.html +++ b/sha1.html @@ -8,7 +8,11 @@ diff --git a/sha1.js b/sha1.js index a8fa004..119647c 100644 --- a/sha1.js +++ b/sha1.js @@ -3,10 +3,10 @@ function char_code_to_bytes(code) var result = []; do { - result.push(code & 0xff); - code = code >> 8; + result.unshift(code & 0xff); + code >>= 8; } while (code); - return result.reverse(); + return result; } function str_to_bytes(str) @@ -43,18 +43,39 @@ function bytes_to_big_endian_32(array) return result; } +function rol(x,n) +{ + return (x << n) | (x >>> (32 - n)); +} + +function to_hex(x) +{ + var h = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; + + return String( + h[(x & 0xf0000000) >>> 28] + + h[(x & 0x0f000000) >>> 24] + + h[(x & 0x00f00000) >>> 20] + + h[(x & 0x000f0000) >>> 16] + + h[(x & 0x0000f000) >>> 12] + + h[(x & 0x00000f00) >>> 8] + + h[(x & 0x000000f0) >>> 4] + + h[(x & 0x0000000f) >>> 0] + ); +} + function sha1(text) { // get text into byte array - var message = str_to_bytes(text); + var message = str_to_bytes(text); var message_size_in_bits = message.length * 8; // Initialize variables: var h0 = 0x67452301; - var h1 = 0xEFCDAB89; - var h2 = 0x98BADCFE; + var h1 = 0xefcdab89; + var h2 = 0x98badcfe; var h3 = 0x10325476; - var h4 = 0xC3D2E1F0; + var h4 = 0xc3d2e1f0; // Pre-processing: @@ -63,7 +84,9 @@ function sha1(text) // append (0 <= k < 512) bits '0', so that the resulting message length (in bits) is congruent to 448 = -64 (mod 512) while ((message.length + 8) % 64) + { message.push(0); + }; // append length of message (before pre-processing), in bits, as 64-bit big-endian integer message = message.concat(num_to_big_endian_64(message_size_in_bits)); @@ -71,11 +94,82 @@ function sha1(text) // Process the message in successive 512-bit chunks: // break message into 512-bit chunks - for (var i_chunk = 0; i_chunk < (message.length/8); i_chunk++) + for (var i_chunk = 0; i_chunk < (message.length/64); i_chunk++) { // break chunk into sixteen 32-bit big-endian words w[i], 0 <= i <= 15 - var w = bytes_to_big_endian_32(message); + var w = bytes_to_big_endian_32(message.slice(i_chunk*64,(i_chunk*64)+64)); + + // Extend the sixteen 32-bit words into eighty 32-bit words: + for (var i = 16; i < 80; i++) + { + w.push(rol((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1)); + }; + + // Initialize hash value for this chunk: + var a = h0; + var b = h1; + var c = h2; + var d = h3; + var e = h4; + var f = 0; + var k = 0; + + // Main loop: + for (var i = 0; i < 80; i++) + { + if (i < 20) + { + f = d ^ (b & (c ^ d)); + k = 0x5a827999; + } + else if (i < 40) + { + f = b ^ c ^ d; + k = 0x6ed9eba1; + } + else if (i < 60) + { + f = (b & c) | (b & d) | (c & d); + k = 0x8f1bbcdc; + } + else + { + f = b ^ c ^ d; + k = 0xca62c1d6; + } + + var temp = (rol(a,5) + f + e + k + w[i]) & 0xffffffff; + e = d; + d = c; + c = rol(b,30); + b = a; + a = temp; + }; + + // Add this chunk's hash to result so far: + h0 = (h0 + a) & 0xffffffff; + h1 = (h1 + b) & 0xffffffff; + h2 = (h2 + c) & 0xffffffff; + h3 = (h3 + d) & 0xffffffff; + h4 = (h4 + e) & 0xffffffff; + }; + + // Produce the final hash value (big-endian): + return to_hex(h0) + to_hex(h1) + to_hex(h2) + to_hex(h3) + to_hex(h4); +} + +function sha1_verify() +{ + return Boolean( + (sha1("The quick brown fox jumps over the lazy dog") == "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12") && + (sha1("") == "da39a3ee5e6b4b0d3255bfef95601890afd80709") + ); +} + +function sha1_profile() +{ + var text = "blah"; + for (var i = 0; i < 250; i++) { + text = sha1(text); }; - - return message; }