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