colonymech / docs / www / colonyscout / internal / includes / uploadify / com / adobe / crypto / MD5Stream.as @ f59acf11
History | View | Annotate | Download (16.2 KB)
1 |
/* |
---|---|
2 |
Copyright (c) 2008, Adobe Systems Incorporated |
3 |
All rights reserved. |
4 |
|
5 |
Redistribution and use in source and binary forms, with or without |
6 |
modification, are permitted provided that the following conditions are |
7 |
met: |
8 |
|
9 |
* Redistributions of source code must retain the above copyright notice, |
10 |
this list of conditions and the following disclaimer. |
11 |
|
12 |
* Redistributions in binary form must reproduce the above copyright |
13 |
notice, this list of conditions and the following disclaimer in the |
14 |
documentation and/or other materials provided with the distribution. |
15 |
|
16 |
* Neither the name of Adobe Systems Incorporated nor the names of its |
17 |
contributors may be used to endorse or promote products derived from |
18 |
this software without specific prior written permission. |
19 |
|
20 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
21 |
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
22 |
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 |
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
24 |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
25 |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
26 |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
27 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
28 |
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
29 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
30 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 |
*/ |
32 |
|
33 |
package com.adobe.crypto |
34 |
{ |
35 |
import com.adobe.utils.IntUtil; |
36 |
import flash.utils.ByteArray; |
37 |
|
38 |
/** |
39 |
* Perform MD5 hash of an input stream in chunks. This class is |
40 |
* based on com.adobe.crypto.MD5 and can process data in |
41 |
* chunks. Both block creation and hash computation are done |
42 |
* together for whatever input is available so that the memory |
43 |
* overhead at a time is always fixed. Memory usage is governed by |
44 |
* two parameters: one is the amount of data passed in to update() |
45 |
* and the other is memoryBlockSize. The latter comes into play |
46 |
* only when the memory window exceeds the pre allocated memory |
47 |
* window of flash player. Usage: create an instance, call |
48 |
* update(data) repeatedly for all chunks and finally complete() |
49 |
* which will return the md5 hash. |
50 |
*/ |
51 |
public class MD5Stream |
52 |
{ |
53 |
private static var mask:int = 0xFF; |
54 |
|
55 |
private var arr:Array = []; |
56 |
|
57 |
/* running count of length */ |
58 |
private var arrLen:int; |
59 |
|
60 |
// initialize the md buffers |
61 |
private var a:int = 1732584193; |
62 |
private var b:int = -271733879; |
63 |
private var c:int = -1732584194; |
64 |
private var d:int = 271733878; |
65 |
|
66 |
// variables to store previous values |
67 |
private var aa:int; |
68 |
private var bb:int; |
69 |
private var cc:int; |
70 |
private var dd:int; |
71 |
|
72 |
/* index for data read */ |
73 |
private var arrIndexLen:int = 0; |
74 |
/* index for hash computation */ |
75 |
private var arrProcessIndex:int = 0; |
76 |
/* index for removing stale arr values */ |
77 |
private var cleanIndex:int = 0; |
78 |
|
79 |
/** |
80 |
* Change this value from the default (16384) in the range of |
81 |
* MBs to actually affect GC as GC allocates in pools of |
82 |
* memory */ |
83 |
public var memoryBlockSize:int = 16384; |
84 |
|
85 |
|
86 |
public function MD5Stream() |
87 |
{ |
88 |
|
89 |
} |
90 |
|
91 |
|
92 |
/** |
93 |
* Pass in chunks of the input data with update(), call |
94 |
* complete() with an optional chunk which will return the |
95 |
* final hash. Equivalent to the way |
96 |
* java.security.MessageDigest works. |
97 |
* |
98 |
* @param input The optional bytearray chunk which is the final part of the input |
99 |
* @return A string containing the hash value |
100 |
* @langversion ActionScript 3.0 |
101 |
* @playerversion Flash 8.5 |
102 |
* @tiptext |
103 |
*/ |
104 |
public function complete(input:ByteArray=null):String |
105 |
{ |
106 |
if ( arr.length == 0 ) |
107 |
{ |
108 |
if ( input == null ) |
109 |
{ |
110 |
throw new Error("null input to complete without prior call to update. At least an empty bytearray must be passed."); |
111 |
} |
112 |
} |
113 |
|
114 |
if ( input != null ) |
115 |
{ |
116 |
readIntoArray(input); |
117 |
} |
118 |
|
119 |
//pad, append length |
120 |
padArray(arrLen); |
121 |
|
122 |
hashRemainingChunks(false); |
123 |
|
124 |
var res:String = IntUtil.toHex( a ) + IntUtil.toHex( b ) + |
125 |
IntUtil.toHex( c ) + IntUtil.toHex( d ); |
126 |
resetFields(); |
127 |
|
128 |
return res; |
129 |
} |
130 |
|
131 |
/** |
132 |
* Pass in chunks of the input data with update(), call |
133 |
* complete() with an optional chunk which will return the |
134 |
* final hash. Equivalent to the way |
135 |
* java.security.MessageDigest works. |
136 |
* |
137 |
* @param input The bytearray chunk to perform the hash on |
138 |
* @langversion ActionScript 3.0 |
139 |
* @playerversion Flash 8.5 |
140 |
* @tiptext |
141 |
*/ |
142 |
public function update(input:ByteArray):void |
143 |
{ |
144 |
readIntoArray(input); |
145 |
hashRemainingChunks(); |
146 |
} |
147 |
|
148 |
/** |
149 |
* Re-initialize this instance for use to perform hashing on |
150 |
* another input stream. This is called automatically by |
151 |
* complete(). |
152 |
* |
153 |
* @langversion ActionScript 3.0 |
154 |
* @playerversion Flash 8.5 |
155 |
* @tiptext |
156 |
*/ |
157 |
public function resetFields():void |
158 |
{ |
159 |
//truncate array |
160 |
arr.length = 0; |
161 |
arrLen = 0; |
162 |
|
163 |
// initialize the md buffers |
164 |
a = 1732584193; |
165 |
b = -271733879; |
166 |
c = -1732584194; |
167 |
d = 271733878; |
168 |
|
169 |
// variables to store previous values |
170 |
aa = 0; |
171 |
bb = 0; |
172 |
cc = 0; |
173 |
dd = 0; |
174 |
|
175 |
arrIndexLen = 0; |
176 |
arrProcessIndex = 0; |
177 |
cleanIndex = 0; |
178 |
} |
179 |
|
180 |
/** read into arr and free up used blocks of arr */ |
181 |
private function readIntoArray(input:ByteArray):void |
182 |
{ |
183 |
var closestChunkLen:int = input.length * 8; |
184 |
arrLen += closestChunkLen; |
185 |
|
186 |
/* clean up memory. if there are entries in the array that |
187 |
* are already processed and the amount is greater than |
188 |
* memoryBlockSize, create a new array, copy the last |
189 |
* block into it and let the old one get picked up by |
190 |
* GC. */ |
191 |
if ( arrProcessIndex - cleanIndex > memoryBlockSize ) |
192 |
{ |
193 |
var newarr:Array= new Array(); |
194 |
|
195 |
/* AS Arrays in sparse arrays. arr[2002] can exist |
196 |
* without values for arr[0] - arr[2001] */ |
197 |
for ( var j:int = arrProcessIndex; j < arr.length; j++ ) |
198 |
{ |
199 |
newarr[j] = arr[j]; |
200 |
} |
201 |
|
202 |
cleanIndex = arrProcessIndex; |
203 |
arr = null; |
204 |
arr = newarr; |
205 |
} |
206 |
|
207 |
for ( var k:int = 0; k < closestChunkLen; k+=8 ) |
208 |
{ |
209 |
//discard high bytes (convert to uint) |
210 |
arr[ int(arrIndexLen >> 5) ] |= ( input[ k / 8 ] & mask ) << ( arrIndexLen % 32 ); |
211 |
arrIndexLen += 8; |
212 |
} |
213 |
|
214 |
|
215 |
} |
216 |
|
217 |
private function hashRemainingChunks(bUpdate:Boolean=true):void |
218 |
{ |
219 |
var len:int = arr.length; |
220 |
|
221 |
/* leave a 16 word block untouched if we are called from |
222 |
* update. This is because, padArray() can modify the last |
223 |
* block and this modification has to happen before we |
224 |
* compute the hash. */ |
225 |
if ( bUpdate ) |
226 |
{ |
227 |
len -= 16; |
228 |
} |
229 |
|
230 |
/* don't do anything if don't have a 16 word block. */ |
231 |
if ( arrProcessIndex >= len || len - arrProcessIndex < 15 ) |
232 |
{ |
233 |
return; |
234 |
} |
235 |
|
236 |
|
237 |
for ( var i:int = arrProcessIndex; i < len ; i += 16, arrProcessIndex += 16) |
238 |
{ |
239 |
// save previous values |
240 |
aa = a; |
241 |
bb = b; |
242 |
cc = c; |
243 |
dd = d; |
244 |
|
245 |
// Round 1 |
246 |
a = ff( a, b, c, d, arr[int(i+ 0)], 7, -680876936 ); // 1 |
247 |
d = ff( d, a, b, c, arr[int(i+ 1)], 12, -389564586 ); // 2 |
248 |
c = ff( c, d, a, b, arr[int(i+ 2)], 17, 606105819 ); // 3 |
249 |
b = ff( b, c, d, a, arr[int(i+ 3)], 22, -1044525330 ); // 4 |
250 |
a = ff( a, b, c, d, arr[int(i+ 4)], 7, -176418897 ); // 5 |
251 |
d = ff( d, a, b, c, arr[int(i+ 5)], 12, 1200080426 ); // 6 |
252 |
c = ff( c, d, a, b, arr[int(i+ 6)], 17, -1473231341 ); // 7 |
253 |
b = ff( b, c, d, a, arr[int(i+ 7)], 22, -45705983 ); // 8 |
254 |
a = ff( a, b, c, d, arr[int(i+ 8)], 7, 1770035416 ); // 9 |
255 |
d = ff( d, a, b, c, arr[int(i+ 9)], 12, -1958414417 ); // 10 |
256 |
c = ff( c, d, a, b, arr[int(i+10)], 17, -42063 ); // 11 |
257 |
b = ff( b, c, d, a, arr[int(i+11)], 22, -1990404162 ); // 12 |
258 |
a = ff( a, b, c, d, arr[int(i+12)], 7, 1804603682 ); // 13 |
259 |
d = ff( d, a, b, c, arr[int(i+13)], 12, -40341101 ); // 14 |
260 |
c = ff( c, d, a, b, arr[int(i+14)], 17, -1502002290 ); // 15 |
261 |
b = ff( b, c, d, a, arr[int(i+15)], 22, 1236535329 ); // 16 |
262 |
|
263 |
// Round 2 |
264 |
a = gg( a, b, c, d, arr[int(i+ 1)], 5, -165796510 ); // 17 |
265 |
d = gg( d, a, b, c, arr[int(i+ 6)], 9, -1069501632 ); // 18 |
266 |
c = gg( c, d, a, b, arr[int(i+11)], 14, 643717713 ); // 19 |
267 |
b = gg( b, c, d, a, arr[int(i+ 0)], 20, -373897302 ); // 20 |
268 |
a = gg( a, b, c, d, arr[int(i+ 5)], 5, -701558691 ); // 21 |
269 |
d = gg( d, a, b, c, arr[int(i+10)], 9, 38016083 ); // 22 |
270 |
c = gg( c, d, a, b, arr[int(i+15)], 14, -660478335 ); // 23 |
271 |
b = gg( b, c, d, a, arr[int(i+ 4)], 20, -405537848 ); // 24 |
272 |
a = gg( a, b, c, d, arr[int(i+ 9)], 5, 568446438 ); // 25 |
273 |
d = gg( d, a, b, c, arr[int(i+14)], 9, -1019803690 ); // 26 |
274 |
c = gg( c, d, a, b, arr[int(i+ 3)], 14, -187363961 ); // 27 |
275 |
b = gg( b, c, d, a, arr[int(i+ 8)], 20, 1163531501 ); // 28 |
276 |
a = gg( a, b, c, d, arr[int(i+13)], 5, -1444681467 ); // 29 |
277 |
d = gg( d, a, b, c, arr[int(i+ 2)], 9, -51403784 ); // 30 |
278 |
c = gg( c, d, a, b, arr[int(i+ 7)], 14, 1735328473 ); // 31 |
279 |
b = gg( b, c, d, a, arr[int(i+12)], 20, -1926607734 ); // 32 |
280 |
|
281 |
// Round 3 |
282 |
a = hh( a, b, c, d, arr[int(i+ 5)], 4, -378558 ); // 33 |
283 |
d = hh( d, a, b, c, arr[int(i+ 8)], 11, -2022574463 ); // 34 |
284 |
c = hh( c, d, a, b, arr[int(i+11)], 16, 1839030562 ); // 35 |
285 |
b = hh( b, c, d, a, arr[int(i+14)], 23, -35309556 ); // 36 |
286 |
a = hh( a, b, c, d, arr[int(i+ 1)], 4, -1530992060 ); // 37 |
287 |
d = hh( d, a, b, c, arr[int(i+ 4)], 11, 1272893353 ); // 38 |
288 |
c = hh( c, d, a, b, arr[int(i+ 7)], 16, -155497632 ); // 39 |
289 |
b = hh( b, c, d, a, arr[int(i+10)], 23, -1094730640 ); // 40 |
290 |
a = hh( a, b, c, d, arr[int(i+13)], 4, 681279174 ); // 41 |
291 |
d = hh( d, a, b, c, arr[int(i+ 0)], 11, -358537222 ); // 42 |
292 |
c = hh( c, d, a, b, arr[int(i+ 3)], 16, -722521979 ); // 43 |
293 |
b = hh( b, c, d, a, arr[int(i+ 6)], 23, 76029189 ); // 44 |
294 |
a = hh( a, b, c, d, arr[int(i+ 9)], 4, -640364487 ); // 45 |
295 |
d = hh( d, a, b, c, arr[int(i+12)], 11, -421815835 ); // 46 |
296 |
c = hh( c, d, a, b, arr[int(i+15)], 16, 530742520 ); // 47 |
297 |
b = hh( b, c, d, a, arr[int(i+ 2)], 23, -995338651 ); // 48 |
298 |
|
299 |
// Round 4 |
300 |
a = ii( a, b, c, d, arr[int(i+ 0)], 6, -198630844 ); // 49 |
301 |
d = ii( d, a, b, c, arr[int(i+ 7)], 10, 1126891415 ); // 50 |
302 |
c = ii( c, d, a, b, arr[int(i+14)], 15, -1416354905 ); // 51 |
303 |
b = ii( b, c, d, a, arr[int(i+ 5)], 21, -57434055 ); // 52 |
304 |
a = ii( a, b, c, d, arr[int(i+12)], 6, 1700485571 ); // 53 |
305 |
d = ii( d, a, b, c, arr[int(i+ 3)], 10, -1894986606 ); // 54 |
306 |
c = ii( c, d, a, b, arr[int(i+10)], 15, -1051523 ); // 55 |
307 |
b = ii( b, c, d, a, arr[int(i+ 1)], 21, -2054922799 ); // 56 |
308 |
a = ii( a, b, c, d, arr[int(i+ 8)], 6, 1873313359 ); // 57 |
309 |
d = ii( d, a, b, c, arr[int(i+15)], 10, -30611744 ); // 58 |
310 |
c = ii( c, d, a, b, arr[int(i+ 6)], 15, -1560198380 ); // 59 |
311 |
b = ii( b, c, d, a, arr[int(i+13)], 21, 1309151649 ); // 60 |
312 |
a = ii( a, b, c, d, arr[int(i+ 4)], 6, -145523070 ); // 61 |
313 |
d = ii( d, a, b, c, arr[int(i+11)], 10, -1120210379 ); // 62 |
314 |
c = ii( c, d, a, b, arr[int(i+ 2)], 15, 718787259 ); // 63 |
315 |
b = ii( b, c, d, a, arr[int(i+ 9)], 21, -343485551 ); // 64 |
316 |
|
317 |
a += aa; |
318 |
b += bb; |
319 |
c += cc; |
320 |
d += dd; |
321 |
|
322 |
} |
323 |
|
324 |
} |
325 |
|
326 |
private function padArray(len:int):void |
327 |
{ |
328 |
arr[ int(len >> 5) ] |= 0x80 << ( len % 32 ); |
329 |
arr[ int(( ( ( len + 64 ) >>> 9 ) << 4 ) + 14) ] = len; |
330 |
arrLen = arr.length; |
331 |
} |
332 |
|
333 |
/* Code below same as com.adobe.crypto.MD5 */ |
334 |
|
335 |
/** |
336 |
* Auxiliary function f as defined in RFC |
337 |
*/ |
338 |
private static function f( x:int, y:int, z:int ):int { |
339 |
return ( x & y ) | ( (~x) & z ); |
340 |
} |
341 |
|
342 |
/** |
343 |
* Auxiliary function g as defined in RFC |
344 |
*/ |
345 |
private static function g( x:int, y:int, z:int ):int { |
346 |
return ( x & z ) | ( y & (~z) ); |
347 |
} |
348 |
|
349 |
/** |
350 |
* Auxiliary function h as defined in RFC |
351 |
*/ |
352 |
private static function h( x:int, y:int, z:int ):int { |
353 |
return x ^ y ^ z; |
354 |
} |
355 |
|
356 |
/** |
357 |
* Auxiliary function i as defined in RFC |
358 |
*/ |
359 |
private static function i( x:int, y:int, z:int ):int { |
360 |
return y ^ ( x | (~z) ); |
361 |
} |
362 |
|
363 |
/** |
364 |
* A generic transformation function. The logic of ff, gg, hh, and |
365 |
* ii are all the same, minus the function used, so pull that logic |
366 |
* out and simplify the method bodies for the transoformation functions. |
367 |
*/ |
368 |
private static function transform( func:Function, a:int, b:int, c:int, d:int, x:int, s:int, t:int):int { |
369 |
var tmp:int = a + int( func( b, c, d ) ) + x + t; |
370 |
return IntUtil.rol( tmp, s ) + b; |
371 |
} |
372 |
|
373 |
/** |
374 |
* ff transformation function |
375 |
*/ |
376 |
private static function ff ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int { |
377 |
return transform( f, a, b, c, d, x, s, t ); |
378 |
} |
379 |
|
380 |
/** |
381 |
* gg transformation function |
382 |
*/ |
383 |
private static function gg ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int { |
384 |
return transform( g, a, b, c, d, x, s, t ); |
385 |
} |
386 |
|
387 |
/** |
388 |
* hh transformation function |
389 |
*/ |
390 |
private static function hh ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int { |
391 |
return transform( h, a, b, c, d, x, s, t ); |
392 |
} |
393 |
|
394 |
/** |
395 |
* ii transformation function |
396 |
*/ |
397 |
private static function ii ( a:int, b:int, c:int, d:int, x:int, s:int, t:int ):int { |
398 |
return transform( i, a, b, c, d, x, s, t ); |
399 |
} |
400 |
|
401 |
} |
402 |
} |