-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmd5.js
351 lines (301 loc) · 14.1 KB
/
md5.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/*
Javascript MD5 library - version 0.4
Coded (2011) by Luigi Galli - [email protected] - http://faultylabs.com
Thanks to: Roberto Viola
The below code is PUBLIC DOMAIN - NO WARRANTY!
Changelog:
Version 0.4 - 2011-06-19
+ added compact version (md5_compact_min.js), this is a slower but smaller version
(more than 4KB lighter before stripping/minification)
+ added preliminary support for Typed Arrays (see:
https://developer.mozilla.org/en/JavaScript_typed_arrays and
http://www.khronos.org/registry/typedarray/specs/latest/)
MD5() now accepts input data as ArrayBuffer, Float32Array, Float64Array,
Int16Array, Int32Array, Int8Array, Uint16Array, Uint32Array or Uint8Array
- moved unit tests to md5_test.js
- minor refactoring
Version 0.3.* - 2011-06-##
- Internal dev versions
Version 0.2 - 2011-05-22
** FIXED: serious integer overflow problems which could cause a wrong MD5 hash being returned
Version 0.1 - 2011
-Initial version
*/
if (typeof faultylabs == 'undefined') {
faultylabs = {}
}
/*
MD5()
Computes the MD5 hash for the given input data
input : data as String - (Assumes Unicode code points are encoded as UTF-8. If you
attempt to digest Unicode strings using other encodings
you will get incorrect results!)
data as array of characters - (Assumes Unicode code points are encoded as UTF-8. If you
attempt to digest Unicode strings using other encodings
you will get incorrect results!)
data as array of bytes (plain javascript array of integer numbers)
data as ArrayBuffer (see: https://developer.mozilla.org/en/JavaScript_typed_arrays)
data as Float32Array, Float64Array, Int16Array, Int32Array, Int8Array, Uint16Array, Uint32Array or Uint8Array (see: https://developer.mozilla.org/en/JavaScript_typed_arrays)
(DataView is not supported yet)
output: MD5 hash (as Hex Uppercase String)
*/
faultylabs.MD5 = function(data) {
// convert number to (unsigned) 32 bit hex, zero filled string
function to_zerofilled_hex(n) {
var t1 = (n >>> 0).toString(16)
return "00000000".substr(0, 8 - t1.length) + t1
}
// convert array of chars to array of bytes
function chars_to_bytes(ac) {
var retval = []
for (var i = 0; i < ac.length; i++) {
retval = retval.concat(str_to_bytes(ac[i]))
}
return retval
}
// convert a 64 bit unsigned number to array of bytes. Little endian
function int64_to_bytes(num) {
var retval = []
for (var i = 0; i < 8; i++) {
retval.push(num & 0xFF)
num = num >>> 8
}
return retval
}
// 32 bit left-rotation
function rol(num, places) {
return ((num << places) & 0xFFFFFFFF) | (num >>> (32 - places))
}
// The 4 MD5 functions
function fF(b, c, d) {
return (b & c) | (~b & d)
}
function fG(b, c, d) {
return (d & b) | (~d & c)
}
function fH(b, c, d) {
return b ^ c ^ d
}
function fI(b, c, d) {
return c ^ (b | ~d)
}
// pick 4 bytes at specified offset. Little-endian is assumed
function bytes_to_int32(arr, off) {
return (arr[off + 3] << 24) | (arr[off + 2] << 16) | (arr[off + 1] << 8) | (arr[off])
}
/*
Conver string to array of bytes in UTF-8 encoding
See:
http://www.dangrossman.info/2007/05/25/handling-utf-8-in-javascript-php-and-non-utf8-databases/
http://stackoverflow.com/questions/1240408/reading-bytes-from-a-javascript-string
How about a String.getBytes(<ENCODING>) for Javascript!? Isn't it time to add it?
*/
function str_to_bytes(str) {
var retval = [ ]
for (var i = 0; i < str.length; i++)
if (str.charCodeAt(i) <= 0x7F) {
retval.push(str.charCodeAt(i))
} else {
var tmp = encodeURIComponent(str.charAt(i)).substr(1).split('%')
for (var j = 0; j < tmp.length; j++) {
retval.push(parseInt(tmp[j], 0x10))
}
}
return retval
}
// convert the 4 32-bit buffers to a 128 bit hex string. (Little-endian is assumed)
function int128le_to_hex(a, b, c, d) {
var ra = ""
var t = 0
var ta = 0
for (var i = 3; i >= 0; i--) {
ta = arguments[i]
t = (ta & 0xFF)
ta = ta >>> 8
t = t << 8
t = t | (ta & 0xFF)
ta = ta >>> 8
t = t << 8
t = t | (ta & 0xFF)
ta = ta >>> 8
t = t << 8
t = t | ta
ra = ra + to_zerofilled_hex(t)
}
return ra
}
// conversion from typed byte array to plain javascript array
function typed_to_plain(tarr) {
var retval = new Array(tarr.length)
for (var i = 0; i < tarr.length; i++) {
retval[i] = tarr[i]
}
return retval
}
// check input data type and perform conversions if needed
var databytes = null
// String
var type_mismatch = null
if (typeof data == 'string') {
// convert string to array bytes
databytes = str_to_bytes(data)
} else if (data.constructor == Array) {
if (data.length === 0) {
// if it's empty, just assume array of bytes
databytes = data
} else if (typeof data[0] == 'string') {
databytes = chars_to_bytes(data)
} else if (typeof data[0] == 'number') {
databytes = data
} else {
type_mismatch = typeof data[0]
}
} else if (typeof ArrayBuffer != 'undefined') {
if (data instanceof ArrayBuffer) {
databytes = typed_to_plain(new Uint8Array(data))
} else if ((data instanceof Uint8Array) || (data instanceof Int8Array)) {
databytes = typed_to_plain(data)
} else if ((data instanceof Uint32Array) || (data instanceof Int32Array) ||
(data instanceof Uint16Array) || (data instanceof Int16Array) ||
(data instanceof Float32Array) || (data instanceof Float64Array)
) {
databytes = typed_to_plain(new Uint8Array(data.buffer))
} else {
type_mismatch = typeof data
}
} else {
type_mismatch = typeof data
}
if (type_mismatch) {
alert('MD5 type mismatch, cannot process ' + type_mismatch)
}
function _add(n1, n2) {
return 0x0FFFFFFFF & (n1 + n2)
}
return do_digest()
function do_digest() {
// function update partial state for each run
function updateRun(nf, sin32, dw32, b32) {
var temp = d
d = c
c = b
//b = b + rol(a + (nf + (sin32 + dw32)), b32)
b = _add(b,
rol(
_add(a,
_add(nf, _add(sin32, dw32))
), b32
)
)
a = temp
}
// save original length
var org_len = databytes.length
// first append the "1" + 7x "0"
databytes.push(0x80)
// determine required amount of padding
var tail = databytes.length % 64
// no room for msg length?
if (tail > 56) {
// pad to next 512 bit block
for (var i = 0; i < (64 - tail); i++) {
databytes.push(0x0)
}
tail = databytes.length % 64
}
for (i = 0; i < (56 - tail); i++) {
databytes.push(0x0)
}
// message length in bits mod 512 should now be 448
// append 64 bit, little-endian original msg length (in *bits*!)
databytes = databytes.concat(int64_to_bytes(org_len * 8))
// initialize 4x32 bit state
var h0 = 0x67452301
var h1 = 0xEFCDAB89
var h2 = 0x98BADCFE
var h3 = 0x10325476
// temp buffers
var a = 0, b = 0, c = 0, d = 0
// Digest message
for (i = 0; i < databytes.length / 64; i++) {
// initialize run
a = h0
b = h1
c = h2
d = h3
var ptr = i * 64
// do 64 runs
updateRun(fF(b, c, d), 0xd76aa478, bytes_to_int32(databytes, ptr), 7)
updateRun(fF(b, c, d), 0xe8c7b756, bytes_to_int32(databytes, ptr + 4), 12)
updateRun(fF(b, c, d), 0x242070db, bytes_to_int32(databytes, ptr + 8), 17)
updateRun(fF(b, c, d), 0xc1bdceee, bytes_to_int32(databytes, ptr + 12), 22)
updateRun(fF(b, c, d), 0xf57c0faf, bytes_to_int32(databytes, ptr + 16), 7)
updateRun(fF(b, c, d), 0x4787c62a, bytes_to_int32(databytes, ptr + 20), 12)
updateRun(fF(b, c, d), 0xa8304613, bytes_to_int32(databytes, ptr + 24), 17)
updateRun(fF(b, c, d), 0xfd469501, bytes_to_int32(databytes, ptr + 28), 22)
updateRun(fF(b, c, d), 0x698098d8, bytes_to_int32(databytes, ptr + 32), 7)
updateRun(fF(b, c, d), 0x8b44f7af, bytes_to_int32(databytes, ptr + 36), 12)
updateRun(fF(b, c, d), 0xffff5bb1, bytes_to_int32(databytes, ptr + 40), 17)
updateRun(fF(b, c, d), 0x895cd7be, bytes_to_int32(databytes, ptr + 44), 22)
updateRun(fF(b, c, d), 0x6b901122, bytes_to_int32(databytes, ptr + 48), 7)
updateRun(fF(b, c, d), 0xfd987193, bytes_to_int32(databytes, ptr + 52), 12)
updateRun(fF(b, c, d), 0xa679438e, bytes_to_int32(databytes, ptr + 56), 17)
updateRun(fF(b, c, d), 0x49b40821, bytes_to_int32(databytes, ptr + 60), 22)
updateRun(fG(b, c, d), 0xf61e2562, bytes_to_int32(databytes, ptr + 4), 5)
updateRun(fG(b, c, d), 0xc040b340, bytes_to_int32(databytes, ptr + 24), 9)
updateRun(fG(b, c, d), 0x265e5a51, bytes_to_int32(databytes, ptr + 44), 14)
updateRun(fG(b, c, d), 0xe9b6c7aa, bytes_to_int32(databytes, ptr), 20)
updateRun(fG(b, c, d), 0xd62f105d, bytes_to_int32(databytes, ptr + 20), 5)
updateRun(fG(b, c, d), 0x2441453, bytes_to_int32(databytes, ptr + 40), 9)
updateRun(fG(b, c, d), 0xd8a1e681, bytes_to_int32(databytes, ptr + 60), 14)
updateRun(fG(b, c, d), 0xe7d3fbc8, bytes_to_int32(databytes, ptr + 16), 20)
updateRun(fG(b, c, d), 0x21e1cde6, bytes_to_int32(databytes, ptr + 36), 5)
updateRun(fG(b, c, d), 0xc33707d6, bytes_to_int32(databytes, ptr + 56), 9)
updateRun(fG(b, c, d), 0xf4d50d87, bytes_to_int32(databytes, ptr + 12), 14)
updateRun(fG(b, c, d), 0x455a14ed, bytes_to_int32(databytes, ptr + 32), 20)
updateRun(fG(b, c, d), 0xa9e3e905, bytes_to_int32(databytes, ptr + 52), 5)
updateRun(fG(b, c, d), 0xfcefa3f8, bytes_to_int32(databytes, ptr + 8), 9)
updateRun(fG(b, c, d), 0x676f02d9, bytes_to_int32(databytes, ptr + 28), 14)
updateRun(fG(b, c, d), 0x8d2a4c8a, bytes_to_int32(databytes, ptr + 48), 20)
updateRun(fH(b, c, d), 0xfffa3942, bytes_to_int32(databytes, ptr + 20), 4)
updateRun(fH(b, c, d), 0x8771f681, bytes_to_int32(databytes, ptr + 32), 11)
updateRun(fH(b, c, d), 0x6d9d6122, bytes_to_int32(databytes, ptr + 44), 16)
updateRun(fH(b, c, d), 0xfde5380c, bytes_to_int32(databytes, ptr + 56), 23)
updateRun(fH(b, c, d), 0xa4beea44, bytes_to_int32(databytes, ptr + 4), 4)
updateRun(fH(b, c, d), 0x4bdecfa9, bytes_to_int32(databytes, ptr + 16), 11)
updateRun(fH(b, c, d), 0xf6bb4b60, bytes_to_int32(databytes, ptr + 28), 16)
updateRun(fH(b, c, d), 0xbebfbc70, bytes_to_int32(databytes, ptr + 40), 23)
updateRun(fH(b, c, d), 0x289b7ec6, bytes_to_int32(databytes, ptr + 52), 4)
updateRun(fH(b, c, d), 0xeaa127fa, bytes_to_int32(databytes, ptr), 11)
updateRun(fH(b, c, d), 0xd4ef3085, bytes_to_int32(databytes, ptr + 12), 16)
updateRun(fH(b, c, d), 0x4881d05, bytes_to_int32(databytes, ptr + 24), 23)
updateRun(fH(b, c, d), 0xd9d4d039, bytes_to_int32(databytes, ptr + 36), 4)
updateRun(fH(b, c, d), 0xe6db99e5, bytes_to_int32(databytes, ptr + 48), 11)
updateRun(fH(b, c, d), 0x1fa27cf8, bytes_to_int32(databytes, ptr + 60), 16)
updateRun(fH(b, c, d), 0xc4ac5665, bytes_to_int32(databytes, ptr + 8), 23)
updateRun(fI(b, c, d), 0xf4292244, bytes_to_int32(databytes, ptr), 6)
updateRun(fI(b, c, d), 0x432aff97, bytes_to_int32(databytes, ptr + 28), 10)
updateRun(fI(b, c, d), 0xab9423a7, bytes_to_int32(databytes, ptr + 56), 15)
updateRun(fI(b, c, d), 0xfc93a039, bytes_to_int32(databytes, ptr + 20), 21)
updateRun(fI(b, c, d), 0x655b59c3, bytes_to_int32(databytes, ptr + 48), 6)
updateRun(fI(b, c, d), 0x8f0ccc92, bytes_to_int32(databytes, ptr + 12), 10)
updateRun(fI(b, c, d), 0xffeff47d, bytes_to_int32(databytes, ptr + 40), 15)
updateRun(fI(b, c, d), 0x85845dd1, bytes_to_int32(databytes, ptr + 4), 21)
updateRun(fI(b, c, d), 0x6fa87e4f, bytes_to_int32(databytes, ptr + 32), 6)
updateRun(fI(b, c, d), 0xfe2ce6e0, bytes_to_int32(databytes, ptr + 60), 10)
updateRun(fI(b, c, d), 0xa3014314, bytes_to_int32(databytes, ptr + 24), 15)
updateRun(fI(b, c, d), 0x4e0811a1, bytes_to_int32(databytes, ptr + 52), 21)
updateRun(fI(b, c, d), 0xf7537e82, bytes_to_int32(databytes, ptr + 16), 6)
updateRun(fI(b, c, d), 0xbd3af235, bytes_to_int32(databytes, ptr + 44), 10)
updateRun(fI(b, c, d), 0x2ad7d2bb, bytes_to_int32(databytes, ptr + 8), 15)
updateRun(fI(b, c, d), 0xeb86d391, bytes_to_int32(databytes, ptr + 36), 21)
// update buffers
h0 = _add(h0, a)
h1 = _add(h1, b)
h2 = _add(h2, c)
h3 = _add(h3, d)
}
// Done! Convert buffers to 128 bit (LE)
return int128le_to_hex(h3, h2, h1, h0).toUpperCase()
}
}