build/pgo/js-input/crypto-aes.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/build/pgo/js-input/crypto-aes.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,472 @@
     1.4 +<!DOCTYPE html>
     1.5 +<head>
     1.6 +<!--
     1.7 + Copyright (C) 2007 Apple Inc.  All rights reserved.
     1.8 +
     1.9 + Redistribution and use in source and binary forms, with or without
    1.10 + modification, are permitted provided that the following conditions
    1.11 + are met:
    1.12 + 1. Redistributions of source code must retain the above copyright
    1.13 +    notice, this list of conditions and the following disclaimer.
    1.14 + 2. Redistributions in binary form must reproduce the above copyright
    1.15 +    notice, this list of conditions and the following disclaimer in the
    1.16 +    documentation and/or other materials provided with the distribution.
    1.17 +
    1.18 + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
    1.19 + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.20 + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    1.21 + PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
    1.22 + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    1.23 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    1.24 + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    1.25 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    1.26 + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.27 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.28 + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    1.29 +-->
    1.30 +
    1.31 +<title>SunSpider crypto-aes</title>
    1.32 +
    1.33 +</head>
    1.34 +
    1.35 +<body>
    1.36 +<h3>crypto-aes</h3>
    1.37 +<div id="console">
    1.38 +</div>
    1.39 +
    1.40 +<script>
    1.41 +
    1.42 +var _sunSpiderStartDate = new Date();
    1.43 +
    1.44 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
    1.45 +
    1.46 +/*
    1.47 + * AES Cipher function: encrypt 'input' with Rijndael algorithm
    1.48 + *
    1.49 + *   takes   byte-array 'input' (16 bytes)
    1.50 + *           2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
    1.51 + *
    1.52 + *   applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
    1.53 + *
    1.54 + *   returns byte-array encrypted value (16 bytes)
    1.55 + */
    1.56 +function Cipher(input, w) {    // main Cipher function [§5.1]
    1.57 +  var Nb = 4;               // block size (in words): no of columns in state (fixed at 4 for AES)
    1.58 +  var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
    1.59 +
    1.60 +  var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [§3.4]
    1.61 +  for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
    1.62 +
    1.63 +  state = AddRoundKey(state, w, 0, Nb);
    1.64 +
    1.65 +  for (var round=1; round<Nr; round++) {
    1.66 +    state = SubBytes(state, Nb);
    1.67 +    state = ShiftRows(state, Nb);
    1.68 +    state = MixColumns(state, Nb);
    1.69 +    state = AddRoundKey(state, w, round, Nb);
    1.70 +  }
    1.71 +
    1.72 +  state = SubBytes(state, Nb);
    1.73 +  state = ShiftRows(state, Nb);
    1.74 +  state = AddRoundKey(state, w, Nr, Nb);
    1.75 +
    1.76 +  var output = new Array(4*Nb);  // convert state to 1-d array before returning [§3.4]
    1.77 +  for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
    1.78 +  return output;
    1.79 +}
    1.80 +
    1.81 +
    1.82 +function SubBytes(s, Nb) {    // apply SBox to state S [§5.1.1]
    1.83 +  for (var r=0; r<4; r++) {
    1.84 +    for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
    1.85 +  }
    1.86 +  return s;
    1.87 +}
    1.88 +
    1.89 +
    1.90 +function ShiftRows(s, Nb) {    // shift row r of state S left by r bytes [§5.1.2]
    1.91 +  var t = new Array(4);
    1.92 +  for (var r=1; r<4; r++) {
    1.93 +    for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];  // shift into temp copy
    1.94 +    for (var c=0; c<4; c++) s[r][c] = t[c];         // and copy back
    1.95 +  }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
    1.96 +  return s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf 
    1.97 +}
    1.98 +
    1.99 +
   1.100 +function MixColumns(s, Nb) {   // combine bytes of each col of state S [§5.1.3]
   1.101 +  for (var c=0; c<4; c++) {
   1.102 +    var a = new Array(4);  // 'a' is a copy of the current column from 's'
   1.103 +    var b = new Array(4);  // 'b' is a•{02} in GF(2^8)
   1.104 +    for (var i=0; i<4; i++) {
   1.105 +      a[i] = s[i][c];
   1.106 +      b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
   1.107 +    }
   1.108 +    // a[n] ^ b[n] is a•{03} in GF(2^8)
   1.109 +    s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
   1.110 +    s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
   1.111 +    s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
   1.112 +    s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
   1.113 +  }
   1.114 +  return s;
   1.115 +}
   1.116 +
   1.117 +
   1.118 +function AddRoundKey(state, w, rnd, Nb) {  // xor Round Key into state S [§5.1.4]
   1.119 +  for (var r=0; r<4; r++) {
   1.120 +    for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
   1.121 +  }
   1.122 +  return state;
   1.123 +}
   1.124 +
   1.125 +
   1.126 +function KeyExpansion(key) {  // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
   1.127 +  var Nb = 4;            // block size (in words): no of columns in state (fixed at 4 for AES)
   1.128 +  var Nk = key.length/4  // key length (in words): 4/6/8 for 128/192/256-bit keys
   1.129 +  var Nr = Nk + 6;       // no of rounds: 10/12/14 for 128/192/256-bit keys
   1.130 +
   1.131 +  var w = new Array(Nb*(Nr+1));
   1.132 +  var temp = new Array(4);
   1.133 +
   1.134 +  for (var i=0; i<Nk; i++) {
   1.135 +    var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
   1.136 +    w[i] = r;
   1.137 +  }
   1.138 +
   1.139 +  for (var i=Nk; i<(Nb*(Nr+1)); i++) {
   1.140 +    w[i] = new Array(4);
   1.141 +    for (var t=0; t<4; t++) temp[t] = w[i-1][t];
   1.142 +    if (i % Nk == 0) {
   1.143 +      temp = SubWord(RotWord(temp));
   1.144 +      for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
   1.145 +    } else if (Nk > 6 && i%Nk == 4) {
   1.146 +      temp = SubWord(temp);
   1.147 +    }
   1.148 +    for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
   1.149 +  }
   1.150 +
   1.151 +  return w;
   1.152 +}
   1.153 +
   1.154 +function SubWord(w) {    // apply SBox to 4-byte word w
   1.155 +  for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
   1.156 +  return w;
   1.157 +}
   1.158 +
   1.159 +function RotWord(w) {    // rotate 4-byte word w left by one byte
   1.160 +  w[4] = w[0];
   1.161 +  for (var i=0; i<4; i++) w[i] = w[i+1];
   1.162 +  return w;
   1.163 +}
   1.164 +
   1.165 +
   1.166 +// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
   1.167 +var Sbox =  [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
   1.168 +             0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
   1.169 +             0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
   1.170 +             0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
   1.171 +             0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
   1.172 +             0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
   1.173 +             0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
   1.174 +             0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
   1.175 +             0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
   1.176 +             0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
   1.177 +             0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
   1.178 +             0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
   1.179 +             0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
   1.180 +             0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
   1.181 +             0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
   1.182 +             0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
   1.183 +
   1.184 +// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
   1.185 +var Rcon = [ [0x00, 0x00, 0x00, 0x00],
   1.186 +             [0x01, 0x00, 0x00, 0x00],
   1.187 +             [0x02, 0x00, 0x00, 0x00],
   1.188 +             [0x04, 0x00, 0x00, 0x00],
   1.189 +             [0x08, 0x00, 0x00, 0x00],
   1.190 +             [0x10, 0x00, 0x00, 0x00],
   1.191 +             [0x20, 0x00, 0x00, 0x00],
   1.192 +             [0x40, 0x00, 0x00, 0x00],
   1.193 +             [0x80, 0x00, 0x00, 0x00],
   1.194 +             [0x1b, 0x00, 0x00, 0x00],
   1.195 +             [0x36, 0x00, 0x00, 0x00] ]; 
   1.196 +
   1.197 +
   1.198 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   1.199 +
   1.200 +/* 
   1.201 + * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
   1.202 + *                           - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
   1.203 + *   for each block
   1.204 + *   - outputblock = cipher(counter, key)
   1.205 + *   - cipherblock = plaintext xor outputblock
   1.206 + */
   1.207 +function AESEncryptCtr(plaintext, password, nBits) {
   1.208 +  if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
   1.209 +
   1.210 +  // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; 
   1.211 +  // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
   1.212 +  var nBytes = nBits/8;  // no bytes in key
   1.213 +  var pwBytes = new Array(nBytes);
   1.214 +  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
   1.215 +  var key = Cipher(pwBytes, KeyExpansion(pwBytes));
   1.216 +  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
   1.217 +
   1.218 +  // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
   1.219 +  // block counter in 2nd 8 bytes
   1.220 +  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   1.221 +  var counterBlock = new Array(blockSize);  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   1.222 +  var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970
   1.223 +
   1.224 +  // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
   1.225 +  for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
   1.226 +  for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
   1.227 +
   1.228 +  // generate key schedule - an expansion of the key into distinct Key Rounds for each round
   1.229 +  var keySchedule = KeyExpansion(key);
   1.230 +
   1.231 +  var blockCount = Math.ceil(plaintext.length/blockSize);
   1.232 +  var ciphertext = new Array(blockCount);  // ciphertext as array of strings
   1.233 +  
   1.234 +  for (var b=0; b<blockCount; b++) {
   1.235 +    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
   1.236 +    // again done in two stages for 32-bit ops
   1.237 +    for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
   1.238 +    for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
   1.239 +
   1.240 +    var cipherCntr = Cipher(counterBlock, keySchedule);  // -- encrypt counter block --
   1.241 +    
   1.242 +    // calculate length of final block:
   1.243 +    var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
   1.244 +
   1.245 +    var ct = '';
   1.246 +    for (var i=0; i<blockLength; i++) {  // -- xor plaintext with ciphered counter byte-by-byte --
   1.247 +      var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
   1.248 +      var cipherByte = plaintextByte ^ cipherCntr[i];
   1.249 +      ct += String.fromCharCode(cipherByte);
   1.250 +    }
   1.251 +    // ct is now ciphertext for this block
   1.252 +
   1.253 +    ciphertext[b] = escCtrlChars(ct);  // escape troublesome characters in ciphertext
   1.254 +  }
   1.255 +
   1.256 +  // convert the nonce to a string to go on the front of the ciphertext
   1.257 +  var ctrTxt = '';
   1.258 +  for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
   1.259 +  ctrTxt = escCtrlChars(ctrTxt);
   1.260 +
   1.261 +  // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
   1.262 +  return ctrTxt + '-' + ciphertext.join('-');
   1.263 +}
   1.264 +
   1.265 +
   1.266 +/* 
   1.267 + * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
   1.268 + *
   1.269 + *   for each block
   1.270 + *   - outputblock = cipher(counter, key)
   1.271 + *   - cipherblock = plaintext xor outputblock
   1.272 + */
   1.273 +function AESDecryptCtr(ciphertext, password, nBits) {
   1.274 +  if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
   1.275 +
   1.276 +  var nBytes = nBits/8;  // no bytes in key
   1.277 +  var pwBytes = new Array(nBytes);
   1.278 +  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
   1.279 +  var pwKeySchedule = KeyExpansion(pwBytes);
   1.280 +  var key = Cipher(pwBytes, pwKeySchedule);
   1.281 +  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
   1.282 +
   1.283 +  var keySchedule = KeyExpansion(key);
   1.284 +
   1.285 +  ciphertext = ciphertext.split('-');  // split ciphertext into array of block-length strings 
   1.286 +
   1.287 +  // recover nonce from 1st element of ciphertext
   1.288 +  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   1.289 +  var counterBlock = new Array(blockSize);
   1.290 +  var ctrTxt = unescCtrlChars(ciphertext[0]);
   1.291 +  for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
   1.292 +
   1.293 +  var plaintext = new Array(ciphertext.length-1);
   1.294 +
   1.295 +  for (var b=1; b<ciphertext.length; b++) {
   1.296 +    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
   1.297 +    for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
   1.298 +    for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
   1.299 +
   1.300 +    var cipherCntr = Cipher(counterBlock, keySchedule);  // encrypt counter block
   1.301 +
   1.302 +    ciphertext[b] = unescCtrlChars(ciphertext[b]);
   1.303 +
   1.304 +    var pt = '';
   1.305 +    for (var i=0; i<ciphertext[b].length; i++) {
   1.306 +      // -- xor plaintext with ciphered counter byte-by-byte --
   1.307 +      var ciphertextByte = ciphertext[b].charCodeAt(i);
   1.308 +      var plaintextByte = ciphertextByte ^ cipherCntr[i];
   1.309 +      pt += String.fromCharCode(plaintextByte);
   1.310 +    }
   1.311 +    // pt is now plaintext for this block
   1.312 +
   1.313 +    plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext
   1.314 +  }
   1.315 +
   1.316 +  return plaintext.join('');
   1.317 +}
   1.318 +
   1.319 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   1.320 +
   1.321 +function escCtrlChars(str) {  // escape control chars which might cause problems handling ciphertext
   1.322 +  return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
   1.323 +}  // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
   1.324 +
   1.325 +function unescCtrlChars(str) {  // unescape potentially problematic control characters
   1.326 +  return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
   1.327 +}
   1.328 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   1.329 +
   1.330 +/*
   1.331 + * if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead
   1.332 + */
   1.333 +var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
   1.334 +
   1.335 +function encodeBase64(str) {  // http://tools.ietf.org/html/rfc4648
   1.336 +   var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
   1.337 +   
   1.338 +   str = encodeUTF8(str);  // encode multi-byte chars into UTF-8 for byte-array
   1.339 +
   1.340 +   do {  // pack three octets into four hexets
   1.341 +      o1 = str.charCodeAt(i++);
   1.342 +      o2 = str.charCodeAt(i++);
   1.343 +      o3 = str.charCodeAt(i++);
   1.344 +      
   1.345 +      bits = o1<<16 | o2<<8 | o3;
   1.346 +      
   1.347 +      h1 = bits>>18 & 0x3f;
   1.348 +      h2 = bits>>12 & 0x3f;
   1.349 +      h3 = bits>>6 & 0x3f;
   1.350 +      h4 = bits & 0x3f;
   1.351 +      
   1.352 +      // end of string? index to '=' in b64
   1.353 +      if (isNaN(o3)) h4 = 64;
   1.354 +      if (isNaN(o2)) h3 = 64;
   1.355 +      
   1.356 +      // use hexets to index into b64, and append result to encoded string
   1.357 +      enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
   1.358 +   } while (i < str.length);
   1.359 +   
   1.360 +   return enc;
   1.361 +}
   1.362 +
   1.363 +function decodeBase64(str) {
   1.364 +   var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
   1.365 +
   1.366 +   do {  // unpack four hexets into three octets using index points in b64
   1.367 +      h1 = b64.indexOf(str.charAt(i++));
   1.368 +      h2 = b64.indexOf(str.charAt(i++));
   1.369 +      h3 = b64.indexOf(str.charAt(i++));
   1.370 +      h4 = b64.indexOf(str.charAt(i++));
   1.371 +      
   1.372 +      bits = h1<<18 | h2<<12 | h3<<6 | h4;
   1.373 +      
   1.374 +      o1 = bits>>16 & 0xff;
   1.375 +      o2 = bits>>8 & 0xff;
   1.376 +      o3 = bits & 0xff;
   1.377 +      
   1.378 +      if (h3 == 64)      enc += String.fromCharCode(o1);
   1.379 +      else if (h4 == 64) enc += String.fromCharCode(o1, o2);
   1.380 +      else               enc += String.fromCharCode(o1, o2, o3);
   1.381 +   } while (i < str.length);
   1.382 +
   1.383 +   return decodeUTF8(enc);  // decode UTF-8 byte-array back to Unicode
   1.384 +}
   1.385 +
   1.386 +function encodeUTF8(str) {  // encode multi-byte string into utf-8 multiple single-byte characters 
   1.387 +  str = str.replace(
   1.388 +      /[\u0080-\u07ff]/g,  // U+0080 - U+07FF = 2-byte chars
   1.389 +      function(c) { 
   1.390 +        var cc = c.charCodeAt(0);
   1.391 +        return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
   1.392 +    );
   1.393 +  str = str.replace(
   1.394 +      /[\u0800-\uffff]/g,  // U+0800 - U+FFFF = 3-byte chars
   1.395 +      function(c) { 
   1.396 +        var cc = c.charCodeAt(0); 
   1.397 +        return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
   1.398 +    );
   1.399 +  return str;
   1.400 +}
   1.401 +
   1.402 +function decodeUTF8(str) {  // decode utf-8 encoded string back into multi-byte characters
   1.403 +  str = str.replace(
   1.404 +      /[\u00c0-\u00df][\u0080-\u00bf]/g,                 // 2-byte chars
   1.405 +      function(c) { 
   1.406 +        var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
   1.407 +        return String.fromCharCode(cc); }
   1.408 +    );
   1.409 +  str = str.replace(
   1.410 +      /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,  // 3-byte chars
   1.411 +      function(c) { 
   1.412 +        var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f; 
   1.413 +        return String.fromCharCode(cc); }
   1.414 +    );
   1.415 +  return str;
   1.416 +}
   1.417 +
   1.418 +
   1.419 +function byteArrayToHexStr(b) {  // convert byte array to hex string for displaying test vectors
   1.420 +  var s = '';
   1.421 +  for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' ';
   1.422 +  return s;
   1.423 +}
   1.424 +
   1.425 +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   1.426 +
   1.427 +
   1.428 +var plainText = "ROMEO: But, soft! what light through yonder window breaks?\n\
   1.429 +It is the east, and Juliet is the sun.\n\
   1.430 +Arise, fair sun, and kill the envious moon,\n\
   1.431 +Who is already sick and pale with grief,\n\
   1.432 +That thou her maid art far more fair than she:\n\
   1.433 +Be not her maid, since she is envious;\n\
   1.434 +Her vestal livery is but sick and green\n\
   1.435 +And none but fools do wear it; cast it off.\n\
   1.436 +It is my lady, O, it is my love!\n\
   1.437 +O, that she knew she were!\n\
   1.438 +She speaks yet she says nothing: what of that?\n\
   1.439 +Her eye discourses; I will answer it.\n\
   1.440 +I am too bold, 'tis not to me she speaks:\n\
   1.441 +Two of the fairest stars in all the heaven,\n\
   1.442 +Having some business, do entreat her eyes\n\
   1.443 +To twinkle in their spheres till they return.\n\
   1.444 +What if her eyes were there, they in her head?\n\
   1.445 +The brightness of her cheek would shame those stars,\n\
   1.446 +As daylight doth a lamp; her eyes in heaven\n\
   1.447 +Would through the airy region stream so bright\n\
   1.448 +That birds would sing and think it were not night.\n\
   1.449 +See, how she leans her cheek upon her hand!\n\
   1.450 +O, that I were a glove upon that hand,\n\
   1.451 +That I might touch that cheek!\n\
   1.452 +JULIET: Ay me!\n\
   1.453 +ROMEO: She speaks:\n\
   1.454 +O, speak again, bright angel! for thou art\n\
   1.455 +As glorious to this night, being o'er my head\n\
   1.456 +As is a winged messenger of heaven\n\
   1.457 +Unto the white-upturned wondering eyes\n\
   1.458 +Of mortals that fall back to gaze on him\n\
   1.459 +When he bestrides the lazy-pacing clouds\n\
   1.460 +And sails upon the bosom of the air.";
   1.461 +
   1.462 +var password = "O Romeo, Romeo! wherefore art thou Romeo?";
   1.463 +
   1.464 +var cipherText = AESEncryptCtr(plainText, password, 256);
   1.465 +var decryptedText = AESDecryptCtr(cipherText, password, 256);
   1.466 +
   1.467 +
   1.468 +var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
   1.469 +
   1.470 +document.getElementById("console").innerHTML = _sunSpiderInterval;
   1.471 +</script>
   1.472 +
   1.473 +
   1.474 +</body>
   1.475 +</html>

mercurial