Project

General

Profile

Statistics
| Branch: | Revision:

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
}