Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: chrome/test/data/dromaeo/tests/sunspider-crypto-aes.html

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

Powered by Google App Engine
This is Rietveld 408576698