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