cc352d0123c8528bbcc04dc8eb9f28868042ef51
[sha1.git] / sha1.js
1 var Sha1 = {}; // SHA-1 namespace
2
3 // SHA-1 algorithm as described at http://en.wikipedia.org/wiki/SHA-1
4 // The implementation follows http://fr.wikipedia.org/wiki/Sp%C3%A9cifications_SHA-1 (in french).
5 // SHA-1 implementation of Chris Veness 2002-2010 [www.movable-type.co.uk] helped a lot for debugging,
6 // and for hacks like toHexStr(). See his script at http://www.movable-type.co.uk/scripts/sha1.html
7 Sha1.Compute = function(subject)
8 {
9 var i, j, tmp, redIndex, a, b, c, d, e;
10
11 // 1) pretreatment
12
13 // note: no check on message length, since the 2^64 boundary is
14 // a lot longer than what would be allowed by HTML/PHP
15
16 // add trailing '1' bit (+ 0's padding) to string
17 subject += String.fromCharCode(0x80);
18
19 // add 8 for two last reserved words to store message length
20 // 8 = 2 x 4, one 32-bits word is 4 characters (bytes) length.
21 var L = subject.length + 8;
22
23 // initialize 512-bits blocks representing the message, each containing 16 32-bits words.
24 // NOTE: one char is 8 bits, so one block in the initial string is 64 chars.
25 var countBlocks = Math.ceil(L / 64);
26 var blocks = new Array(countBlocks);
27 for (i=0; i<countBlocks; i++)
28 {
29 var words = new Array(16);
30 for (j=0; j<16; j++)
31 {
32 tmp = subject.substr(64 * i + 4 * j, 4);
33 // note: running off the end of msg is ok because bitwise ops on NaN return 0
34 words[j] = (1 << 24) * tmp.charCodeAt(0) | (1 << 16) * tmp.charCodeAt(1) | (1 << 8) * tmp.charCodeAt(2) | tmp.charCodeAt(3);
35 }
36 blocks[i] = words;
37 }
38
39 // note: 'subject' in our context will never be of length >= 2^32.
40 // therefore we don't need to fill before-last block.
41 blocks[countBlocks-1][15] = (subject.length-1) * 8;
42
43 // initialize parts of the final hash
44 var h0 = 0x67452301;
45 var h1 = 0xefcdab89;
46 var h2 = 0x98badcfe;
47 var h3 = 0x10325476;
48 var h4 = 0xc3d2e1f0;
49
50 // initialize constants array
51 var k = [0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6];
52
53 // 2) computations
54
55 for (i=0; i<blocks.length; i++)
56 {
57 // initialize w array
58 var w = new Array(80);
59 for (j=0; j<16; j++) w[j] = blocks[i][j];
60 for (j=16; j<80; j++)
61 {
62 w[j] = Sha1.LeftRotate(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
63 }
64
65 // initialize a,b,c,d,e variables
66 a = h0;
67 b = h1;
68 c = h2;
69 d = h3;
70 e = h4;
71
72 // iterations over a,b,c,d,e
73 for (j=0; j<80; j++)
74 {
75 // note: '& 0xffffffff' == 'modulo 2^32'.
76 redIndex = Math.floor(j/20);
77 tmp = (Sha1.LeftRotate(a, 5) + Sha1.BitOp(b, c, d, redIndex) + e + k[redIndex] + w[j]) & 0xffffffff;
78 e = d;
79 d = c;
80 c = Sha1.LeftRotate(b, 30);
81 b = a;
82 a = tmp;
83 }
84
85 // update intermediate hash values
86 h0 = (h0+a) & 0xffffffff;
87 h1 = (h1+b) & 0xffffffff;
88 h2 = (h2+c) & 0xffffffff;
89 h3 = (h3+d) & 0xffffffff;
90 h4 = (h4+e) & 0xffffffff;
91 }
92
93 return Sha1.ToHexStr(h0)+Sha1.ToHexStr(h1)+Sha1.ToHexStr(h2)+Sha1.ToHexStr(h3)+Sha1.ToHexStr(h4);
94 }
95
96 // auxiliary functions.
97 Sha1.BitOp = function(x, y, z, t)
98 {
99 if (t == 0) return (x & y) ^ (~x & z);
100 if (t == 1) return x ^ y ^ z;
101 if (t == 2) return (x & y) ^ (x & z) ^ (y & z);
102 if (t == 3) return x ^ y ^ z;
103 }
104
105 // left rotation (within 32 bits).
106 Sha1.LeftRotate = function(x, n)
107 {
108 return (x << n) | (x >>> (32 - n));
109 }
110
111 // [copy-pasted from Chris Veness implementation]
112 // Hexadecimal representation of a number
113 // (note toString(16) is implementation-dependant, and
114 // in IE returns signed numbers when used on full words)
115 Sha1.ToHexStr = function(x)
116 {
117 var s="";
118 for (var i=7; i>=0; i--)
119 {
120 var v = (x >>> (i*4)) & 0xf;
121 s += v.toString(16);
122 }
123 return s;
124 }
125
126 try { module.exports = Sha1; } catch (err) { }