1 | define(["./_sha-32"], function(sha32){ |
---|
2 | // basic functions for 64-bit word based SHA-2 processing. Includes |
---|
3 | // a constructor for int64. Relies on the sha32 base for encoding functions, |
---|
4 | // but provides its own, making it easier for the user to not worry about 64-bit |
---|
5 | // word handling. |
---|
6 | |
---|
7 | var int64 = function(h, l){ return { h: h, l: l }; }; |
---|
8 | |
---|
9 | // 64-bit math functions |
---|
10 | function copy(dst, src){ |
---|
11 | dst.h = src.h; |
---|
12 | dst.l = src.l; |
---|
13 | } |
---|
14 | |
---|
15 | //Right-rotates a 64-bit number by shift |
---|
16 | function rrot(dst, x, shift){ |
---|
17 | dst.l = (x.l >>> shift) | (x.h << (32-shift)); |
---|
18 | dst.h = (x.h >>> shift) | (x.l << (32-shift)); |
---|
19 | } |
---|
20 | |
---|
21 | //Reverses the dwords of the source and then rotates right by shift. |
---|
22 | function revrrot(dst, x, shift){ |
---|
23 | dst.l = (x.h >>> shift) | (x.l << (32-shift)); |
---|
24 | dst.h = (x.l >>> shift) | (x.h << (32-shift)); |
---|
25 | } |
---|
26 | |
---|
27 | //Bitwise-shifts right a 64-bit number by shift |
---|
28 | function shr(dst, x, shift){ |
---|
29 | dst.l = (x.l >>> shift) | (x.h << (32-shift)); |
---|
30 | dst.h = (x.h >>> shift); |
---|
31 | } |
---|
32 | |
---|
33 | //Adds two 64-bit numbers |
---|
34 | function add(dst, x, y){ |
---|
35 | var w0 = (x.l & 0xffff) + (y.l & 0xffff); |
---|
36 | var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16); |
---|
37 | var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16); |
---|
38 | var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16); |
---|
39 | dst.l = (w0 & 0xffff) | (w1 << 16); |
---|
40 | dst.h = (w2 & 0xffff) | (w3 << 16); |
---|
41 | } |
---|
42 | |
---|
43 | //Same, except with 4 addends. Works faster than adding them one by one. |
---|
44 | function add4(dst, a, b, c, d){ |
---|
45 | var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff); |
---|
46 | var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16); |
---|
47 | var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16); |
---|
48 | var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16); |
---|
49 | dst.l = (w0 & 0xffff) | (w1 << 16); |
---|
50 | dst.h = (w2 & 0xffff) | (w3 << 16); |
---|
51 | } |
---|
52 | |
---|
53 | //Same, except with 5 addends |
---|
54 | function add5(dst, a, b, c, d, e){ |
---|
55 | var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff); |
---|
56 | var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16); |
---|
57 | var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16); |
---|
58 | var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16); |
---|
59 | dst.l = (w0 & 0xffff) | (w1 << 16); |
---|
60 | dst.h = (w2 & 0xffff) | (w3 << 16); |
---|
61 | } |
---|
62 | |
---|
63 | // constants |
---|
64 | var K = [ |
---|
65 | int64(0x428a2f98, 0xd728ae22), int64(0x71374491, 0x23ef65cd), int64(0xb5c0fbcf, 0xec4d3b2f), int64(0xe9b5dba5, 0x8189dbbc), |
---|
66 | int64(0x3956c25b, 0xf348b538), int64(0x59f111f1, 0xb605d019), int64(0x923f82a4, 0xaf194f9b), int64(0xab1c5ed5, 0xda6d8118), |
---|
67 | int64(0xd807aa98, 0xa3030242), int64(0x12835b01, 0x45706fbe), int64(0x243185be, 0x4ee4b28c), int64(0x550c7dc3, 0xd5ffb4e2), |
---|
68 | int64(0x72be5d74, 0xf27b896f), int64(0x80deb1fe, 0x3b1696b1), int64(0x9bdc06a7, 0x25c71235), int64(0xc19bf174, 0xcf692694), |
---|
69 | int64(0xe49b69c1, 0x9ef14ad2), int64(0xefbe4786, 0x384f25e3), int64(0x0fc19dc6, 0x8b8cd5b5), int64(0x240ca1cc, 0x77ac9c65), |
---|
70 | int64(0x2de92c6f, 0x592b0275), int64(0x4a7484aa, 0x6ea6e483), int64(0x5cb0a9dc, 0xbd41fbd4), int64(0x76f988da, 0x831153b5), |
---|
71 | int64(0x983e5152, 0xee66dfab), int64(0xa831c66d, 0x2db43210), int64(0xb00327c8, 0x98fb213f), int64(0xbf597fc7, 0xbeef0ee4), |
---|
72 | int64(0xc6e00bf3, 0x3da88fc2), int64(0xd5a79147, 0x930aa725), int64(0x06ca6351, 0xe003826f), int64(0x14292967, 0x0a0e6e70), |
---|
73 | int64(0x27b70a85, 0x46d22ffc), int64(0x2e1b2138, 0x5c26c926), int64(0x4d2c6dfc, 0x5ac42aed), int64(0x53380d13, 0x9d95b3df), |
---|
74 | int64(0x650a7354, 0x8baf63de), int64(0x766a0abb, 0x3c77b2a8), int64(0x81c2c92e, 0x47edaee6), int64(0x92722c85, 0x1482353b), |
---|
75 | int64(0xa2bfe8a1, 0x4cf10364), int64(0xa81a664b, 0xbc423001), int64(0xc24b8b70, 0xd0f89791), int64(0xc76c51a3, 0x0654be30), |
---|
76 | int64(0xd192e819, 0xd6ef5218), int64(0xd6990624, 0x5565a910), int64(0xf40e3585, 0x5771202a), int64(0x106aa070, 0x32bbd1b8), |
---|
77 | int64(0x19a4c116, 0xb8d2d0c8), int64(0x1e376c08, 0x5141ab53), int64(0x2748774c, 0xdf8eeb99), int64(0x34b0bcb5, 0xe19b48a8), |
---|
78 | int64(0x391c0cb3, 0xc5c95a63), int64(0x4ed8aa4a, 0xe3418acb), int64(0x5b9cca4f, 0x7763e373), int64(0x682e6ff3, 0xd6b2b8a3), |
---|
79 | int64(0x748f82ee, 0x5defb2fc), int64(0x78a5636f, 0x43172f60), int64(0x84c87814, 0xa1f0ab72), int64(0x8cc70208, 0x1a6439ec), |
---|
80 | int64(0x90befffa, 0x23631e28), int64(0xa4506ceb, 0xde82bde9), int64(0xbef9a3f7, 0xb2c67915), int64(0xc67178f2, 0xe372532b), |
---|
81 | int64(0xca273ece, 0xea26619c), int64(0xd186b8c7, 0x21c0c207), int64(0xeada7dd6, 0xcde0eb1e), int64(0xf57d4f7f, 0xee6ed178), |
---|
82 | int64(0x06f067aa, 0x72176fba), int64(0x0a637dc5, 0xa2c898a6), int64(0x113f9804, 0xbef90dae), int64(0x1b710b35, 0x131c471b), |
---|
83 | int64(0x28db77f5, 0x23047d84), int64(0x32caab7b, 0x40c72493), int64(0x3c9ebe0a, 0x15c9bebc), int64(0x431d67c4, 0x9c100d4c), |
---|
84 | int64(0x4cc5d4be, 0xcb3e42b6), int64(0x597f299c, 0xfc657e2a), int64(0x5fcb6fab, 0x3ad6faec), int64(0x6c44198c, 0x4a475817) |
---|
85 | ]; |
---|
86 | |
---|
87 | // our return object |
---|
88 | var o = { |
---|
89 | outputTypes: sha32.outputTypes, |
---|
90 | stringToUtf8: function(s){ return sha32.stringToUtf8(s); }, |
---|
91 | toWord: function(s){ return sha32.toWord(s); }, |
---|
92 | toHex: function(wa){ return sha32.toHex(wa); }, |
---|
93 | toBase64: function(wa){ return sha32.toBase64(wa); }, |
---|
94 | _toString: function(wa){ return sha32._toString(wa); } |
---|
95 | }; |
---|
96 | |
---|
97 | // the main function |
---|
98 | o.digest = function(msg, length, hash, depth){ |
---|
99 | // prep the hash |
---|
100 | var HASH = []; |
---|
101 | for(var i=0, l=hash.length; i<l; i+=2){ |
---|
102 | HASH.push(int64(hash[i], hash[i+1])); |
---|
103 | } |
---|
104 | |
---|
105 | // initialize our variables |
---|
106 | var T1 = int64(0,0), |
---|
107 | T2 = int64(0,0), |
---|
108 | a = int64(0,0), |
---|
109 | b = int64(0,0), |
---|
110 | c = int64(0,0), |
---|
111 | d = int64(0,0), |
---|
112 | e = int64(0,0), |
---|
113 | f = int64(0,0), |
---|
114 | g = int64(0,0), |
---|
115 | h = int64(0,0), |
---|
116 | s0 = int64(0,0), |
---|
117 | s1 = int64(0,0), |
---|
118 | Ch = int64(0,0), |
---|
119 | Maj = int64(0,0), |
---|
120 | r1 = int64(0,0), |
---|
121 | r2 = int64(0,0), |
---|
122 | r3 = int64(0,0); |
---|
123 | var j, i; |
---|
124 | var w = new Array(80); |
---|
125 | for(i=0; i<80; i++) w[i] = int64(0, 0); |
---|
126 | |
---|
127 | // append padding to the source string. |
---|
128 | msg[length >> 5] |= 0x80 << (24 - (length & 0x1f)); |
---|
129 | msg[((length + 128 >> 10)<< 5) + 31] = length; |
---|
130 | |
---|
131 | for(i=0; i<msg.length; i+=32){ |
---|
132 | copy(a, HASH[0]); |
---|
133 | copy(b, HASH[1]); |
---|
134 | copy(c, HASH[2]); |
---|
135 | copy(d, HASH[3]); |
---|
136 | copy(e, HASH[4]); |
---|
137 | copy(f, HASH[5]); |
---|
138 | copy(g, HASH[6]); |
---|
139 | copy(h, HASH[7]); |
---|
140 | |
---|
141 | for(j=0; j<16; j++){ |
---|
142 | w[j].h = msg[i + 2*j]; |
---|
143 | w[j].l = msg[i + 2*j + 1]; |
---|
144 | } |
---|
145 | |
---|
146 | for(j=16; j<80; j++){ |
---|
147 | //sigma1 |
---|
148 | rrot(r1, w[j-2], 19); |
---|
149 | revrrot(r2, w[j-2], 29); |
---|
150 | shr(r3, w[j-2], 6); |
---|
151 | s1.l = r1.l ^ r2.l ^ r3.l; |
---|
152 | s1.h = r1.h ^ r2.h ^ r3.h; |
---|
153 | |
---|
154 | //sigma0 |
---|
155 | rrot(r1, w[j-15], 1); |
---|
156 | rrot(r2, w[j-15], 8); |
---|
157 | shr(r3, w[j-15], 7); |
---|
158 | s0.l = r1.l ^ r2.l ^ r3.l; |
---|
159 | s0.h = r1.h ^ r2.h ^ r3.h; |
---|
160 | |
---|
161 | add4(w[j], s1, w[j-7], s0, w[j-16]); |
---|
162 | } |
---|
163 | |
---|
164 | for(j = 0; j < 80; j++){ |
---|
165 | //Ch |
---|
166 | Ch.l = (e.l & f.l) ^ (~e.l & g.l); |
---|
167 | Ch.h = (e.h & f.h) ^ (~e.h & g.h); |
---|
168 | |
---|
169 | //Sigma1 |
---|
170 | rrot(r1, e, 14); |
---|
171 | rrot(r2, e, 18); |
---|
172 | revrrot(r3, e, 9); |
---|
173 | s1.l = r1.l ^ r2.l ^ r3.l; |
---|
174 | s1.h = r1.h ^ r2.h ^ r3.h; |
---|
175 | |
---|
176 | //Sigma0 |
---|
177 | rrot(r1, a, 28); |
---|
178 | revrrot(r2, a, 2); |
---|
179 | revrrot(r3, a, 7); |
---|
180 | s0.l = r1.l ^ r2.l ^ r3.l; |
---|
181 | s0.h = r1.h ^ r2.h ^ r3.h; |
---|
182 | |
---|
183 | //Maj |
---|
184 | Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l); |
---|
185 | Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h); |
---|
186 | |
---|
187 | add5(T1, h, s1, Ch, K[j], w[j]); |
---|
188 | add(T2, s0, Maj); |
---|
189 | |
---|
190 | copy(h, g); |
---|
191 | copy(g, f); |
---|
192 | copy(f, e); |
---|
193 | add(e, d, T1); |
---|
194 | copy(d, c); |
---|
195 | copy(c, b); |
---|
196 | copy(b, a); |
---|
197 | add(a, T1, T2); |
---|
198 | } |
---|
199 | |
---|
200 | add(HASH[0], HASH[0], a); |
---|
201 | add(HASH[1], HASH[1], b); |
---|
202 | add(HASH[2], HASH[2], c); |
---|
203 | add(HASH[3], HASH[3], d); |
---|
204 | add(HASH[4], HASH[4], e); |
---|
205 | add(HASH[5], HASH[5], f); |
---|
206 | add(HASH[6], HASH[6], g); |
---|
207 | add(HASH[7], HASH[7], h); |
---|
208 | } |
---|
209 | |
---|
210 | // convert the final hash back to 32-bit words |
---|
211 | var ret = []; |
---|
212 | if(depth == 384){ HASH.length = 6; } |
---|
213 | for(var i=0, l=HASH.length; i<l; i++){ |
---|
214 | ret[i*2] = HASH[i].h; |
---|
215 | ret[i*2+1] = HASH[i].l; |
---|
216 | } |
---|
217 | return ret; |
---|
218 | }; |
---|
219 | |
---|
220 | return o; |
---|
221 | }); |
---|