1 // ========================================================================== 2 // Project: The M-Project - Mobile HTML5 Application Framework 3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved. 4 // Creator: Dominik 5 // Date: 11.11.2010 6 // License: Dual licensed under the MIT or GPL Version 2 licenses. 7 // http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE 8 // http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE 9 // ========================================================================== 10 11 m_require('core/foundation/object.js'); 12 13 /** 14 * @class 15 * 16 * This prototype defines a hashing mechanism based on the SHA256 algorithm. You normally 17 * don't call this object respectively its methods directly, but let M.Cypher handle 18 * this. 19 * 20 * @extends M.Object 21 */ 22 M.SHA256 = M.Object.extend( 23 /** @scope M.SHA256.prototype */ { 24 25 /** 26 * The type of this object. 27 * 28 * @type String 29 */ 30 type: 'M.SHA256', 31 32 /** 33 * Defines the bits per input character: 8 - ASCII, 16 - Unicode 34 * 35 * @type Number 36 */ 37 chrsz: 8, 38 39 /** 40 * Defines the hex output format: 0 - lowercase, 1 - uppercase 41 * 42 * @type Number 43 */ 44 hexcase: 0, 45 46 /** 47 * This method is called from the 'outside world', controls the hashing and 48 * finally returns the hash value. 49 * 50 * @param {String} input The input string to be hashed. 51 * @returns {String} The sha256 hashed string. 52 */ 53 hash: function(input) { 54 input = M.Cypher.utf8_encode(input); 55 return this.binb2hex(this.core_sha256(this.str2binb(input), input.length * this.chrsz)); 56 }, 57 58 /** 59 * @private 60 */ 61 safe_add: function(x, y) { 62 var lsw = (x & 0xFFFF) + (y & 0xFFFF); 63 var msw = (x >> 16) + (y >> 16) + (lsw >> 16); 64 return (msw << 16) | (lsw & 0xFFFF); 65 }, 66 67 /** 68 * @private 69 */ 70 S: function(X, n) { 71 return ( X >>> n ) | (X << (32 - n)); 72 }, 73 74 /** 75 * @private 76 */ 77 R: function(X, n) { 78 return ( X >>> n ); 79 }, 80 81 /** 82 * @private 83 */ 84 Ch: function(x, y, z) { 85 return ((x & y) ^ ((~x) & z)); 86 }, 87 88 /** 89 * @private 90 */ 91 Maj: function(x, y, z) { 92 return ((x & y) ^ (x & z) ^ (y & z)); 93 }, 94 95 /** 96 * @private 97 */ 98 Sigma0256: function(x) { 99 return (this.S(x, 2) ^ this.S(x, 13) ^ this.S(x, 22)); 100 }, 101 102 /** 103 * @private 104 */ 105 Sigma1256: function(x) { 106 return (this.S(x, 6) ^ this.S(x, 11) ^ this.S(x, 25)); 107 }, 108 109 /** 110 * @private 111 */ 112 Gamma0256: function(x) { 113 return (this.S(x, 7) ^ this.S(x, 18) ^ this.R(x, 3)); 114 }, 115 116 /** 117 * @private 118 */ 119 Gamma1256: function(x) { 120 return (this.S(x, 17) ^ this.S(x, 19) ^ this.R(x, 10)); 121 }, 122 123 /** 124 * @private 125 */ 126 core_sha256: function(m, l) { 127 var K = new 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); 128 var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); 129 var W = new Array(64); 130 var a, b, c, d, e, f, g, h, i, j; 131 var T1, T2; 132 133 m[l >> 5] |= 0x80 << (24 - l % 32); 134 m[((l + 64 >> 9) << 4) + 15] = l; 135 136 for (var i = 0; i < m.length; i += 16) { 137 a = HASH[0]; 138 b = HASH[1]; 139 c = HASH[2]; 140 d = HASH[3]; 141 e = HASH[4]; 142 f = HASH[5]; 143 g = HASH[6]; 144 h = HASH[7]; 145 146 for (var j = 0; j < 64; j++) { 147 if (j < 16) W[j] = m[j + i]; 148 else W[j] = this.safe_add(this.safe_add(this.safe_add(this.Gamma1256(W[j - 2]), W[j - 7]), this.Gamma0256(W[j - 15])), W[j - 16]); 149 150 T1 = this.safe_add(this.safe_add(this.safe_add(this.safe_add(h, this.Sigma1256(e)), this.Ch(e, f, g)), K[j]), W[j]); 151 T2 = this.safe_add(this.Sigma0256(a), this.Maj(a, b, c)); 152 153 h = g; 154 g = f; 155 f = e; 156 e = this.safe_add(d, T1); 157 d = c; 158 c = b; 159 b = a; 160 a = this.safe_add(T1, T2); 161 } 162 163 HASH[0] = this.safe_add(a, HASH[0]); 164 HASH[1] = this.safe_add(b, HASH[1]); 165 HASH[2] = this.safe_add(c, HASH[2]); 166 HASH[3] = this.safe_add(d, HASH[3]); 167 HASH[4] = this.safe_add(e, HASH[4]); 168 HASH[5] = this.safe_add(f, HASH[5]); 169 HASH[6] = this.safe_add(g, HASH[6]); 170 HASH[7] = this.safe_add(h, HASH[7]); 171 } 172 return HASH; 173 }, 174 175 /** 176 * @private 177 */ 178 str2binb: function(str) { 179 var bin = Array(); 180 var mask = (1 << this.chrsz) - 1; 181 for (var i = 0; i < str.length * this.chrsz; i += this.chrsz) { 182 bin[i >> 5] |= (str.charCodeAt(i / this.chrsz) & mask) << (24 - i % 32); 183 } 184 return bin; 185 }, 186 187 /** 188 * @private 189 */ 190 binb2hex: function(binarray) { 191 var hex_tab = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 192 var str = ""; 193 for (var i = 0; i < binarray.length * 4; i++) { 194 str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + 195 hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 )) & 0xF); 196 } 197 return str; 198 } 199 200 });