1 | /*
|
---|
2 | Adobe Systems Incorporated(r) Source Code License Agreement
|
---|
3 | Copyright(c) 2005 Adobe Systems Incorporated. All rights reserved.
|
---|
4 |
|
---|
5 | Please read this Source Code License Agreement carefully before using
|
---|
6 | the source code.
|
---|
7 |
|
---|
8 | Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive,
|
---|
9 | no-charge, royalty-free, irrevocable copyright license, to reproduce,
|
---|
10 | prepare derivative works of, publicly display, publicly perform, and
|
---|
11 | distribute this source code and such derivative works in source or
|
---|
12 | object code form without any attribution requirements.
|
---|
13 |
|
---|
14 | The name "Adobe Systems Incorporated" must not be used to endorse or promote products
|
---|
15 | derived from the source code without prior written permission.
|
---|
16 |
|
---|
17 | You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
|
---|
18 | against any loss, damage, claims or lawsuits, including attorney's
|
---|
19 | fees that arise or result from your use or distribution of the source
|
---|
20 | code.
|
---|
21 |
|
---|
22 | THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT
|
---|
23 | ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
|
---|
24 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
---|
25 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ALSO, THERE IS NO WARRANTY OF
|
---|
26 | NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT. IN NO EVENT SHALL MACROMEDIA
|
---|
27 | OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
---|
28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
---|
29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
---|
30 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
---|
31 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
---|
32 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
|
---|
33 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
34 | */
|
---|
35 |
|
---|
36 | package com.adobe.crypto
|
---|
37 | {
|
---|
38 | import com.adobe.utils.IntUtil;
|
---|
39 | import flash.utils.ByteArray;
|
---|
40 | import mx.utils.Base64Encoder;
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * US Secure Hash Algorithm 1 (SHA1)
|
---|
44 | *
|
---|
45 | * Implementation based on algorithm description at
|
---|
46 | * http://www.faqs.org/rfcs/rfc3174.html
|
---|
47 | */
|
---|
48 | public class SHA1
|
---|
49 | {
|
---|
50 | /**
|
---|
51 | * Performs the SHA1 hash algorithm on a string.
|
---|
52 | *
|
---|
53 | * @param s The string to hash
|
---|
54 | * @return A string containing the hash value of s
|
---|
55 | * @langversion ActionScript 3.0
|
---|
56 | * @playerversion 9.0
|
---|
57 | * @tiptext
|
---|
58 | */
|
---|
59 | public static function hash( s:String ):String
|
---|
60 | {
|
---|
61 | var blocks:Array = createBlocksFromString( s );
|
---|
62 | var byteArray:ByteArray = hashBlocks( blocks );
|
---|
63 |
|
---|
64 | return IntUtil.toHex( byteArray.readInt(), true )
|
---|
65 | + IntUtil.toHex( byteArray.readInt(), true )
|
---|
66 | + IntUtil.toHex( byteArray.readInt(), true )
|
---|
67 | + IntUtil.toHex( byteArray.readInt(), true )
|
---|
68 | + IntUtil.toHex( byteArray.readInt(), true );
|
---|
69 | }
|
---|
70 |
|
---|
71 | /**
|
---|
72 | * Performs the SHA1 hash algorithm on a ByteArray.
|
---|
73 | *
|
---|
74 | * @param data The ByteArray data to hash
|
---|
75 | * @return A string containing the hash value of data
|
---|
76 | * @langversion ActionScript 3.0
|
---|
77 | * @playerversion 9.0
|
---|
78 | */
|
---|
79 | public static function hashBytes( data:ByteArray ):String
|
---|
80 | {
|
---|
81 | var blocks:Array = SHA1.createBlocksFromByteArray( data );
|
---|
82 | var byteArray:ByteArray = hashBlocks(blocks);
|
---|
83 |
|
---|
84 | return 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 | }
|
---|
90 |
|
---|
91 | /**
|
---|
92 | * Performs the SHA1 hash algorithm on a string, then does
|
---|
93 | * Base64 encoding on the result.
|
---|
94 | *
|
---|
95 | * @param s The string to hash
|
---|
96 | * @return The base64 encoded hash value of s
|
---|
97 | * @langversion ActionScript 3.0
|
---|
98 | * @playerversion 9.0
|
---|
99 | * @tiptext
|
---|
100 | */
|
---|
101 | public static function hashToBase64( s:String ):String
|
---|
102 | {
|
---|
103 | var blocks:Array = SHA1.createBlocksFromString( s );
|
---|
104 | var byteArray:ByteArray = hashBlocks(blocks);
|
---|
105 |
|
---|
106 | // ByteArray.toString() returns the contents as a UTF-8 string,
|
---|
107 | // which we can't use because certain byte sequences might trigger
|
---|
108 | // a UTF-8 conversion. Instead, we convert the bytes to characters
|
---|
109 | // one by one.
|
---|
110 | var charsInByteArray:String = "";
|
---|
111 | byteArray.position = 0;
|
---|
112 | for (var j:int = 0; j < byteArray.length; j++)
|
---|
113 | {
|
---|
114 | var byte:uint = byteArray.readUnsignedByte();
|
---|
115 | charsInByteArray += String.fromCharCode(byte);
|
---|
116 | }
|
---|
117 |
|
---|
118 | var encoder:Base64Encoder = new Base64Encoder();
|
---|
119 | encoder.encode(charsInByteArray);
|
---|
120 | return encoder.flush();
|
---|
121 | }
|
---|
122 |
|
---|
123 | private static function hashBlocks( blocks:Array ):ByteArray
|
---|
124 | {
|
---|
125 | // initialize the h's
|
---|
126 | var h0:int = 0x67452301;
|
---|
127 | var h1:int = 0xefcdab89;
|
---|
128 | var h2:int = 0x98badcfe;
|
---|
129 | var h3:int = 0x10325476;
|
---|
130 | var h4:int = 0xc3d2e1f0;
|
---|
131 |
|
---|
132 | var len:int = blocks.length;
|
---|
133 | var w:Array = new Array( 80 );
|
---|
134 |
|
---|
135 | // loop over all of the blocks
|
---|
136 | for ( var i:int = 0; i < len; i += 16 ) {
|
---|
137 |
|
---|
138 | // 6.1.c
|
---|
139 | var a:int = h0;
|
---|
140 | var b:int = h1;
|
---|
141 | var c:int = h2;
|
---|
142 | var d:int = h3;
|
---|
143 | var e:int = h4;
|
---|
144 |
|
---|
145 | // 80 steps to process each block
|
---|
146 | // TODO: unroll for faster execution, or 4 loops of
|
---|
147 | // 20 each to avoid the k and f function calls
|
---|
148 | for ( var t:int = 0; t < 80; t++ ) {
|
---|
149 |
|
---|
150 | if ( t < 16 ) {
|
---|
151 | // 6.1.a
|
---|
152 | w[ t ] = blocks[ i + t ];
|
---|
153 | } else {
|
---|
154 | // 6.1.b
|
---|
155 | w[ t ] = IntUtil.rol( w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ], 1 );
|
---|
156 | }
|
---|
157 |
|
---|
158 | // 6.1.d
|
---|
159 | var temp:int = IntUtil.rol( a, 5 ) + f( t, b, c, d ) + e + int( w[ t ] ) + k( t );
|
---|
160 |
|
---|
161 | e = d;
|
---|
162 | d = c;
|
---|
163 | c = IntUtil.rol( b, 30 );
|
---|
164 | b = a;
|
---|
165 | a = temp;
|
---|
166 | }
|
---|
167 |
|
---|
168 | // 6.1.e
|
---|
169 | h0 += a;
|
---|
170 | h1 += b;
|
---|
171 | h2 += c;
|
---|
172 | h3 += d;
|
---|
173 | h4 += e;
|
---|
174 | }
|
---|
175 |
|
---|
176 | var byteArray:ByteArray = new ByteArray();
|
---|
177 | byteArray.writeInt(h0);
|
---|
178 | byteArray.writeInt(h1);
|
---|
179 | byteArray.writeInt(h2);
|
---|
180 | byteArray.writeInt(h3);
|
---|
181 | byteArray.writeInt(h4);
|
---|
182 | byteArray.position = 0;
|
---|
183 | return byteArray;
|
---|
184 | }
|
---|
185 |
|
---|
186 | /**
|
---|
187 | * Performs the logical function based on t
|
---|
188 | */
|
---|
189 | private static function f( t:int, b:int, c:int, d:int ):int {
|
---|
190 | if ( t < 20 ) {
|
---|
191 | return ( b & c ) | ( ~b & d );
|
---|
192 | } else if ( t < 40 ) {
|
---|
193 | return b ^ c ^ d;
|
---|
194 | } else if ( t < 60 ) {
|
---|
195 | return ( b & c ) | ( b & d ) | ( c & d );
|
---|
196 | }
|
---|
197 | return b ^ c ^ d;
|
---|
198 | }
|
---|
199 |
|
---|
200 | /**
|
---|
201 | * Determines the constant value based on t
|
---|
202 | */
|
---|
203 | private static function k( t:int ):int {
|
---|
204 | if ( t < 20 ) {
|
---|
205 | return 0x5a827999;
|
---|
206 | } else if ( t < 40 ) {
|
---|
207 | return 0x6ed9eba1;
|
---|
208 | } else if ( t < 60 ) {
|
---|
209 | return 0x8f1bbcdc;
|
---|
210 | }
|
---|
211 | return 0xca62c1d6;
|
---|
212 | }
|
---|
213 |
|
---|
214 | /**
|
---|
215 | * Converts a ByteArray to a sequence of 16-word blocks
|
---|
216 | * that we'll do the processing on. Appends padding
|
---|
217 | * and length in the process.
|
---|
218 | *
|
---|
219 | * @param data The data to split into blocks
|
---|
220 | * @return An array containing the blocks into which data was split
|
---|
221 | */
|
---|
222 | private static function createBlocksFromByteArray( data:ByteArray ):Array
|
---|
223 | {
|
---|
224 | var oldPosition:int = data.position;
|
---|
225 | data.position = 0;
|
---|
226 |
|
---|
227 | var blocks:Array = new Array();
|
---|
228 | var len:int = data.length * 8;
|
---|
229 | var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
|
---|
230 | for( var i:int = 0; i < len; i += 8 )
|
---|
231 | {
|
---|
232 | blocks[ i >> 5 ] |= ( data.readByte() & mask ) << ( 24 - i % 32 );
|
---|
233 | }
|
---|
234 |
|
---|
235 | // append padding and length
|
---|
236 | blocks[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
|
---|
237 | blocks[ ( ( ( len + 64 ) >> 9 ) << 4 ) + 15 ] = len;
|
---|
238 |
|
---|
239 | data.position = oldPosition;
|
---|
240 |
|
---|
241 | return blocks;
|
---|
242 | }
|
---|
243 |
|
---|
244 | /**
|
---|
245 | * Converts a string to a sequence of 16-word blocks
|
---|
246 | * that we'll do the processing on. Appends padding
|
---|
247 | * and length in the process.
|
---|
248 | *
|
---|
249 | * @param s The string to split into blocks
|
---|
250 | * @return An array containing the blocks that s was split into.
|
---|
251 | */
|
---|
252 | private static function createBlocksFromString( s:String ):Array
|
---|
253 | {
|
---|
254 | var blocks:Array = new Array();
|
---|
255 | var len:int = s.length * 8;
|
---|
256 | var mask:int = 0xFF; // ignore hi byte of characters > 0xFF
|
---|
257 | for( var i:int = 0; i < len; i += 8 ) {
|
---|
258 | blocks[ i >> 5 ] |= ( s.charCodeAt( i / 8 ) & mask ) << ( 24 - i % 32 );
|
---|
259 | }
|
---|
260 |
|
---|
261 | // append padding and length
|
---|
262 | blocks[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
|
---|
263 | blocks[ ( ( ( len + 64 ) >> 9 ) << 4 ) + 15 ] = len;
|
---|
264 | return blocks;
|
---|
265 | }
|
---|
266 |
|
---|
267 | }
|
---|
268 | }
|
---|