[7849] | 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 | }
|
---|