1  /**
     2   * com.sekati.crypt.SHA256
     3   * @version 1.0.7
     4   * @author jason m horwitz | sekati.com
     5   * Copyright (C) 2007  jason m horwitz, Sekat LLC. All Rights Reserved.
     6   * Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
     7   */
     8  import com.sekati.crypt.IHash;
     9  
    10  /**
    11   * Calculate NIST compatible SHA256 checksum hash. 
    12   * @see {@link http://anmar.eu.org/projects/jssha2}
    13   */
    14  class com.sekati.crypt.SHA256 implements IHash {
    15  
    16  	/* bits per input character. 8 - ASCII; 16 - Unicode      */
    17  	//private var chrsz:Number = 8;
    18  	/* hex output format. 0 - lowercase; 1 - uppercase        */
    19  	//private var hexcase:Number = 0;
    20  	
    21  	/**
    22  	 * Calculates the SHA256 checksum.
    23  	 * @param src (String) string to hash
    24  	 * @return String
    25  	 */
    26  	public static function calculate(str:String):String {
    27  		return hex_sha256( str );
    28  	}
    29  
    30  	private static function safe_add(x:Number, y:Number):Number {
    31  		var lsw:Number = (x & 0xFFFF) + (y & 0xFFFF);
    32  		var msw:Number = (x >> 16) + (y >> 16) + (lsw >> 16);
    33  		return (msw << 16) | (lsw & 0xFFFF);
    34  	}
    35  
    36  	private static function S(X:Number, n:Number):Number { 
    37  		return (X >>> n) | (X << (32 - n)); 
    38  	}
    39  
    40  	private static function R(X:Number, n:Number):Number { 
    41  		return (X >>> n); 
    42  	}
    43  
    44  	private static function Ch(x:Number, y:Number, z:Number):Number { 
    45  		return ((x & y) ^ ((~x) & z)); 
    46  	}
    47  
    48  	private static function Maj(x:Number, y:Number, z:Number):Number { 
    49  		return ((x & y) ^ (x & z) ^ (y & z)); 
    50  	}
    51  
    52  	private static function Sigma0256(x:Number):Number { 
    53  		return (S( x, 2 ) ^ S( x, 13 ) ^ S( x, 22 )); 
    54  	}
    55  
    56  	private static function Sigma1256(x:Number):Number { 
    57  		return (S( x, 6 ) ^ S( x, 11 ) ^ S( x, 25 )); 
    58  	}
    59  
    60  	private static function Gamma0256(x:Number):Number { 
    61  		return (S( x, 7 ) ^ S( x, 18 ) ^ R( x, 3 )); 
    62  	}
    63  
    64  	private static function Gamma1256(x:Number):Number { 
    65  		return (S( x, 17 ) ^ S( x, 19 ) ^ R( x, 10 )); 
    66  	}
    67  
    68  	private static function Sigma0512(x:Number):Number { 
    69  		return (S( x, 28 ) ^ S( x, 34 ) ^ S( x, 39 )); 
    70  	}
    71  
    72  	private static function Sigma1512(x:Number):Number { 
    73  		return (S( x, 14 ) ^ S( x, 18 ) ^ S( x, 41 )); 
    74  	}
    75  
    76  	private static function Gamma0512(x:Number):Number { 
    77  		return (S( x, 1 ) ^ S( x, 8 ) ^ R( x, 7 )); 
    78  	}
    79  
    80  	private static function Gamma1512(x:Number):Number { 
    81  		return (S( x, 19 ) ^ S( x, 61 ) ^ R( x, 6 )); 
    82  	}
    83  
    84  	private static function core_sha256(m:Array, l:Number):Array {
    85  		var K:Array = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 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 ];
    86  		var HASH:Array = [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ];
    87  		var W:Array = new Array( 64 );
    88  		var a:Number, b:Number, c:Number, d:Number, e:Number, f:Number, g:Number, h:Number, i:Number, j:Number;
    89  		var T1:Number, T2:Number;
    90  		/* append padding */
    91  		m[l >> 5] |= 0x80 << (24 - l % 32);
    92  		m[((l + 64 >> 9) << 4) + 15] = l;
    93  		for (i = 0; i < m.length ; i += 16) {
    94  			a = HASH[0];
    95  			b = HASH[1];
    96  			c = HASH[2];
    97  			d = HASH[3];
    98  			e = HASH[4];
    99  			f = HASH[5];
   100  			g = HASH[6];
   101  			h = HASH[7];
   102  			for (j = 0; j < 64 ; j++) {
   103  				if (j < 16) {
   104  					W[j] = m[j + i];
   105  				} else {
   106  					W[j] = safe_add( safe_add( safe_add( Gamma1256( W[j - 2] ), W[j - 7] ), Gamma0256( W[j - 15] ) ), W[j - 16] );
   107  				}
   108  				T1 = safe_add( safe_add( safe_add( safe_add( h, Sigma1256( e ) ), Ch( e, f, g ) ), K[j] ), W[j] );
   109  				T2 = safe_add( Sigma0256( a ), Maj( a, b, c ) );
   110  				h = g;
   111  				g = f;
   112  				f = e;
   113  				e = safe_add( d, T1 );
   114  				d = c;
   115  				c = b;
   116  				b = a;
   117  				a = safe_add( T1, T2 );
   118  			}
   119  			HASH[0] = safe_add( a, HASH[0] );
   120  			HASH[1] = safe_add( b, HASH[1] );
   121  			HASH[2] = safe_add( c, HASH[2] );
   122  			HASH[3] = safe_add( d, HASH[3] );
   123  			HASH[4] = safe_add( e, HASH[4] );
   124  			HASH[5] = safe_add( f, HASH[5] );
   125  			HASH[6] = safe_add( g, HASH[6] );
   126  			HASH[7] = safe_add( h, HASH[7] );
   127  		}
   128  		return HASH;
   129  	}
   130  
   131  	/*
   132  	private static function core_sha512 (m:Array, l:Number):Void {
   133  	var K:Array = [0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817];
   134  	var HASH:Array = [0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179];
   135  	var W:Array = new Array (80);
   136  	var a:Number, b:Number, c:Number, d:Number, e:Number, f:Number, g:Number, h:Number, i:Number, j:Number;
   137  	var T1:Number, T2:Number;
   138  	}
   139  	 */
   140  	private static function str2binb(str:String):Array {
   141  		var bin:Array = new Array( );
   142  		var mask:Number = (1 << 8) - 1;
   143  		for (var i:Number = 0; i < str.length * 8 ; i += 8) {
   144  			bin[i >> 5] |= (str.charCodeAt( i / 8 ) & mask) << (24 - i % 32);
   145  		}
   146  		return bin;
   147  	}
   148  
   149  	private static function binb2str(bin:Array):String {
   150  		var str:String = "";
   151  		var mask:Number = (1 << 8) - 1;
   152  		for (var i:Number = 0; i < bin.length * 32 ; i += 8) {
   153  			str += String.fromCharCode( (bin[i >> 5] >>> (24 - i % 32)) & mask );
   154  		}
   155  		return str;
   156  	}
   157  
   158  	private static function binb2hex(binarray:Array):String {
   159  		var hex_tab:String = 0 ? "0123456789ABCDEF" : "0123456789abcdef";
   160  		var str:String = "";
   161  		for (var i:Number = 0; i < binarray.length * 4 ; i++) {
   162  			str += hex_tab.charAt( (binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF ) + hex_tab.charAt( (binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF );
   163  		}
   164  		return str;
   165  	}
   166  
   167  	/*
   168  	function binb2b64 (binarray:Array):String {
   169  	var tab:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
   170  	var str:String = "";
   171  	for(var i:Number = 0; i < binarray.length * 4; i += 3) {
   172  	var triplet:Number = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16) | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
   173  	for(var j:Number = 0; j < 4; j++) {
   174  	if (i * 8 + j * 6 > binarray.length * 32) str += b64pad; else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
   175  	}
   176  	}
   177  	return str;
   178  	}	
   179  	 */
   180  	private static function hex_sha256(s:String):String {
   181  		return binb2hex( core_sha256( str2binb( s ), s.length * 8 ) );
   182  	}
   183  
   184  	private static function str_sha256(s:String):String {
   185  		return binb2str( core_sha256( str2binb( s ), s.length * 8 ) );
   186  	}
   187  
   188  	private function SHA256() {
   189  	}
   190  }