|
| 1 | +var AES_Sbox_Inv; |
| 2 | +var AES_ShiftRowTab_Inv; |
| 3 | +var AES_xtime; |
| 4 | + |
| 5 | +/* |
| 6 | + v1.00 Jan.21.2014 |
| 7 | +*/ |
| 8 | +function AES_Init() { |
| 9 | + AES_Sbox_Inv = new Array(256); |
| 10 | + for(var i = 0; i < 256; i++) |
| 11 | + AES_Sbox_Inv[AES_Sbox[i]] = i; |
| 12 | + |
| 13 | + AES_ShiftRowTab_Inv = new Array(16); |
| 14 | + for(var i = 0; i < 16; i++) |
| 15 | + AES_ShiftRowTab_Inv[AES_ShiftRowTab[i]] = i; |
| 16 | + |
| 17 | + AES_xtime = new Array(256); |
| 18 | + for(var i = 0; i < 128; i++) { |
| 19 | + AES_xtime[i] = i << 1; |
| 20 | + AES_xtime[128 + i] = (i << 1) ^ 0x1b; |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +/* |
| 25 | + AES_Done: release memory reserved by AES_Init. Call this function after |
| 26 | + the last encryption/decryption operation. |
| 27 | +*/ |
| 28 | + |
| 29 | +function AES_Done() { |
| 30 | + delete AES_Sbox_Inv; |
| 31 | + delete AES_ShiftRowTab_Inv; |
| 32 | + delete AES_xtime; |
| 33 | +} |
| 34 | + |
| 35 | +/* |
| 36 | + AES_ExpandKey: expand a cipher key. Depending on the desired encryption |
| 37 | + strength of 128, 192 or 256 bits 'key' has to be a byte array of length |
| 38 | + 16, 24 or 32, respectively. The key expansion is done "in place", meaning |
| 39 | + that the array 'key' is modified. |
| 40 | +*/ |
| 41 | +/* No longer use. |
| 42 | +function AES_ExpandKey(key) { |
| 43 | + var kl = key.length, ks, Rcon = 1; |
| 44 | + switch (kl) { |
| 45 | + case 16: |
| 46 | + ks = 16 * (10 + 1); |
| 47 | + break; |
| 48 | + case 24: |
| 49 | + ks = 16 * (12 + 1); |
| 50 | + break; |
| 51 | + case 32: |
| 52 | + ks = 16 * (14 + 1); |
| 53 | + break; |
| 54 | + default: |
| 55 | + alert("AES_ExpandKey: Only key lengths of 16, 24 or 32 bytes allowed!"); |
| 56 | + } |
| 57 | + for(var i = kl; i < ks; i += 4) { |
| 58 | + var temp = key.slice(i - 4, i); |
| 59 | + if (i % kl == 0) { |
| 60 | + temp = new Array(AES_Sbox[temp[1]] ^ Rcon, AES_Sbox[temp[2]], |
| 61 | + AES_Sbox[temp[3]], AES_Sbox[temp[0]]); |
| 62 | + if ((Rcon <<= 1) >= 256) |
| 63 | + Rcon ^= 0x11b; |
| 64 | + } else if ((kl > 24) && (i % kl == 16)) |
| 65 | + temp = new Array(AES_Sbox[temp[0]], AES_Sbox[temp[1]], |
| 66 | + AES_Sbox[temp[2]], AES_Sbox[temp[3]]); |
| 67 | + for(var j = 0; j < 4; j++) |
| 68 | + key[i + j] = key[i + j - kl] ^ temp[j]; |
| 69 | + } |
| 70 | + return key; |
| 71 | +} |
| 72 | +*/ |
| 73 | +/* |
| 74 | + AES_Encrypt: encrypt the 16 byte array 'block' with the previously |
| 75 | + expanded key 'key'. |
| 76 | +*/ |
| 77 | + |
| 78 | +function AES_Encrypt(block, key) { |
| 79 | + var l = key.length; |
| 80 | + AES_AddRoundKey(block, key.slice(0, 16)); |
| 81 | + for(var i = 16; i < l - 16; i += 16) { |
| 82 | + AES_SubBytes(block, AES_Sbox); |
| 83 | + AES_ShiftRows(block, AES_ShiftRowTab); |
| 84 | + AES_MixColumns(block); |
| 85 | + AES_AddRoundKey(block, key.slice(i, i + 16)); |
| 86 | + } |
| 87 | + AES_SubBytes(block, AES_Sbox); |
| 88 | + AES_ShiftRows(block, AES_ShiftRowTab); |
| 89 | + AES_AddRoundKey(block, key.slice(i, l)); |
| 90 | + return block; |
| 91 | +} |
| 92 | + |
| 93 | +/* |
| 94 | + AES_Decrypt: decrypt the 16 byte array 'block' with the previously |
| 95 | + expanded key 'key'. |
| 96 | +*/ |
| 97 | + |
| 98 | +function AES_Decrypt(block, key) { |
| 99 | + var l = key.length; |
| 100 | + AES_AddRoundKey(block, key.slice(l - 16, l)); |
| 101 | + AES_ShiftRows(block, AES_ShiftRowTab_Inv); |
| 102 | + AES_SubBytes(block, AES_Sbox_Inv); |
| 103 | + for(var i = l - 32; i >= 16; i -= 16) { |
| 104 | + AES_AddRoundKey(block, key.slice(i, i + 16)); |
| 105 | + AES_MixColumns_Inv(block); |
| 106 | + AES_ShiftRows(block, AES_ShiftRowTab_Inv); |
| 107 | + AES_SubBytes(block, AES_Sbox_Inv); |
| 108 | + } |
| 109 | + AES_AddRoundKey(block, key.slice(0, 16)); |
| 110 | + return block; |
| 111 | +} |
| 112 | + |
| 113 | +/******************************************************************************/ |
| 114 | + |
| 115 | +/* The following lookup tables and functions are for internal use only! */ |
| 116 | + |
| 117 | +AES_Sbox = new Array(99,124,119,123,242,107,111,197,48,1,103,43,254,215,171, |
| 118 | + 118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253, |
| 119 | + 147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154, |
| 120 | + 7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227, |
| 121 | + 47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170, |
| 122 | + 251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245, |
| 123 | + 188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61, |
| 124 | + 100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224, |
| 125 | + 50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213, |
| 126 | + 78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221, |
| 127 | + 116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29, |
| 128 | + 158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161, |
| 129 | + 137,13,191,230,66,104,65,153,45,15,176,84,187,22); |
| 130 | + |
| 131 | +AES_ShiftRowTab = new Array(0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11); |
| 132 | + |
| 133 | +function AES_SubBytes(state, sbox) { |
| 134 | + for(var i = 0; i < 16; i++) |
| 135 | + state[i] = sbox[state[i]]; |
| 136 | +} |
| 137 | + |
| 138 | +function AES_AddRoundKey(state, rkey) { |
| 139 | + for(var i = 0; i < 16; i++) |
| 140 | + state[i] ^= rkey[i]; |
| 141 | +} |
| 142 | + |
| 143 | +function AES_ShiftRows(state, shifttab) { |
| 144 | + var h = new Array().concat(state); |
| 145 | + for(var i = 0; i < 16; i++) |
| 146 | + state[i] = h[shifttab[i]]; |
| 147 | +} |
| 148 | + |
| 149 | +function AES_MixColumns(state) { |
| 150 | + for(var i = 0; i < 16; i += 4) { |
| 151 | + var s0 = state[i + 0], s1 = state[i + 1]; |
| 152 | + var s2 = state[i + 2], s3 = state[i + 3]; |
| 153 | + var h = s0 ^ s1 ^ s2 ^ s3; |
| 154 | + state[i + 0] ^= h ^ AES_xtime[s0 ^ s1]; |
| 155 | + state[i + 1] ^= h ^ AES_xtime[s1 ^ s2]; |
| 156 | + state[i + 2] ^= h ^ AES_xtime[s2 ^ s3]; |
| 157 | + state[i + 3] ^= h ^ AES_xtime[s3 ^ s0]; |
| 158 | + } |
| 159 | +} |
| 160 | + |
| 161 | +function AES_MixColumns_Inv(state) { |
| 162 | + for(var i = 0; i < 16; i += 4) { |
| 163 | + var s0 = state[i + 0], s1 = state[i + 1]; |
| 164 | + var s2 = state[i + 2], s3 = state[i + 3]; |
| 165 | + var h = s0 ^ s1 ^ s2 ^ s3; |
| 166 | + var xh = AES_xtime[h]; |
| 167 | + var h1 = AES_xtime[AES_xtime[xh ^ s0 ^ s2]] ^ h; |
| 168 | + var h2 = AES_xtime[AES_xtime[xh ^ s1 ^ s3]] ^ h; |
| 169 | + state[i + 0] ^= h1 ^ AES_xtime[s0 ^ s1]; |
| 170 | + state[i + 1] ^= h2 ^ AES_xtime[s1 ^ s2]; |
| 171 | + state[i + 2] ^= h1 ^ AES_xtime[s2 ^ s3]; |
| 172 | + state[i + 3] ^= h2 ^ AES_xtime[s3 ^ s0]; |
| 173 | + } |
| 174 | +} |
| 175 | + |
| 176 | +function hexstr2array(input, length) { |
| 177 | + var output = new Array(length); |
| 178 | + var i=0; |
| 179 | + |
| 180 | + for (i=0; i<length; i++) { |
| 181 | + if (i < input.length/2) { |
| 182 | + output[i] = parseInt(input.substr(i*2,2),16); |
| 183 | + } else { |
| 184 | + output[i] = 0; |
| 185 | + } |
| 186 | + } |
| 187 | + return output; |
| 188 | +} |
| 189 | + |
| 190 | +function str2hexstr(input) { |
| 191 | + var output=""; |
| 192 | + for (var a = 0; a < input.length; a = a + 1) { |
| 193 | + output = output + input.charCodeAt(a).toString(16); |
| 194 | + } |
| 195 | + return output; |
| 196 | +} |
| 197 | + |
| 198 | +function array2hexstr(input) { |
| 199 | + var len=input.length; |
| 200 | + var output=""; |
| 201 | + for (var i=0; i< len; i++) { |
| 202 | + var tmp=input[i].toString(16); |
| 203 | + if (tmp.length == 1) { |
| 204 | + tmp = "0" + tmp; |
| 205 | + } |
| 206 | + output = output + tmp; |
| 207 | + } |
| 208 | + return output; |
| 209 | +} |
| 210 | + |
| 211 | +function hexstr2str(input) { |
| 212 | + var output=""; |
| 213 | + for (var i=0; i < input.length; i=i+2) { |
| 214 | + var hexstr = input.substr(i, 2); |
| 215 | + if(hexstr=="00") break; |
| 216 | + else output = output + String.fromCharCode(parseInt(hexstr, 16)); |
| 217 | + } |
| 218 | + return output; |
| 219 | +} |
| 220 | +exports.AES_Encrypt128 = function (passwd, PrivateKey) |
| 221 | +{ |
| 222 | + var passwd_hex = str2hexstr(passwd); |
| 223 | + |
| 224 | + if (PrivateKey.length > 32) { |
| 225 | + PrivateKey = PrivateKey.substr(0,32); |
| 226 | + } |
| 227 | + |
| 228 | + var private_key_byte = hexstr2array(PrivateKey, 32); |
| 229 | + var passwd_byte = hexstr2array(passwd_hex, 64); |
| 230 | + var output=""; |
| 231 | + var output_byte = new Array(64); |
| 232 | + AES_Init(); |
| 233 | + |
| 234 | + for (var i=0; i<4; i++) { |
| 235 | + var block = new Array(16); |
| 236 | + |
| 237 | + for (var j=0; j<16; j++) |
| 238 | + { |
| 239 | + block[j] = passwd_byte[i*16+j]; |
| 240 | + } |
| 241 | + block = AES_Encrypt(block,private_key_byte); |
| 242 | + |
| 243 | + for (var j=0; j<16; j++) |
| 244 | + { |
| 245 | + output_byte[i*16+j] = block[j]; |
| 246 | + } |
| 247 | + } |
| 248 | + |
| 249 | + output = array2hexstr(output_byte); |
| 250 | + AES_Done(); |
| 251 | + return output; |
| 252 | +} |
| 253 | + |
| 254 | +function AES_Encrypt_SeqNo(passwd, key) |
| 255 | +{ |
| 256 | + var passwd_hex = str2hexstr(passwd); |
| 257 | + |
| 258 | + if (key.length > 32) { |
| 259 | + key = key.substr(0,32); |
| 260 | + } |
| 261 | + |
| 262 | + var private_key_byte = hexstr2array(key, 32); |
| 263 | + var passwd_byte = hexstr2array(passwd_hex, 64); |
| 264 | + var output=""; |
| 265 | + var output_byte = new Array(64); |
| 266 | + AES_Init(); |
| 267 | + |
| 268 | + for (var i=0; i<4; i++) { |
| 269 | + var block = new Array(16); |
| 270 | + |
| 271 | + for (var j=0; j<16; j++) |
| 272 | + { |
| 273 | + block[j] = passwd_byte[i*16+j]; |
| 274 | + } |
| 275 | + block = AES_Encrypt(block,private_key_byte); |
| 276 | + |
| 277 | + for (var j=0; j<16; j++) |
| 278 | + { |
| 279 | + output_byte[i*16+j] = block[j]; |
| 280 | + } |
| 281 | + } |
| 282 | + |
| 283 | + output = array2hexstr(output_byte); |
| 284 | + AES_Done(); |
| 285 | + return output; |
| 286 | +} |
| 287 | + |
| 288 | +function AES_Decrypt128(encrypted) |
| 289 | +{ |
| 290 | + var PrivateKey = localStorage.getItem('PrivateKey'); |
| 291 | + if (PrivateKey.length > 32) { |
| 292 | + PrivateKey = PrivateKey.substr(0,32); |
| 293 | + } |
| 294 | + |
| 295 | + var private_key_byte = hexstr2array(PrivateKey, 32); |
| 296 | + var encrypted_byte = hexstr2array(encrypted, 64); |
| 297 | + var output=""; |
| 298 | + var output_byte = new Array(64); |
| 299 | + AES_Init(); |
| 300 | + |
| 301 | + for (var i=0; i<4; i++) { |
| 302 | + var block = new Array(16); |
| 303 | + |
| 304 | + for (var j=0; j<16; j++) |
| 305 | + { |
| 306 | + block[j] = encrypted_byte[i*16+j]; |
| 307 | + } |
| 308 | + block = AES_Decrypt(block,private_key_byte); |
| 309 | + |
| 310 | + for (var j=0; j<16; j++) |
| 311 | + { |
| 312 | + output_byte[i*16+j] = block[j]; |
| 313 | + } |
| 314 | + } |
| 315 | + |
| 316 | + output = array2hexstr(output_byte); |
| 317 | + output = hexstr2str(output); |
| 318 | + AES_Done(); |
| 319 | + return output; |
| 320 | +} |
0 commit comments