js/src/devtools/jint/sunspider/crypto-aes.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
     3 /*
     4  * AES Cipher function: encrypt 'input' with Rijndael algorithm
     5  *
     6  *   takes   byte-array 'input' (16 bytes)
     7  *           2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
     8  *
     9  *   applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
    10  *
    11  *   returns byte-array encrypted value (16 bytes)
    12  */
    13 function Cipher(input, w) {    // main Cipher function [§5.1]
    14   var Nb = 4;               // block size (in words): no of columns in state (fixed at 4 for AES)
    15   var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
    17   var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [§3.4]
    18   /* BEGIN LOOP */
    19   for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
    20   /* END LOOP */
    22   state = AddRoundKey(state, w, 0, Nb);
    24   /* BEGIN LOOP */
    25   for (var round=1; round<Nr; round++) {
    26     state = SubBytes(state, Nb);
    27     state = ShiftRows(state, Nb);
    28     state = MixColumns(state, Nb);
    29     state = AddRoundKey(state, w, round, Nb);
    30   }
    31   /* END LOOP */
    33   state = SubBytes(state, Nb);
    34   state = ShiftRows(state, Nb);
    35   state = AddRoundKey(state, w, Nr, Nb);
    37   var output = new Array(4*Nb);  // convert state to 1-d array before returning [§3.4]
    38   /* BEGIN LOOP */
    39   for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
    40   /* END LOOP */
    41   return output;
    42 }
    45 function SubBytes(s, Nb) {    // apply SBox to state S [§5.1.1]
    46   /* BEGIN LOOP */
    47   for (var r=0; r<4; r++) {
    48     /* BEGIN LOOP */
    49     for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
    50     /* END LOOP */
    51   }
    52   /* END LOOP */
    53   return s;
    54 }
    57 function ShiftRows(s, Nb) {    // shift row r of state S left by r bytes [§5.1.2]
    58   var t = new Array(4);
    59   /* BEGIN LOOP */
    60   for (var r=1; r<4; r++) {
    61     /* BEGIN LOOP */
    62     for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];  // shift into temp copy
    63     /* END LOOP */
    64     /* BEGIN LOOP */
    65     for (var c=0; c<4; c++) s[r][c] = t[c];         // and copy back
    66     /* END LOOP */
    67   }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
    68   /* END LOOP */
    69   return s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf 
    70 }
    73 function MixColumns(s, Nb) {   // combine bytes of each col of state S [§5.1.3]
    74   /* BEGIN LOOP */
    75   for (var c=0; c<4; c++) {
    76     var a = new Array(4);  // 'a' is a copy of the current column from 's'
    77     var b = new Array(4);  // 'b' is a•{02} in GF(2^8)
    78     /* BEGIN LOOP */
    79     for (var i=0; i<4; i++) {
    80       a[i] = s[i][c];
    81       b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
    82     }
    83     /* END LOOP */
    84     // a[n] ^ b[n] is a•{03} in GF(2^8)
    85     s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
    86     s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
    87     s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
    88     s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
    89   }
    90   /* END LOOP */
    91   return s;
    92 }
    95 function AddRoundKey(state, w, rnd, Nb) {  // xor Round Key into state S [§5.1.4]
    96   /* BEGIN LOOP */
    97   for (var r=0; r<4; r++) {
    98     /* BEGIN LOOP */
    99     for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
   100     /* END LOOP */
   101   }
   102   /* END LOOP */
   103   return state;
   104 }
   107 function KeyExpansion(key) {  // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
   108   var Nb = 4;            // block size (in words): no of columns in state (fixed at 4 for AES)
   109   var Nk = key.length/4  // key length (in words): 4/6/8 for 128/192/256-bit keys
   110   var Nr = Nk + 6;       // no of rounds: 10/12/14 for 128/192/256-bit keys
   112   var w = new Array(Nb*(Nr+1));
   113   var temp = new Array(4);
   115   /* BEGIN LOOP */
   116   for (var i=0; i<Nk; i++) {
   117     var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
   118     w[i] = r;
   119   }
   120   /* END LOOP */
   122   /* BEGIN LOOP */
   123   for (var i=Nk; i<(Nb*(Nr+1)); i++) {
   124     w[i] = new Array(4);
   125     /* BEGIN LOOP */
   126     for (var t=0; t<4; t++) temp[t] = w[i-1][t];
   127     /* END LOOP */
   128     if (i % Nk == 0) {
   129       temp = SubWord(RotWord(temp));
   130       /* BEGIN LOOP */
   131       for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
   132       /* END LOOP */
   133     } else if (Nk > 6 && i%Nk == 4) {
   134       temp = SubWord(temp);
   135     }
   136     /* BEGIN LOOP */
   137     for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
   138     /* END LOOP */
   139   }
   140   /* END LOOP */
   142   return w;
   143 }
   145 function SubWord(w) {    // apply SBox to 4-byte word w
   146   /* BEGIN LOOP */
   147   for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
   148   /* END LOOP */
   149   return w;
   150 }
   152 function RotWord(w) {    // rotate 4-byte word w left by one byte
   153   w[4] = w[0];
   154   /* BEGIN LOOP */
   155   for (var i=0; i<4; i++) w[i] = w[i+1];
   156   /* END LOOP */
   157   return w;
   158 }
   161 // Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
   162 var Sbox =  [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
   163              0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
   164              0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
   165              0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
   166              0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
   167              0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
   168              0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
   169              0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
   170              0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
   171              0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
   172              0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
   173              0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
   174              0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
   175              0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
   176              0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
   177              0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
   179 // Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
   180 var Rcon = [ [0x00, 0x00, 0x00, 0x00],
   181              [0x01, 0x00, 0x00, 0x00],
   182              [0x02, 0x00, 0x00, 0x00],
   183              [0x04, 0x00, 0x00, 0x00],
   184              [0x08, 0x00, 0x00, 0x00],
   185              [0x10, 0x00, 0x00, 0x00],
   186              [0x20, 0x00, 0x00, 0x00],
   187              [0x40, 0x00, 0x00, 0x00],
   188              [0x80, 0x00, 0x00, 0x00],
   189              [0x1b, 0x00, 0x00, 0x00],
   190              [0x36, 0x00, 0x00, 0x00] ]; 
   193 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   195 /* 
   196  * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
   197  *                           - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
   198  *   for each block
   199  *   - outputblock = cipher(counter, key)
   200  *   - cipherblock = plaintext xor outputblock
   201  */
   202 function AESEncryptCtr(plaintext, password, nBits) {
   203   if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
   205   // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; 
   206   // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
   207   var nBytes = nBits/8;  // no bytes in key
   208   var pwBytes = new Array(nBytes);
   209   /* BEGIN LOOP */
   210   for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
   211   /* END LOOP */
   212   var key = Cipher(pwBytes, KeyExpansion(pwBytes));
   213   key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
   215   // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
   216   // block counter in 2nd 8 bytes
   217   var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   218   var counterBlock = new Array(blockSize);  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   219   var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970
   221   // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
   222   /* BEGIN LOOP */
   223   for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
   224   /* END LOOP */
   225   /* BEGIN LOOP */
   226   for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
   227   /* END LOOP */
   229   // generate key schedule - an expansion of the key into distinct Key Rounds for each round
   230   var keySchedule = KeyExpansion(key);
   232   var blockCount = Math.ceil(plaintext.length/blockSize);
   233   var ciphertext = new Array(blockCount);  // ciphertext as array of strings
   235   /* BEGIN LOOP */
   236   for (var b=0; b<blockCount; b++) {
   237     // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
   238     // again done in two stages for 32-bit ops
   239     /* BEGIN LOOP */
   240     for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
   241     /* END LOOP */
   242     /* BEGIN LOOP */
   243     for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
   244     /* END LOOP */
   246     var cipherCntr = Cipher(counterBlock, keySchedule);  // -- encrypt counter block --
   248     // calculate length of final block:
   249     var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
   251     var ct = '';
   252     /* BEGIN LOOP */
   253     for (var i=0; i<blockLength; i++) {  // -- xor plaintext with ciphered counter byte-by-byte --
   254       var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
   255       var cipherByte = plaintextByte ^ cipherCntr[i];
   256       ct += String.fromCharCode(cipherByte);
   257     }
   258     /* END LOOP */
   259     // ct is now ciphertext for this block
   261     ciphertext[b] = escCtrlChars(ct);  // escape troublesome characters in ciphertext
   262   }
   263   /* END LOOP */
   265   // convert the nonce to a string to go on the front of the ciphertext
   266   var ctrTxt = '';
   267   /* BEGIN LOOP */
   268   for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
   269   /* END LOOP */
   270   ctrTxt = escCtrlChars(ctrTxt);
   272   // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
   273   return ctrTxt + '-' + ciphertext.join('-');
   274 }
   277 /* 
   278  * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
   279  *
   280  *   for each block
   281  *   - outputblock = cipher(counter, key)
   282  *   - cipherblock = plaintext xor outputblock
   283  */
   284 function AESDecryptCtr(ciphertext, password, nBits) {
   285   if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
   287   var nBytes = nBits/8;  // no bytes in key
   288   var pwBytes = new Array(nBytes);
   289   /* BEGIN LOOP */
   290   for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
   291   /* END LOOP */
   292   var pwKeySchedule = KeyExpansion(pwBytes);
   293   var key = Cipher(pwBytes, pwKeySchedule);
   294   key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
   296   var keySchedule = KeyExpansion(key);
   298   ciphertext = ciphertext.split('-');  // split ciphertext into array of block-length strings 
   300   // recover nonce from 1st element of ciphertext
   301   var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   302   var counterBlock = new Array(blockSize);
   303   var ctrTxt = unescCtrlChars(ciphertext[0]);
   304   /* BEGIN LOOP */
   305   for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
   306   /* END LOOP */
   308   var plaintext = new Array(ciphertext.length-1);
   310   /* BEGIN LOOP */
   311   for (var b=1; b<ciphertext.length; b++) {
   312     // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
   313     /* BEGIN LOOP */
   314     for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
   315     /* END LOOP */
   316     /* BEGIN LOOP */
   317     for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
   318     /* END LOOP */
   320     var cipherCntr = Cipher(counterBlock, keySchedule);  // encrypt counter block
   322     ciphertext[b] = unescCtrlChars(ciphertext[b]);
   324     var pt = '';
   325     /* BEGIN LOOP */
   326     for (var i=0; i<ciphertext[b].length; i++) {
   327       // -- xor plaintext with ciphered counter byte-by-byte --
   328       var ciphertextByte = ciphertext[b].charCodeAt(i);
   329       var plaintextByte = ciphertextByte ^ cipherCntr[i];
   330       pt += String.fromCharCode(plaintextByte);
   331     }
   332     /* END LOOP */
   333     // pt is now plaintext for this block
   335     plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext
   336   }
   337   /* END LOOP */
   339   return plaintext.join('');
   340 }
   342 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   344 function escCtrlChars(str) {  // escape control chars which might cause problems handling ciphertext
   345   return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
   346 }  // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
   348 function unescCtrlChars(str) {  // unescape potentially problematic control characters
   349   return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
   350 }
   351 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   353 /*
   354  * if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead
   355  */
   356 var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
   358 function encodeBase64(str) {  // http://tools.ietf.org/html/rfc4648
   359    var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
   361    str = encodeUTF8(str);  // encode multi-byte chars into UTF-8 for byte-array
   363    /* BEGIN LOOP */
   364    do {  // pack three octets into four hexets
   365       o1 = str.charCodeAt(i++);
   366       o2 = str.charCodeAt(i++);
   367       o3 = str.charCodeAt(i++);
   369       bits = o1<<16 | o2<<8 | o3;
   371       h1 = bits>>18 & 0x3f;
   372       h2 = bits>>12 & 0x3f;
   373       h3 = bits>>6 & 0x3f;
   374       h4 = bits & 0x3f;
   376       // end of string? index to '=' in b64
   377       if (isNaN(o3)) h4 = 64;
   378       if (isNaN(o2)) h3 = 64;
   380       // use hexets to index into b64, and append result to encoded string
   381       enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
   382    } while (i < str.length);
   383    /* END LOOP */
   385    return enc;
   386 }
   388 function decodeBase64(str) {
   389    var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
   391    /* BEGIN LOOP */
   392    do {  // unpack four hexets into three octets using index points in b64
   393       h1 = b64.indexOf(str.charAt(i++));
   394       h2 = b64.indexOf(str.charAt(i++));
   395       h3 = b64.indexOf(str.charAt(i++));
   396       h4 = b64.indexOf(str.charAt(i++));
   398       bits = h1<<18 | h2<<12 | h3<<6 | h4;
   400       o1 = bits>>16 & 0xff;
   401       o2 = bits>>8 & 0xff;
   402       o3 = bits & 0xff;
   404       if (h3 == 64)      enc += String.fromCharCode(o1);
   405       else if (h4 == 64) enc += String.fromCharCode(o1, o2);
   406       else               enc += String.fromCharCode(o1, o2, o3);
   407    } while (i < str.length);
   408    /* END LOOP */
   410    return decodeUTF8(enc);  // decode UTF-8 byte-array back to Unicode
   411 }
   413 function encodeUTF8(str) {  // encode multi-byte string into utf-8 multiple single-byte characters 
   414   str = str.replace(
   415       /[\u0080-\u07ff]/g,  // U+0080 - U+07FF = 2-byte chars
   416       function(c) { 
   417         var cc = c.charCodeAt(0);
   418         return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
   419     );
   420   str = str.replace(
   421       /[\u0800-\uffff]/g,  // U+0800 - U+FFFF = 3-byte chars
   422       function(c) { 
   423         var cc = c.charCodeAt(0); 
   424         return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
   425     );
   426   return str;
   427 }
   429 function decodeUTF8(str) {  // decode utf-8 encoded string back into multi-byte characters
   430   str = str.replace(
   431       /[\u00c0-\u00df][\u0080-\u00bf]/g,                 // 2-byte chars
   432       function(c) { 
   433         var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
   434         return String.fromCharCode(cc); }
   435     );
   436   str = str.replace(
   437       /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,  // 3-byte chars
   438       function(c) { 
   439         var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f; 
   440         return String.fromCharCode(cc); }
   441     );
   442   return str;
   443 }
   446 function byteArrayToHexStr(b) {  // convert byte array to hex string for displaying test vectors
   447   var s = '';
   448   /* BEGIN LOOP */
   449   for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' ';
   450   /* END LOOP */
   451   return s;
   452 }
   454 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
   457 var plainText = "ROMEO: But, soft! what light through yonder window breaks?\n\
   458 It is the east, and Juliet is the sun.\n\
   459 Arise, fair sun, and kill the envious moon,\n\
   460 Who is already sick and pale with grief,\n\
   461 That thou her maid art far more fair than she:\n\
   462 Be not her maid, since she is envious;\n\
   463 Her vestal livery is but sick and green\n\
   464 And none but fools do wear it; cast it off.\n\
   465 It is my lady, O, it is my love!\n\
   466 O, that she knew she were!\n\
   467 She speaks yet she says nothing: what of that?\n\
   468 Her eye discourses; I will answer it.\n\
   469 I am too bold, 'tis not to me she speaks:\n\
   470 Two of the fairest stars in all the heaven,\n\
   471 Having some business, do entreat her eyes\n\
   472 To twinkle in their spheres till they return.\n\
   473 What if her eyes were there, they in her head?\n\
   474 The brightness of her cheek would shame those stars,\n\
   475 As daylight doth a lamp; her eyes in heaven\n\
   476 Would through the airy region stream so bright\n\
   477 That birds would sing and think it were not night.\n\
   478 See, how she leans her cheek upon her hand!\n\
   479 O, that I were a glove upon that hand,\n\
   480 That I might touch that cheek!\n\
   481 JULIET: Ay me!\n\
   482 ROMEO: She speaks:\n\
   483 O, speak again, bright angel! for thou art\n\
   484 As glorious to this night, being o'er my head\n\
   485 As is a winged messenger of heaven\n\
   486 Unto the white-upturned wondering eyes\n\
   487 Of mortals that fall back to gaze on him\n\
   488 When he bestrides the lazy-pacing clouds\n\
   489 And sails upon the bosom of the air.";
   491 var password = "O Romeo, Romeo! wherefore art thou Romeo?";
   493 var cipherText = AESEncryptCtr(plainText, password, 256);
   494 var decryptedText = AESDecryptCtr(cipherText, password, 256);

mercurial