try to fix some minor dropdown bugs
[potlatch2.git] / com / adobe / crypto / SHA224.as
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         import mx.utils.Base64Encoder;
38         
39         /**
40          * The SHA-224 algorithm
41          * 
42          * @see http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
43          */
44         public class SHA224
45         {
46                 public static var digest:ByteArray;
47                 
48                 /**
49                  *  Performs the SHA224 hash algorithm on a string.
50                  *
51                  *  @param s            The string to hash
52                  *  @return                     A string containing the hash value of s
53                  *  @langversion        ActionScript 3.0
54                  *  @playerversion      9.0
55                  *  @tiptext
56                  */
57                 public static function hash( s:String ):String {
58                         var blocks:Array = createBlocksFromString( s );
59                         var byteArray:ByteArray = hashBlocks( blocks );
60                         return IntUtil.toHex( byteArray.readInt(), true )
61                                         + IntUtil.toHex( byteArray.readInt(), true )
62                                         + IntUtil.toHex( byteArray.readInt(), true )
63                                         + IntUtil.toHex( byteArray.readInt(), true )
64                                         + IntUtil.toHex( byteArray.readInt(), true )
65                                         + IntUtil.toHex( byteArray.readInt(), true )
66                                         + IntUtil.toHex( byteArray.readInt(), true );
67                 }
68                 
69                 /**
70                  *  Performs the SHA224 hash algorithm on a ByteArray.
71                  *
72                  *  @param data         The ByteArray data to hash
73                  *  @return                     A string containing the hash value of data
74                  *  @langversion        ActionScript 3.0
75                  *  @playerversion      9.0
76                  */
77                 public static function hashBytes( data:ByteArray ):String
78                 {
79                         var blocks:Array = createBlocksFromByteArray( data );
80                         var byteArray:ByteArray = hashBlocks(blocks);
81                         return IntUtil.toHex( byteArray.readInt(), true )
82                                         + IntUtil.toHex( byteArray.readInt(), true )
83                                         + IntUtil.toHex( byteArray.readInt(), true )
84                                         + IntUtil.toHex( byteArray.readInt(), true )
85                                         + IntUtil.toHex( byteArray.readInt(), true )
86                                         + IntUtil.toHex( byteArray.readInt(), true )
87                                         + IntUtil.toHex( byteArray.readInt(), true );
88                 }
89                 
90                 /**
91                  *  Performs the SHA224 hash algorithm on a string, then does
92                  *  Base64 encoding on the result.
93                  *
94                  *  @param s            The string to hash
95                  *  @return                     The base64 encoded hash value of s
96                  *  @langversion        ActionScript 3.0
97                  *  @playerversion      9.0
98                  *  @tiptext
99                  */
100                 public static function hashToBase64( s:String ):String
101                 {
102                         var blocks:Array = createBlocksFromString( s );
103                         var byteArray:ByteArray = hashBlocks(blocks);
104
105                         // ByteArray.toString() returns the contents as a UTF-8 string,
106                         // which we can't use because certain byte sequences might trigger
107                         // a UTF-8 conversion.  Instead, we convert the bytes to characters
108                         // one by one.
109                         var charsInByteArray:String = "";
110                         byteArray.position = 0;
111                         for (var j:int = 0; j < byteArray.length; j++)
112                         {
113                                 var byte:uint = byteArray.readUnsignedByte();
114                                 charsInByteArray += String.fromCharCode(byte);
115                         }
116
117                         var encoder:Base64Encoder = new Base64Encoder();
118                         encoder.encode(charsInByteArray);
119                         return encoder.flush();
120                 }
121                 
122                 private static function hashBlocks( blocks:Array ):ByteArray {
123                         var h0:int = 0xc1059ed8;
124                         var h1:int = 0x367cd507;
125                         var h2:int = 0x3070dd17;
126                         var h3:int = 0xf70e5939;
127                         var h4:int = 0xffc00b31;
128                         var h5:int = 0x68581511;
129                         var h6:int = 0x64f98fa7;
130                         var h7:int = 0xbefa4fa4;
131                         
132                         var k:Array = new Array(0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2);
133                         
134                         var len:int = blocks.length;
135                         var w:Array = new Array();
136                         
137                         // loop over all of the blocks
138                         for ( var i:int = 0; i < len; i += 16 ) {
139                                 
140                                 var a:int = h0;
141                                 var b:int = h1;
142                                 var c:int = h2;
143                                 var d:int = h3;
144                                 var e:int = h4;
145                                 var f:int = h5;
146                                 var g:int = h6;
147                                 var h:int = h7;
148                                 
149                                 for(var t:int = 0; t < 64; t++) {
150                                         
151                                         if ( t < 16 ) {
152                                                 w[t] = blocks[ i + t ];
153                                                 if(isNaN(w[t])) { w[t] = 0; }
154                                         } else {
155                                                 var ws0:int = IntUtil.ror(w[t-15], 7) ^ IntUtil.ror(w[t-15], 18) ^ (w[t-15] >>> 3);
156                                                 var ws1:int = IntUtil.ror(w[t-2], 17) ^ IntUtil.ror(w[t-2], 19) ^ (w[t-2] >>> 10);
157                                                 w[t] = w[t-16] + ws0 + w[t-7] + ws1;
158                                         }
159                                         
160                                         var s0:int = IntUtil.ror(a, 2) ^ IntUtil.ror(a, 13) ^ IntUtil.ror(a, 22);
161                                         var maj:int = (a & b) ^ (a & c) ^ (b & c);
162                                         var t2:int = s0 + maj;
163                                         var s1:int = IntUtil.ror(e, 6) ^ IntUtil.ror(e, 11) ^ IntUtil.ror(e, 25);
164                                         var ch:int = (e & f) ^ ((~e) & g);
165                                         var t1:int = h + s1 + ch + k[t] + w[t];
166                                         
167                                         h = g;
168                                         g = f;
169                                         f = e;
170                                         e = d + t1;
171                                         d = c;
172                                         c = b;
173                                         b = a;
174                                         a = t1 + t2;
175                                 }
176                                         
177                                 //Add this chunk's hash to result so far:
178                                 h0 += a;
179                                 h1 += b;
180                                 h2 += c;
181                                 h3 += d;
182                                 h4 += e;
183                                 h5 += f;
184                                 h6 += g;
185                                 h7 += h;
186                         }
187                         
188                         var byteArray:ByteArray = new ByteArray();
189                         byteArray.writeInt(h0);
190                         byteArray.writeInt(h1);
191                         byteArray.writeInt(h2);
192                         byteArray.writeInt(h3);
193                         byteArray.writeInt(h4);
194                         byteArray.writeInt(h5);
195                         byteArray.writeInt(h6);
196                         byteArray.position = 0;
197                         
198                         digest = new ByteArray();
199                         digest.writeBytes(byteArray);
200                         digest.position = 0;
201                         return byteArray;
202                 }
203                 
204                 /**
205                  *  Converts a ByteArray to a sequence of 16-word blocks
206                  *  that we'll do the processing on.  Appends padding
207                  *  and length in the process.
208                  *
209                  *  @param data         The data to split into blocks
210                  *  @return                     An array containing the blocks into which data was split
211                  */
212                 private static function createBlocksFromByteArray( data:ByteArray ):Array
213                 {
214                         var oldPosition:int = data.position;
215                         data.position = 0;
216                         
217                         var blocks:Array = new Array();
218                         var len:int = data.length * 8;
219                         var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
220                         for( var i:int = 0; i < len; i += 8 )
221                         {
222                                 blocks[ i >> 5 ] |= ( data.readByte() & mask ) << ( 24 - i % 32 );
223                         }
224                         
225                         // append padding and length
226                         blocks[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
227                         blocks[ ( ( ( len + 64 ) >> 9 ) << 4 ) + 15 ] = len;
228                         
229                         data.position = oldPosition;
230                         
231                         return blocks;
232                 }
233                                         
234                 /**
235                  *  Converts a string to a sequence of 16-word blocks
236                  *  that we'll do the processing on.  Appends padding
237                  *  and length in the process.
238                  *
239                  *  @param s    The string to split into blocks
240                  *  @return             An array containing the blocks that s was split into.
241                  */
242                 private static function createBlocksFromString( s:String ):Array
243                 {
244                         var blocks:Array = new Array();
245                         var len:int = s.length * 8;
246                         var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
247                         for( var i:int = 0; i < len; i += 8 ) {
248                                 blocks[ i >> 5 ] |= ( s.charCodeAt( i / 8 ) & mask ) << ( 24 - i % 32 );
249                         }
250                         
251                         // append padding and length
252                         blocks[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
253                         blocks[ ( ( ( len + 64 ) >> 9 ) << 4 ) + 15 ] = len;
254                         return blocks;
255                 }
256         }
257 }