mas01mj@732
|
1 /*
|
mas01mj@732
|
2 Copyright (c) 2008, Adobe Systems Incorporated
|
mas01mj@732
|
3 All rights reserved.
|
mas01mj@732
|
4
|
mas01mj@732
|
5 Redistribution and use in source and binary forms, with or without
|
mas01mj@732
|
6 modification, are permitted provided that the following conditions are
|
mas01mj@732
|
7 met:
|
mas01mj@732
|
8
|
mas01mj@732
|
9 * Redistributions of source code must retain the above copyright notice,
|
mas01mj@732
|
10 this list of conditions and the following disclaimer.
|
mas01mj@732
|
11
|
mas01mj@732
|
12 * Redistributions in binary form must reproduce the above copyright
|
mas01mj@732
|
13 notice, this list of conditions and the following disclaimer in the
|
mas01mj@732
|
14 documentation and/or other materials provided with the distribution.
|
mas01mj@732
|
15
|
mas01mj@732
|
16 * Neither the name of Adobe Systems Incorporated nor the names of its
|
mas01mj@732
|
17 contributors may be used to endorse or promote products derived from
|
mas01mj@732
|
18 this software without specific prior written permission.
|
mas01mj@732
|
19
|
mas01mj@732
|
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
mas01mj@732
|
21 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
mas01mj@732
|
22 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
mas01mj@732
|
23 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
mas01mj@732
|
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
mas01mj@732
|
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
mas01mj@732
|
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
mas01mj@732
|
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
mas01mj@732
|
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
mas01mj@732
|
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
mas01mj@732
|
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
mas01mj@732
|
31 */
|
mas01mj@732
|
32
|
mas01mj@732
|
33 package com.adobe.crypto
|
mas01mj@732
|
34 {
|
mas01mj@732
|
35 import com.adobe.utils.IntUtil;
|
mas01mj@732
|
36 import flash.utils.ByteArray;
|
mas01mj@732
|
37 import mx.utils.Base64Encoder;
|
mas01mj@732
|
38
|
mas01mj@732
|
39 /**
|
mas01mj@732
|
40 * US Secure Hash Algorithm 1 (SHA1)
|
mas01mj@732
|
41 *
|
mas01mj@732
|
42 * Implementation based on algorithm description at
|
mas01mj@732
|
43 * http://www.faqs.org/rfcs/rfc3174.html
|
mas01mj@732
|
44 */
|
mas01mj@732
|
45 public class SHA1
|
mas01mj@732
|
46 {
|
mas01mj@732
|
47 public static var digest:ByteArray;
|
mas01mj@732
|
48
|
mas01mj@732
|
49 /**
|
mas01mj@732
|
50 * Performs the SHA1 hash algorithm on a string.
|
mas01mj@732
|
51 *
|
mas01mj@732
|
52 * @param s The string to hash
|
mas01mj@732
|
53 * @return A string containing the hash value of s
|
mas01mj@732
|
54 * @langversion ActionScript 3.0
|
mas01mj@732
|
55 * @playerversion 9.0
|
mas01mj@732
|
56 * @tiptext
|
mas01mj@732
|
57 */
|
mas01mj@732
|
58 public static function hash( s:String ):String
|
mas01mj@732
|
59 {
|
mas01mj@732
|
60 var blocks:Array = createBlocksFromString( s );
|
mas01mj@732
|
61 var byteArray:ByteArray = hashBlocks( blocks );
|
mas01mj@732
|
62
|
mas01mj@732
|
63 return IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
64 + IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
65 + IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
66 + IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
67 + IntUtil.toHex( byteArray.readInt(), true );
|
mas01mj@732
|
68 }
|
mas01mj@732
|
69
|
mas01mj@732
|
70 /**
|
mas01mj@732
|
71 * Performs the SHA1 hash algorithm on a ByteArray.
|
mas01mj@732
|
72 *
|
mas01mj@732
|
73 * @param data The ByteArray data to hash
|
mas01mj@732
|
74 * @return A string containing the hash value of data
|
mas01mj@732
|
75 * @langversion ActionScript 3.0
|
mas01mj@732
|
76 * @playerversion 9.0
|
mas01mj@732
|
77 */
|
mas01mj@732
|
78 public static function hashBytes( data:ByteArray ):String
|
mas01mj@732
|
79 {
|
mas01mj@732
|
80 var blocks:Array = SHA1.createBlocksFromByteArray( data );
|
mas01mj@732
|
81 var byteArray:ByteArray = hashBlocks(blocks);
|
mas01mj@732
|
82
|
mas01mj@732
|
83 return IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
84 + IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
85 + IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
86 + IntUtil.toHex( byteArray.readInt(), true )
|
mas01mj@732
|
87 + IntUtil.toHex( byteArray.readInt(), true );
|
mas01mj@732
|
88 }
|
mas01mj@732
|
89
|
mas01mj@732
|
90 /**
|
mas01mj@732
|
91 * Performs the SHA1 hash algorithm on a string, then does
|
mas01mj@732
|
92 * Base64 encoding on the result.
|
mas01mj@732
|
93 *
|
mas01mj@732
|
94 * @param s The string to hash
|
mas01mj@732
|
95 * @return The base64 encoded hash value of s
|
mas01mj@732
|
96 * @langversion ActionScript 3.0
|
mas01mj@732
|
97 * @playerversion 9.0
|
mas01mj@732
|
98 * @tiptext
|
mas01mj@732
|
99 */
|
mas01mj@732
|
100 public static function hashToBase64( s:String ):String
|
mas01mj@732
|
101 {
|
mas01mj@732
|
102 var blocks:Array = SHA1.createBlocksFromString( s );
|
mas01mj@732
|
103 var byteArray:ByteArray = hashBlocks(blocks);
|
mas01mj@732
|
104
|
mas01mj@732
|
105 // ByteArray.toString() returns the contents as a UTF-8 string,
|
mas01mj@732
|
106 // which we can't use because certain byte sequences might trigger
|
mas01mj@732
|
107 // a UTF-8 conversion. Instead, we convert the bytes to characters
|
mas01mj@732
|
108 // one by one.
|
mas01mj@732
|
109 var charsInByteArray:String = "";
|
mas01mj@732
|
110 byteArray.position = 0;
|
mas01mj@732
|
111 for (var j:int = 0; j < byteArray.length; j++)
|
mas01mj@732
|
112 {
|
mas01mj@732
|
113 var byte:uint = byteArray.readUnsignedByte();
|
mas01mj@732
|
114 charsInByteArray += String.fromCharCode(byte);
|
mas01mj@732
|
115 }
|
mas01mj@732
|
116
|
mas01mj@732
|
117 var encoder:Base64Encoder = new Base64Encoder();
|
mas01mj@732
|
118 encoder.encode(charsInByteArray);
|
mas01mj@732
|
119 return encoder.flush();
|
mas01mj@732
|
120 }
|
mas01mj@732
|
121
|
mas01mj@732
|
122 private static function hashBlocks( blocks:Array ):ByteArray
|
mas01mj@732
|
123 {
|
mas01mj@732
|
124 // initialize the h's
|
mas01mj@732
|
125 var h0:int = 0x67452301;
|
mas01mj@732
|
126 var h1:int = 0xefcdab89;
|
mas01mj@732
|
127 var h2:int = 0x98badcfe;
|
mas01mj@732
|
128 var h3:int = 0x10325476;
|
mas01mj@732
|
129 var h4:int = 0xc3d2e1f0;
|
mas01mj@732
|
130
|
mas01mj@732
|
131 var len:int = blocks.length;
|
mas01mj@732
|
132 var w:Array = new Array( 80 );
|
mas01mj@732
|
133 var temp:int;
|
mas01mj@732
|
134
|
mas01mj@732
|
135 // loop over all of the blocks
|
mas01mj@732
|
136 for ( var i:int = 0; i < len; i += 16 ) {
|
mas01mj@732
|
137
|
mas01mj@732
|
138 // 6.1.c
|
mas01mj@732
|
139 var a:int = h0;
|
mas01mj@732
|
140 var b:int = h1;
|
mas01mj@732
|
141 var c:int = h2;
|
mas01mj@732
|
142 var d:int = h3;
|
mas01mj@732
|
143 var e:int = h4;
|
mas01mj@732
|
144
|
mas01mj@732
|
145 // 80 steps to process each block
|
mas01mj@732
|
146 var t:int;
|
mas01mj@732
|
147 for ( t = 0; t < 20; t++ ) {
|
mas01mj@732
|
148
|
mas01mj@732
|
149 if ( t < 16 ) {
|
mas01mj@732
|
150 // 6.1.a
|
mas01mj@732
|
151 w[ t ] = blocks[ i + t ];
|
mas01mj@732
|
152 } else {
|
mas01mj@732
|
153 // 6.1.b
|
mas01mj@732
|
154 temp = w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ];
|
mas01mj@732
|
155 w[ t ] = ( temp << 1 ) | ( temp >>> 31 )
|
mas01mj@732
|
156 }
|
mas01mj@732
|
157
|
mas01mj@732
|
158 // 6.1.d
|
mas01mj@732
|
159 temp = ( ( a << 5 ) | ( a >>> 27 ) ) + ( ( b & c ) | ( ~b & d ) ) + e + int( w[ t ] ) + 0x5a827999;
|
mas01mj@732
|
160
|
mas01mj@732
|
161 e = d;
|
mas01mj@732
|
162 d = c;
|
mas01mj@732
|
163 c = ( b << 30 ) | ( b >>> 2 );
|
mas01mj@732
|
164 b = a;
|
mas01mj@732
|
165 a = temp;
|
mas01mj@732
|
166 }
|
mas01mj@732
|
167 for ( ; t < 40; t++ )
|
mas01mj@732
|
168 {
|
mas01mj@732
|
169 // 6.1.b
|
mas01mj@732
|
170 temp = w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ];
|
mas01mj@732
|
171 w[ t ] = ( temp << 1 ) | ( temp >>> 31 )
|
mas01mj@732
|
172
|
mas01mj@732
|
173 // 6.1.d
|
mas01mj@732
|
174 temp = ( ( a << 5 ) | ( a >>> 27 ) ) + ( b ^ c ^ d ) + e + int( w[ t ] ) + 0x6ed9eba1;
|
mas01mj@732
|
175
|
mas01mj@732
|
176 e = d;
|
mas01mj@732
|
177 d = c;
|
mas01mj@732
|
178 c = ( b << 30 ) | ( b >>> 2 );
|
mas01mj@732
|
179 b = a;
|
mas01mj@732
|
180 a = temp;
|
mas01mj@732
|
181 }
|
mas01mj@732
|
182 for ( ; t < 60; t++ )
|
mas01mj@732
|
183 {
|
mas01mj@732
|
184 // 6.1.b
|
mas01mj@732
|
185 temp = w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ];
|
mas01mj@732
|
186 w[ t ] = ( temp << 1 ) | ( temp >>> 31 )
|
mas01mj@732
|
187
|
mas01mj@732
|
188 // 6.1.d
|
mas01mj@732
|
189 temp = ( ( a << 5 ) | ( a >>> 27 ) ) + ( ( b & c ) | ( b & d ) | ( c & d ) ) + e + int( w[ t ] ) + 0x8f1bbcdc;
|
mas01mj@732
|
190
|
mas01mj@732
|
191 e = d;
|
mas01mj@732
|
192 d = c;
|
mas01mj@732
|
193 c = ( b << 30 ) | ( b >>> 2 );
|
mas01mj@732
|
194 b = a;
|
mas01mj@732
|
195 a = temp;
|
mas01mj@732
|
196 }
|
mas01mj@732
|
197 for ( ; t < 80; t++ )
|
mas01mj@732
|
198 {
|
mas01mj@732
|
199 // 6.1.b
|
mas01mj@732
|
200 temp = w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ];
|
mas01mj@732
|
201 w[ t ] = ( temp << 1 ) | ( temp >>> 31 )
|
mas01mj@732
|
202
|
mas01mj@732
|
203 // 6.1.d
|
mas01mj@732
|
204 temp = ( ( a << 5 ) | ( a >>> 27 ) ) + ( b ^ c ^ d ) + e + int( w[ t ] ) + 0xca62c1d6;
|
mas01mj@732
|
205
|
mas01mj@732
|
206 e = d;
|
mas01mj@732
|
207 d = c;
|
mas01mj@732
|
208 c = ( b << 30 ) | ( b >>> 2 );
|
mas01mj@732
|
209 b = a;
|
mas01mj@732
|
210 a = temp;
|
mas01mj@732
|
211 }
|
mas01mj@732
|
212
|
mas01mj@732
|
213 // 6.1.e
|
mas01mj@732
|
214 h0 += a;
|
mas01mj@732
|
215 h1 += b;
|
mas01mj@732
|
216 h2 += c;
|
mas01mj@732
|
217 h3 += d;
|
mas01mj@732
|
218 h4 += e;
|
mas01mj@732
|
219 }
|
mas01mj@732
|
220
|
mas01mj@732
|
221 var byteArray:ByteArray = new ByteArray();
|
mas01mj@732
|
222 byteArray.writeInt(h0);
|
mas01mj@732
|
223 byteArray.writeInt(h1);
|
mas01mj@732
|
224 byteArray.writeInt(h2);
|
mas01mj@732
|
225 byteArray.writeInt(h3);
|
mas01mj@732
|
226 byteArray.writeInt(h4);
|
mas01mj@732
|
227 byteArray.position = 0;
|
mas01mj@732
|
228
|
mas01mj@732
|
229 digest = new ByteArray();
|
mas01mj@732
|
230 digest.writeBytes(byteArray);
|
mas01mj@732
|
231 digest.position = 0;
|
mas01mj@732
|
232 return byteArray;
|
mas01mj@732
|
233 }
|
mas01mj@732
|
234
|
mas01mj@732
|
235 /**
|
mas01mj@732
|
236 * Converts a ByteArray to a sequence of 16-word blocks
|
mas01mj@732
|
237 * that we'll do the processing on. Appends padding
|
mas01mj@732
|
238 * and length in the process.
|
mas01mj@732
|
239 *
|
mas01mj@732
|
240 * @param data The data to split into blocks
|
mas01mj@732
|
241 * @return An array containing the blocks into which data was split
|
mas01mj@732
|
242 */
|
mas01mj@732
|
243 private static function createBlocksFromByteArray( data:ByteArray ):Array
|
mas01mj@732
|
244 {
|
mas01mj@732
|
245 var oldPosition:int = data.position;
|
mas01mj@732
|
246 data.position = 0;
|
mas01mj@732
|
247
|
mas01mj@732
|
248 var blocks:Array = new Array();
|
mas01mj@732
|
249 var len:int = data.length * 8;
|
mas01mj@732
|
250 var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
|
mas01mj@732
|
251 for( var i:int = 0; i < len; i += 8 )
|
mas01mj@732
|
252 {
|
mas01mj@732
|
253 blocks[ i >> 5 ] |= ( data.readByte() & mask ) << ( 24 - i % 32 );
|
mas01mj@732
|
254 }
|
mas01mj@732
|
255
|
mas01mj@732
|
256 // append padding and length
|
mas01mj@732
|
257 blocks[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
|
mas01mj@732
|
258 blocks[ ( ( ( len + 64 ) >> 9 ) << 4 ) + 15 ] = len;
|
mas01mj@732
|
259
|
mas01mj@732
|
260 data.position = oldPosition;
|
mas01mj@732
|
261
|
mas01mj@732
|
262 return blocks;
|
mas01mj@732
|
263 }
|
mas01mj@732
|
264
|
mas01mj@732
|
265 /**
|
mas01mj@732
|
266 * Converts a string to a sequence of 16-word blocks
|
mas01mj@732
|
267 * that we'll do the processing on. Appends padding
|
mas01mj@732
|
268 * and length in the process.
|
mas01mj@732
|
269 *
|
mas01mj@732
|
270 * @param s The string to split into blocks
|
mas01mj@732
|
271 * @return An array containing the blocks that s was split into.
|
mas01mj@732
|
272 */
|
mas01mj@732
|
273 private static function createBlocksFromString( s:String ):Array
|
mas01mj@732
|
274 {
|
mas01mj@732
|
275 var blocks:Array = new Array();
|
mas01mj@732
|
276 var len:int = s.length * 8;
|
mas01mj@732
|
277 var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
|
mas01mj@732
|
278 for( var i:int = 0; i < len; i += 8 ) {
|
mas01mj@732
|
279 blocks[ i >> 5 ] |= ( s.charCodeAt( i / 8 ) & mask ) << ( 24 - i % 32 );
|
mas01mj@732
|
280 }
|
mas01mj@732
|
281
|
mas01mj@732
|
282 // append padding and length
|
mas01mj@732
|
283 blocks[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
|
mas01mj@732
|
284 blocks[ ( ( ( len + 64 ) >> 9 ) << 4 ) + 15 ] = len;
|
mas01mj@732
|
285 return blocks;
|
mas01mj@732
|
286 }
|
mas01mj@732
|
287
|
mas01mj@732
|
288 }
|
mas01mj@732
|
289 }
|