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

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:ac2a09dae4a0
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6 <title>One-Time Pad Generator</title>
7 <meta name="description" content="JavaScript One-Time Pad Generator" />
8 <meta name="author" content="John Walker" />
9 <meta name="keywords" content="one, time, pad, generator, onetime, cryptography, JavaScript" />
10 <style type="text/css">
11 a:link, a:visited {
12 background-color: inherit;
13 color: rgb(0%, 0%, 80%);
14 text-decoration: none;
15 }
16
17 a:hover {
18 background-color: rgb(30%, 30%, 100%);
19 color: rgb(100%, 100%, 100%);
20 }
21
22 a:active {
23 color: rgb(100%, 0%, 0%);
24 background-color: rgb(30%, 30%, 100%);
25 }
26
27 a.i:link, a.i:visited, a.i:hover {
28 background-color: inherit;
29 color: inherit;
30 text-decoration: none;
31 }
32
33 body {
34 margin-left: 15%;
35 margin-right: 10%;
36 background-color: #FFFFFF;
37 color: #000000;
38 }
39
40 body.jsgen {
41 margin-left: 5%;
42 margin-right: 5%;
43 }
44
45 dt {
46 margin-top: 0.5em;
47 }
48
49 img.button {
50 border: 0px;
51 vertical-align: middle;
52 }
53
54 img.keyicon {
55 vertical-align: bottom;
56 }
57
58 p, dd, li {
59 text-align: justify;
60 }
61
62 p.centre {
63 text-align: center;
64 }
65
66 table.r {
67 float: right;
68 }
69
70 table.c {
71 background-color: #E0E0E0;
72 color: #000000;
73 margin-left: auto;
74 margin-right: auto;
75 }
76
77 td.c {
78 text-align: center;
79 }
80
81 textarea {
82 background-color: #FFFFD0;
83 color: #000000;
84 }
85 </style>
86 <script type="text/javascript">
87 //<![CDATA[
88
89 loadTime = (new Date()).getTime();
90
91 /*
92
93 L'Ecuyer's two-sequence generator with a Bays-Durham shuffle
94 on the back-end. Schrage's algorithm is used to perform
95 64-bit modular arithmetic within the 32-bit constraints of
96 JavaScript.
97
98 Bays, C. and S. D. Durham. ACM Trans. Math. Software: 2 (1976)
99 59-64.
100
101 L'Ecuyer, P. Communications of the ACM: 31 (1968) 742-774.
102
103 Schrage, L. ACM Trans. Math. Software: 5 (1979) 132-138.
104
105 */
106
107 function uGen(old, a, q, r, m) { // Schrage's modular multiplication algorithm
108 var t;
109
110 t = Math.floor(old / q);
111 t = a * (old - (t * q)) - (t * r);
112 return Math.round((t < 0) ? (t + m) : t);
113 }
114
115 function LEnext() { // Return next raw value
116 var i;
117
118 this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
119 this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
120
121 /* Extract shuffle table index from most significant part
122 of the previous result. */
123
124 i = Math.floor(this.state / 67108862);
125
126 // New state is sum of generators modulo one of their moduli
127
128 this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
129
130 // Replace value in shuffle table with generator 1 result
131
132 this.shuffle[i] = this.gen1;
133
134 return this.state;
135 }
136
137 // Return next random integer between 0 and n inclusive
138
139 function LEnint(n) {
140 return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
141 }
142
143 // Constructor. Called with seed value
144
145 function LEcuyer(s) {
146 var i;
147
148 this.shuffle = new Array(32);
149 this.gen1 = this.gen2 = (s & 0x7FFFFFFF);
150 for (i = 0; i < 19; i++) {
151 this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
152 }
153
154 // Fill the shuffle table with values
155
156 for (i = 0; i < 32; i++) {
157 this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
158 this.shuffle[31 - i] = this.gen1;
159 }
160 this.state = this.shuffle[0];
161 this.next = LEnext;
162 this.nextInt = LEnint;
163 }
164
165 function sepchar() {
166 if (rsep) {
167 var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
168 return seps.charAt(sepran.nextInt(seps.length - 1));
169 }
170 return "-";
171 }
172
173 /*
174 * md5.jvs 1.0b 27/06/96
175 *
176 * Javascript implementation of the RSA Data Security, Inc. MD5
177 * Message-Digest Algorithm.
178 *
179 * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
180 *
181 * Permission to use, copy, modify, and distribute this software
182 * and its documentation for any purposes and without
183 * fee is hereby granted provided that this copyright notice
184 * appears in all copies.
185 *
186 * Of course, this soft is provided "as is" without express or implied
187 * warranty of any kind.
188
189 This version contains some trivial reformatting modifications
190 by John Walker.
191
192 */
193
194 function array(n) {
195 for (i = 0; i < n; i++) {
196 this[i] = 0;
197 }
198 this.length = n;
199 }
200
201 /* Some basic logical functions had to be rewritten because of a bug in
202 * Javascript.. Just try to compute 0xffffffff >> 4 with it..
203 * Of course, these functions are slower than the original would be, but
204 * at least, they work!
205 */
206
207 function integer(n) {
208 return n % (0xffffffff + 1);
209 }
210
211 function shr(a, b) {
212 a = integer(a);
213 b = integer(b);
214 if (a - 0x80000000 >= 0) {
215 a = a % 0x80000000;
216 a >>= b;
217 a += 0x40000000 >> (b - 1);
218 } else {
219 a >>= b;
220 }
221 return a;
222 }
223
224 function shl1(a) {
225 a = a % 0x80000000;
226 if (a & 0x40000000 == 0x40000000) {
227 a -= 0x40000000;
228 a *= 2;
229 a += 0x80000000;
230 } else {
231 a *= 2;
232 }
233 return a;
234 }
235
236 function shl(a, b) {
237 a = integer(a);
238 b = integer(b);
239 for (var i = 0; i < b; i++) {
240 a = shl1(a);
241 }
242 return a;
243 }
244
245 function and(a, b) {
246 a = integer(a);
247 b = integer(b);
248 var t1 = a - 0x80000000;
249 var t2 = b - 0x80000000;
250 if (t1 >= 0) {
251 if (t2 >= 0) {
252 return ((t1 & t2) + 0x80000000);
253 } else {
254 return (t1 & b);
255 }
256 } else {
257 if (t2 >= 0) {
258 return (a & t2);
259 } else {
260 return (a & b);
261 }
262 }
263 }
264
265 function or(a, b) {
266 a = integer(a);
267 b = integer(b);
268 var t1 = a - 0x80000000;
269 var t2 = b - 0x80000000;
270 if (t1 >= 0) {
271 if (t2 >= 0) {
272 return ((t1 | t2) + 0x80000000);
273 } else {
274 return ((t1 | b) + 0x80000000);
275 }
276 } else {
277 if (t2 >= 0) {
278 return ((a | t2) + 0x80000000);
279 } else {
280 return (a | b);
281 }
282 }
283 }
284
285 function xor(a, b) {
286 a = integer(a);
287 b = integer(b);
288 var t1 = a - 0x80000000;
289 var t2 = b - 0x80000000;
290 if (t1 >= 0) {
291 if (t2 >= 0) {
292 return (t1 ^ t2);
293 } else {
294 return ((t1 ^ b) + 0x80000000);
295 }
296 } else {
297 if (t2 >= 0) {
298 return ((a ^ t2) + 0x80000000);
299 } else {
300 return (a ^ b);
301 }
302 }
303 }
304
305 function not(a) {
306 a = integer(a);
307 return 0xffffffff - a;
308 }
309
310 /* Here begin the real algorithm */
311
312 var state = new array(4);
313 var count = new array(2);
314 count[0] = 0;
315 count[1] = 0;
316 var buffer = new array(64);
317 var transformBuffer = new array(16);
318 var digestBits = new array(16);
319
320 var S11 = 7;
321 var S12 = 12;
322 var S13 = 17;
323 var S14 = 22;
324 var S21 = 5;
325 var S22 = 9;
326 var S23 = 14;
327 var S24 = 20;
328 var S31 = 4;
329 var S32 = 11;
330 var S33 = 16;
331 var S34 = 23;
332 var S41 = 6;
333 var S42 = 10;
334 var S43 = 15;
335 var S44 = 21;
336
337 function F(x, y, z) {
338 return or(and(x, y), and(not(x), z));
339 }
340
341 function G(x, y, z) {
342 return or(and(x, z), and(y, not(z)));
343 }
344
345 function H(x, y, z) {
346 return xor(xor(x, y), z);
347 }
348
349 function I(x, y, z) {
350 return xor(y ,or(x , not(z)));
351 }
352
353 function rotateLeft(a, n) {
354 return or(shl(a, n), (shr(a, (32 - n))));
355 }
356
357 function FF(a, b, c, d, x, s, ac) {
358 a = a + F(b, c, d) + x + ac;
359 a = rotateLeft(a, s);
360 a = a + b;
361 return a;
362 }
363
364 function GG(a, b, c, d, x, s, ac) {
365 a = a + G(b, c, d) + x + ac;
366 a = rotateLeft(a, s);
367 a = a + b;
368 return a;
369 }
370
371 function HH(a, b, c, d, x, s, ac) {
372 a = a + H(b, c, d) + x + ac;
373 a = rotateLeft(a, s);
374 a = a + b;
375 return a;
376 }
377
378 function II(a, b, c, d, x, s, ac) {
379 a = a + I(b, c, d) + x + ac;
380 a = rotateLeft(a, s);
381 a = a + b;
382 return a;
383 }
384
385 function transform(buf, offset) {
386 var a = 0, b = 0, c = 0, d = 0;
387 var x = transformBuffer;
388
389 a = state[0];
390 b = state[1];
391 c = state[2];
392 d = state[3];
393
394 for (i = 0; i < 16; i++) {
395 x[i] = and(buf[i * 4 + offset], 0xFF);
396 for (j = 1; j < 4; j++) {
397 x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
398 }
399 }
400
401 /* Round 1 */
402 a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
403 d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
404 c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
405 b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
406 a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
407 d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
408 c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
409 b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
410 a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
411 d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
412 c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
413 b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
414 a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
415 d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
416 c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
417 b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
418
419 /* Round 2 */
420 a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
421 d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
422 c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
423 b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
424 a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
425 d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */
426 c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
427 b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
428 a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
429 d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
430 c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
431 b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
432 a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
433 d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
434 c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
435 b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
436
437 /* Round 3 */
438 a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
439 d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
440 c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
441 b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
442 a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
443 d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
444 c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
445 b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
446 a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
447 d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
448 c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
449 b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
450 a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
451 d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
452 c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
453 b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
454
455 /* Round 4 */
456 a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
457 d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
458 c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
459 b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
460 a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
461 d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
462 c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
463 b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
464 a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
465 d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
466 c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
467 b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
468 a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
469 d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
470 c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
471 b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
472
473 state[0] += a;
474 state[1] += b;
475 state[2] += c;
476 state[3] += d;
477
478 }
479
480 function init() {
481 count[0] = count[1] = 0;
482 state[0] = 0x67452301;
483 state[1] = 0xefcdab89;
484 state[2] = 0x98badcfe;
485 state[3] = 0x10325476;
486 for (i = 0; i < digestBits.length; i++) {
487 digestBits[i] = 0;
488 }
489 }
490
491 function update(b) {
492 var index, i;
493
494 index = and(shr(count[0],3) , 0x3F);
495 if (count[0] < 0xFFFFFFFF - 7) {
496 count[0] += 8;
497 } else {
498 count[1]++;
499 count[0] -= 0xFFFFFFFF + 1;
500 count[0] += 8;
501 }
502 buffer[index] = and(b, 0xff);
503 if (index >= 63) {
504 transform(buffer, 0);
505 }
506 }
507
508 function finish() {
509 var bits = new array(8);
510 var padding;
511 var i = 0, index = 0, padLen = 0;
512
513 for (i = 0; i < 4; i++) {
514 bits[i] = and(shr(count[0], (i * 8)), 0xFF);
515 }
516 for (i = 0; i < 4; i++) {
517 bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
518 }
519 index = and(shr(count[0], 3), 0x3F);
520 padLen = (index < 56) ? (56 - index) : (120 - index);
521 padding = new array(64);
522 padding[0] = 0x80;
523 for (i = 0; i < padLen; i++) {
524 update(padding[i]);
525 }
526 for (i = 0; i < 8; i++) {
527 update(bits[i]);
528 }
529
530 for (i = 0; i < 4; i++) {
531 for (j = 0; j < 4; j++) {
532 digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
533 }
534 }
535 }
536
537 /* End of the MD5 algorithm */
538
539 function gen() {
540 window.status = "Generating...";
541 document.getElementById('onetime').pad.value = "";
542
543 lower = document.getElementById('onetime').textcase.selectedIndex == 0;
544 upper = document.getElementById('onetime').textcase.selectedIndex == 1;
545 mixed = document.getElementById('onetime').textcase.selectedIndex == 2;
546 rsep = document.getElementById('onetime').rsep.checked;
547 if (!(numeric = document.getElementById('onetime').keytype[0].checked)) {
548 english = document.getElementById('onetime').keytype[1].checked;
549 gibberish = document.getElementById('onetime').keytype[3].checked;
550 }
551 clockseed = document.getElementById('onetime').seedy[0].checked
552 makesig = document.getElementById('onetime').dosig.checked;
553 npass = document.getElementById('onetime').nkeys.value;
554 pw_length = Math.round(document.getElementById('onetime').klength.value);
555 sep = document.getElementById('onetime').sep.value;
556 linelen = document.getElementById('onetime').linelen.value;
557 // 01234567890123456789012345678901
558 charcodes = " " +
559 "!\"#$%&'()*+,-./0123456789:;<=>?" +
560 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
561 "`abcdefghijklmnopqrstuvwxyz{|}~";
562
563 if (clockseed) {
564 var n, j, ran0;
565
566 /* Obtain seed from the clock. To reduce the likelihood
567 of the seed being guessed, we create the seed by combining
568 the time of the request with the time the page was loaded,
569 then use that composite value to seed an auxiliary generator
570 which is cycled between one and 32 times based on the time
571 derived initial seed, with the output of the generator fed
572 back into the seed we use to generate the pad. */
573
574 seed = Math.round((new Date()).getTime() % Math.pow(2, 31));
575 ran0 = new LEcuyer((seed ^ Math.round(loadTime % Math.pow(2, 31))) & 0x7FFFFFFF);
576 for (j = 0; j < (5 + ((seed >> 3) & 0xF)); j++) {
577 n = ran0.nextInt(31);
578 }
579 while (n-- >= 0) {
580 seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next();
581 }
582 seed &= 0x7FFFFFFF;
583 document.getElementById('onetime').seeder.value = seed;
584 } else {
585 var useed, seedNum;
586
587 /* Obtain seed from user specification. If the seed is a
588 decimal number, use it as-is. If it contains any
589 non-numeric characters, construct a hash code and
590 use that as the seed. */
591
592 useed = document.getElementById('onetime').seeder.value;
593 seedNum = true;
594 for (i = 0; i < useed.length; i++) {
595 if ("0123456789".indexOf(useed.charAt(i)) == -1) {
596 seedNum = false;
597 break;
598 }
599 }
600 if (seedNum) {
601 seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31));
602 document.getElementById('onetime').seeder.value = seed;
603 } else {
604 var s, t, iso, hex;
605
606 iso = "";
607 hex = "0123456789ABCDEF";
608 for (i = 32; i < 256; i++) {
609 if (i < 127 || i >= 160) {
610 // Why not "s = i.toString(16);"? Doesn't work in Netscape 3.0
611 iso += "%" + hex.charAt(i >> 4) + hex.charAt(i & 0xF);
612 }
613 }
614 iso = unescape(iso);
615 s = 0;
616 for (i = 0; i < useed.length; i++) {
617 t = iso.indexOf(useed.charAt(i));
618 if (t < 0) {
619 t = 17;
620 }
621 s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t);
622 }
623 seed = s;
624 }
625 }
626 ran1 = new LEcuyer(seed);
627 ran2 = new LEcuyer(seed);
628 if (rsep) {
629 /* Use a separate random generator for separators
630 so that results are the same for a given seed
631 for both choices of separators. */
632 sepran = new LEcuyer(seed);
633 }
634
635 ndig = 1;
636 j = 10;
637 while (npass >= j) {
638 ndig++;
639 j *= 10;
640 }
641 pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0);
642 pw_item += ndig + 5;
643 j = pw_item * 3;
644 if (j < 132) {
645 j = 132;
646 }
647 npline = Math.floor(linelen / pw_item);
648 if (npline < 1) {
649 npline = 0;
650 }
651 v = "";
652 md5v = "";
653 lineno = 0;
654 if (!numeric) {
655 letters = "abcdefghijklmnopqrstuvwxyz";
656 if (upper) {
657 letters = letters.toUpperCase();
658 }
659 if (english) {
660
661 // Frequency of English digraphs (from D. Edwards 1/27/66)
662
663 frequency = new Array(
664 new Array(4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62,
665 23, 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1,
666 9, 1), /* aa - az */
667
668 new Array(13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0,
669 11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0), /* ba - bz */
670
671 new Array(32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1,
672 0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0), /* ca - cz */
673
674 new Array(40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15,
675 6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0), /* da - dz */
676
677 new Array(84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4,
678 55, 54, 146, 35, 37, 6, 191, 149, 65, 9, 26,
679 21, 12, 5, 0), /* ea - ez */
680
681 new Array(19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1,
682 0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0), /* fa - fz */
683
684 new Array(20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1,
685 4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0), /* ga - gz */
686
687 new Array(101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3,
688 2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0), /* ha - hz */
689
690 new Array(40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38,
691 25, 202, 56, 12, 1, 46, 79, 117, 1, 22, 0,
692 4, 0, 3), /* ia - iz */
693
694 new Array(3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4,
695 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0), /* ja - jz */
696
697 new Array(1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2,
698 0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0), /* ka - kz */
699
700 new Array(44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2,
701 2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0), /* la - lz */
702
703 new Array(52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7,
704 1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0), /* ma - mz */
705
706 new Array(42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6,
707 6, 9, 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0,
708 12, 0), /* na - nz */
709
710 new Array(7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19,
711 41, 134, 13, 23, 0, 91, 23, 42, 55, 16, 28,
712 0, 4, 1), /* oa - oz */
713
714 new Array(19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0,
715 27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0), /* pa - pz */
716
717 new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
718 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0), /* qa - qz */
719
720 new Array(83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5,
721 26, 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0,
722 28, 0), /* ra - rz */
723
724 new Array(65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7,
725 11, 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0,
726 4, 0), /* sa - sz */
727
728 new Array(57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14,
729 10, 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0,
730 24, 0), /* ta - tz */
731
732 new Array(11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31,
733 1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0), /* ua - uz */
734
735 new Array(7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0,
736 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0), /* va - vz */
737
738 new Array(36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1,
739 8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0), /* wa - wz */
740
741 new Array(1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1,
742 5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0), /* xa - xz */
743
744 new Array(14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7,
745 5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0), /* ya - yz */
746
747 new Array(1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) /* za - zz */ );
749
750 // This MUST be equal to the sum of the equivalent rows above.
751
752 row_sums = new Array(
753 796, 160, 284, 401, 1276, 262, 199, 539, 777,
754 16, 39, 351, 243, 751, 662, 181, 17, 683,
755 662, 968, 248, 115, 180, 17, 162, 5
756 );
757
758 // Frequencies of starting characters.
759
760 start_freq = new Array(
761 1299, 425, 725, 271, 375, 470, 93, 223, 1009,
762 24, 20, 355, 379, 319, 823, 618, 21, 317,
763 962, 1991, 271, 104, 516, 6, 16, 14
764 );
765
766 // This MUST be equal to the sum of all elements in the above array.
767
768 total_sum = 11646;
769 }
770 if (gibberish) {
771 gibber = "abcdefghijklmnopqrstuvwxyz" +
772 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
773 "0123456789" +
774 "!#$%&()*+,-./:;<=>?@[]^_{|}~";
775 if (upper) {
776 /* Convert to upper case, leaving two copies of the
777 alphabet for two reasons: first, to favour letters
778 over gnarl, and second, to change only the letter case
779 when the mode is selected. */
780 gibber = gibber.toUpperCase();
781 } else if (lower) {
782 gibber = gibber.toLowerCase();
783 }
784 }
785 }
786 for (line = 1; line <= npass; line++) {
787 password = "";
788 if (numeric) {
789 for (nchars = 0; nchars < pw_length; nchars++) {
790 if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
791 password += sepchar();
792 }
793 password += ran1.nextInt(9);
794 }
795 } else if (!english) {
796 for (nchars = 0; nchars < pw_length; nchars++) {
797 if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
798 password += sepchar();
799 }
800 if (gibberish) {
801 password += gibber.charAt(ran1.nextInt(gibber.length - 1));
802 } else {
803 password += letters.charAt(ran1.nextInt(25));
804 }
805 }
806 } else {
807 position = ran1.nextInt(total_sum - 1);
808 for (row_position = 0, j = 0; position >= row_position;
809 row_position += start_freq[j], j++) {
810 continue;
811 }
812
813 password = letters.charAt(i = j - 1);
814 nch = 1;
815 for (nchars = pw_length - 1; nchars; --nchars) {
816
817 // Now find random position within the row.
818
819 position = ran1.nextInt(row_sums[i] - 1);
820 for (row_position = 0, j = 0;
821 position >= row_position;
822 row_position += frequency[i][j], j++) {
823 }
824
825 if ((sep > 0) && ((nch % sep) == 0)) {
826 password += sepchar();
827 }
828 nch++;
829 password += letters.charAt(i = j - 1);
830 }
831 }
832
833 if ((!numeric) && (!gibberish) && mixed) {
834 var pwm = '';
835 var j;
836 for (j = 0; j < password.length; j++) {
837 pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase());
838 }
839 password = pwm;
840 }
841
842 /* If requested, calculate the MD5 signature for this key and
843 and save for later appending to the results. */
844
845 if (makesig) {
846 var n, m, hex = "0123456789ABCDEF";
847
848 init();
849 for (m = 0; m < password.length; m++) {
850 update(32 + charcodes.indexOf(password.charAt(m)));
851 }
852 finish();
853
854 for (n = 0; n < 16; n++) {
855 md5v += hex.charAt(digestBits[n] >> 4);
856 md5v += hex.charAt(digestBits[n] & 0xF);
857 }
858 md5v += "\n";
859 }
860
861 aline = "" + line;
862 while (aline.length < ndig) {
863 aline = " " + aline;
864 }
865 v += aline + ") " + password;
866
867 if ((++lineno) >= npline) {
868 v += "\n";
869 lineno = 0;
870 } else {
871 v += " ";
872 }
873 }
874
875 if (makesig) {
876 v += "\n---------- MD5 Signatures ----------\n" + md5v;
877 }
878
879 document.getElementById('onetime').pad.value = v;
880 window.status = "Done.";
881 }
882
883 function loadHandler() {
884 for (var i = 0; i < 25; i++) {
885 gen();
886 }
887 };
888
889 //]]>
890 </script>
891
892 </head>
893
894 <body class="jsgen" onload="loadHandler();">
895
896 <h1><img src="key.gif" class="keyicon" alt=""
897 width="40" height="40" /> &nbsp; One-Time Pad Generator</h1>
898
899 <p>
900 This page, which requires that your browser support JavaScript
901 (see <a href="#why"><cite>Why JavaScript</cite></a> below),
902 generates one-time pads or password lists in a variety of
903 forms. It is based a high-quality pseudorandom sequence
904 generator, which can be seeded either from the current date
905 and time, or from a seed you provide. Fill in the form below
906 to select the format of the pad and press &ldquo;Generate&rdquo; to
907 create the pad in the text box. You can then copy and paste
908 the generated pad into another window to use as you wish.
909 Each of the labels on the request form is linked to a description
910 of that parameter.
911 </p>
912
913 <form id="onetime" action="#" onsubmit="return false;">
914
915 <p class="centre">
916 <b>Output:</b>
917 <a href="#NumberOfKeys">Number of keys</a>: <input type="text" name="nkeys" value="20" size="4" maxlength="12" />
918 <a href="#LineLength">Line length</a>: <input type="text" name="linelen" value="48" size="3" maxlength="12" />
919 <br />
920 <b>Format:</b>
921 <a href="#KeyLength">Key length</a>: <input type="text" name="klength" value="8" size="3" maxlength="12" />
922 <a href="#GroupLength">Group length</a>: <input type="text" name="sep" value="4" size="2" maxlength="12" />
923
924 <br />
925 <b>Composition:</b>
926 <a href="#KeyText">Key text</a>: <input type="radio" name="keytype" /> Numeric
927 <input type="radio" name="keytype" /> Word-like
928 <input type="radio" name="keytype" checked="checked" /> Alphabetic
929 <input type="radio" name="keytype" /> Gibberish
930 <br />
931 <a href="#LetterCase">Letters:</a>
932 <select size="i" name="textcase">
933
934 <option value="1" selected="selected">Lower case</option>
935 <option value="2">Upper case</option>
936 <option value="3">Mixed case</option>
937 </select>
938
939 <input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a>
940 <input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a>
941
942 <br />
943 <b><a href="#Seed">Seed:</a></b>
944 <input type="radio" name="seedy" checked="checked" /> From clock
945 <input type="radio" name="seedy" /> User-defined:
946 <input type="text" name="seeder" value="" size="12" maxlength="128"
947 onchange="document.getElementById('onetime').seedy[1].checked=true;" />
948 <br />
949 <input type="button" value=" Generate " onclick="gen();" />
950 &nbsp;
951 <input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" />
952 &nbsp;
953 <input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br />
954 <textarea name="pad" rows="12" cols="72">
955
956 Uh, oh. It appears your browser either does not support
957 JavaScript or that JavaScript has been disabled. You'll
958 have to replace your browser with one supporting JavaScript
959 (or enable it, if that's the problem) before you can use
960 this page.
961 </textarea>
962 </p>
963
964 </form>
965
966 <script type="text/javascript">
967 //<![CDATA[
968 // Clear out "sorry, no JavaScript" message from text box.
969 document.getElementById('onetime').pad.value = "";
970 //]]>
971 </script>
972
973 <h2><a name="details">Details</a></h2>
974
975 <p>
976 Each of the fields in the one-time pad request form is described
977 below.
978 </p>
979
980 <h3><a name="output">Output</a></h3>
981
982 <h4><a name="NumberOfKeys">Number of keys</a></h4>
983
984 <p>
985 Enter the number of keys you'd like to generate. If you generate
986 more than fit in the results text box, you can use the scroll
987 bar to view the additional lines.
988 </p>
989
990 <h4><a name="LineLength">Line length</a></h4>
991
992 <p>
993 Lines in the output will be limited to the given length (or contain
994 only one key if the line length is less than required for a single
995 key). If the line length is greater than the width of the results
996 box, you can use the horizontal scroll bar to view the rest of the
997 line. Enter <tt>0</tt> to force one key per line; this is handy
998 when you're preparing a list of keys to be read by a computer program.
999 </p>
1000
1001 <h3><a name="format">Format</a></h3>
1002
1003 <h4><a name="KeyLength">Key length</a></h4>
1004
1005 <p>
1006 Each key will contain this number of characters, not counting
1007 separators between groups.
1008 </p>
1009
1010 <h4><a name="GroupLength">Group length</a></h4>
1011
1012 <p>
1013 If a nonzero value is entered in this field, the key will be broken
1014 into groups of the given number of characters by separators. Humans
1015 find it easier to read and remember sequences of characters when
1016 divided into groups of five or fewer characters.
1017 </p>
1018
1019 <h3><a name="composition">Composition</a></h3>
1020
1021 <h4><a name="KeyText">Key text</a></h4>
1022
1023 <p>
1024 This set of radio buttons lets you select the character set used in
1025 the keys. The alternatives are listed in order of
1026 increasing security.
1027 </p>
1028
1029 <blockquote>
1030 <dl>
1031 <dt><b>Numeric</b></dt>
1032 <dd>Keys contain only the decimal digits &ldquo;0&rdquo; through &ldquo;9&rdquo;.
1033 <em>Least secure.</em></dd>
1034
1035 <dt><b>Word-like</b></dt>
1036 <dd>Keys are composed of alphabetic characters which obey the
1037 digraph statistics of English text. Such keys contain
1038 sequences of vowels and consonants familiar to speakers
1039 of Western languages, and are therefore usually easier to
1040 memorise but, for a given key length, are less secure than
1041 purely random letters.</dd>
1042
1043 <dt><b>Alphabetic</b></dt>
1044 <dd>Keys consist of letters of the alphabet chosen at random.
1045 Each character has an equal probability of being one of
1046 the 26 letters.</dd>
1047
1048 <dt><b>Gibberish</b></dt>
1049 <dd>Keys use most of the printable ASCII character set, excluding
1050 only characters frequently used for quoting purposes. This
1051 option provides the greatest security for a given key length,
1052 but most people find keys like this difficult to memorise or
1053 even transcribe from a printed pad. If a human is in the loop,
1054 it's often better to use a longer alphabetic or word-like key.
1055 <em>Most secure.</em></dd>
1056 </dl>
1057
1058 </blockquote>
1059
1060 <h4><a name="LetterCase">Letters</a></h4>
1061
1062 <p>
1063 The case of letters in keys generated with Word-like, Alphabetic, and
1064 Gibberish key text will be as chosen. Most people find it easier to
1065 read lower case letters than all capitals, but for some applications
1066 (for example, where keys must be scanned optically by hardware that
1067 only recognises capital letters), capitals are required. Selecting
1068 &ldquo;Mixed&nbsp;case&rdquo; creates keys with a mix of upper- and
1069 lower-case letters; such keys are more secure than those with uniform
1070 letter case, but do not pass the &ldquo;telephone test&rdquo;: you
1071 can't read them across a (hopefully secure) voice link without having
1072 to indicate whether each letter is or is not a capital.
1073 </p>
1074
1075 <h4><a name="RandomSep">Random separators</a></h4>
1076
1077 <p>
1078 When the <a href="#KeyLength">Key length</a> is longer than
1079 a nonzero <a href="#GroupLength">Group length</a> specification,
1080 the key is divided into sequences of the given group length
1081 by separator characters. By default, a hyphen, &ldquo;<tt>-</tt>&rdquo;, is used
1082 to separate groups. If you check this box, separators will be
1083 chosen at random among punctuation marks generally acceptable
1084 for applications such as passwords. If you're generating passwords
1085 for a computer system, random separators dramatically increase
1086 the difficulty of guessing passwords by exhaustive search.
1087 </p>
1088
1089 <h4><a name="Signatures">Include signatures</a></h4>
1090
1091 <p>
1092
1093 When this box is checked, at the end of the list of keys, preceded by
1094 a line beginning with ten dashes &ldquo;<tt>-</tt>&rdquo;, the 128 bit MD5 signature of
1095 each key is given, one per line, with signatures expressed as 32
1096 hexadecimal digits. Key signatures can be used to increase security
1097 when keys are used to control access to computer systems or databases.
1098 Instead of storing a copy of the keys, the computer stores their
1099 signatures. When the user enters a key, its signature is computed
1100 with the same MD5 algorithm used to generate it initially, and the key
1101 is accepted only if the signature matches. Since discovering
1102 a key which will generate a given signature is believed to be
1103 computationally prohibitive, even if the list of signatures stored on
1104 the computer is compromised, that information will not permit an
1105 intruder to deduce a valid key.
1106 </p>
1107
1108 <p>
1109 Signature calculation is a computationally intense process for which
1110 JavaScript is not ideally suited; be patient while signatures are
1111 generated, especially if your computer has modest
1112 processing speed.
1113 </p>
1114
1115 <p>
1116 For signature-based validation to be secure, it is essential
1117 the original keys be long enough to prohibit discovery of matching
1118 signatures by exhaustive search. Suppose, for example, one used
1119 four digit numeric keys, as used for Personal Identification
1120 Numbers (PINs) by many credit card systems. Since only 10,000
1121 different keys exist, one could simply compute the signatures of
1122 every possible key from 0000 through 9999, permitting an attacker who
1123 came into possession of the table of signatures to recover the
1124 keys by a simple lookup process. For maximum security, keys must
1125 contain at least as much information as the 128 bit signatures
1126 computed from them. This implies a minimum key length (not counting
1127 non-random separator characters) for the various key formats as
1128 follows:
1129 </p>
1130
1131 <table class="c" border="border" cellpadding="4">
1132 <tr><th>Key Composition</th> <th>Minimum Characters</th></tr>
1133
1134 <tr><td>Numeric</td> <td class="c">39</td></tr>
1135 <tr><td>Word-like</td> <td class="c">30</td></tr>
1136 <tr><td>Alphabetic</td> <td class="c">28</td></tr>
1137 <tr><td>Gibberish</td> <td class="c">20</td></tr>
1138 </table>
1139
1140 <p>
1141 It should be noted that for many practical applications there is no
1142 need for anything approaching 128-bit security. The guidelines above
1143 apply only in the case where maximum protection in the event of
1144 undetected compromise of key signatures occurs. In many
1145 cases, much shorter keys are acceptable, especially when it is assumed
1146 that a compromise of the system's password or signature database would
1147 be only part of a much more serious subversion of all resources
1148 on the system.
1149 </p>
1150
1151 <h3><a name="Seed">Seed</a></h3>
1152
1153 <p>
1154 The <em>seed</em> is the starting value which determines all
1155 subsequent values in the pseudorandom sequence used to generate
1156 the one-time pad. Given the seed, the pad can be reproduced. The
1157 seed is a 31-bit number which can be derived from the date and
1158 time at which the one-time pad was requested, or from a
1159 user-defined seed value. If the user-defined seed consists
1160 entirely of decimal digits, it is used directly as the seed,
1161 modulo 2<sup>31</sup>; if a string containing non-digit characters
1162 is entered, it is used to compute a <em>hash code</em> which is
1163 used to seed the generator.
1164
1165 </p>
1166
1167 <p>
1168 When the clock is used to create the seed, the seed value is entered
1169 in the User-defined box to allow you, by checking &ldquo;User-defined&rdquo;,
1170 to produce additional pads with the same seed.
1171 </p>
1172
1173 <h2><a name="why">Why JavaScript?</a></h2>
1174
1175 <p>
1176 At first glance, JavaScript may seem an odd choice for programming
1177 a page such as this. The one-time pad generator program is rather
1178 large and complicated, and downloading it to your browser takes longer
1179 than would be required for a Java applet or to transfer a
1180 one-time pad generated by a CGI program on the Web server. I chose
1181 JavaScript for two reasons: <em>security</em> and <em>transparency</em>.
1182
1183 </p>
1184
1185 <p>
1186 <b>Security.</b>
1187 The sole reason for the existence of one-time pads is to
1188 provide a source of information known only to people to whom
1189 they have been distributed in a secure manner. This means
1190 the generation process cannot involve any link whose security
1191 is suspect. If the pad were generated on a Web server and
1192 transmitted to you, it would have to pass over the
1193 Internet, where any intermediate site might make a copy
1194 of your pad before you even received it. Even if some
1195 mechanism such as encryption could absolutely prevent the
1196 pad's being intercepted, you'd still have no way to be sure
1197 the site generating the pad didn't keep a copy
1198 in a file, conveniently tagged with your Internet address.
1199 </p>
1200
1201 <p>
1202 In order to have any degree of security, it is essential
1203 that the pad be generated on <em>your</em> computer, without
1204 involving any transmission or interaction with other
1205 sites on the Internet. A Web browser with JavaScript makes
1206 this possible, since the generation program embedded in this
1207 page runs entirely on your own computer and does not
1208 transmit anything over the Internet. Its output appears
1209 only in the text box, allowing you to cut and paste it
1210 to another application. From there on, its security is
1211 up to you.
1212 </p>
1213
1214 <p>
1215 Security is never absolute. A one-time pad generated with
1216 this page might be compromised in a variety of ways, including
1217 the following:
1218
1219 </p>
1220
1221 <ul>
1222 <li> Your Web browser and/or JavaScript interpreter may
1223 contain bugs or deliberate security violations
1224 which report activity on your computer back to some
1225 other Internet site.</li>
1226
1227 <li> Some other applet running on another page of your
1228 browser, perhaps without your being aware of its
1229 existence, is spying on other windows.</li>
1230
1231 <li> Some other application running on your computer
1232 may have compromised your system's security and
1233 be snooping on your activity.</li>
1234
1235 <li> Your Web browser may be keeping a &ldquo;history log&rdquo;
1236
1237 or &ldquo;cache&rdquo; of data you generate. Somebody may
1238 come along later and recover a copy of the pad
1239 from that log.</li>
1240
1241 <li> The implementation of this page may contain a bug
1242 or deliberate error which makes its output
1243 predictable. This is why <a href="#trans"><cite>transparency</cite></a>,
1244 discussed below, is essential.</li>
1245
1246 <li> Your computer's security may have been compromised
1247 physically; when's the last time you checked that a
1248 bug that transmits your keystrokes and/or screen
1249 contents to that white van parked down the street
1250 wasn't lurking inside your computer cabinet?</li>
1251 </ul>
1252
1253 <p>
1254 One can whip oneself into a fine fever of paranoia worrying about
1255 things like this. One way to rule out the most probable risks
1256 is to download a copy of the generator page and run it
1257 from a &ldquo;<tt>file:</tt>&rdquo; URL on a computer which has no network
1258 connection whatsoever and is located in a secure location
1259 under your control. And look very carefully at any files
1260 created by your Web browser. You may find the most interesting
1261 things squirreled away there&hellip;.
1262 </p>
1263
1264 <p>
1265 <b><a name="trans">Transparency</a>.</b>
1266 Any security-related tool is only as good as its design
1267 and implementation. <em>Transparency</em> means that, in
1268 essence, all the moving parts are visible so you can judge
1269 for yourself whether the tool merits your confidence. In
1270 the case of a program, this means that source code must
1271 be available, and that you can verify that the program
1272 you're running corresponds to the source code provided.
1273
1274 </p>
1275
1276 <p>
1277 The very nature of JavaScript achieves this transparency.
1278 The program is embedded into this actual Web page; to
1279 examine it you need only use your browser's &ldquo;View Source&rdquo;
1280 facility, or save the page into a file on your computer
1281 and read it with a text editor. JavaScript's being
1282 an interpreted language eliminates the risk of your running
1283 a program different from the purported source code: with
1284 an interpreted language what you read is what you run.
1285 </p>
1286
1287 <p>
1288 Transparency is important even if you don't know enough about
1289 programming or security to determine whether the program
1290 contains any flaws. The very fact that it can be examined
1291 by anybody allows those with the required expertise to pass
1292 judgment, and you can form your own conclusions based on
1293 their analysis.
1294 </p>
1295
1296 <h2>Credits</h2>
1297
1298 <p>
1299
1300 The pseudorandom sequence generator is based on L'Ecuyer's
1301 two-sequence generator as described in
1302 <cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742.
1303 A Bays-Durham shuffle is used to guard against regularities
1304 lurking in L'Ecuyer's algorithm; see
1305 <cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976)
1306 pages 59&ndash;64 for details.
1307 </p>
1308
1309 <p>
1310 The JavaScript implementation of the
1311 <a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a>
1312 was developed by Henri Torgemane; please view the source code of this
1313 page to examine the code, including the copyright notice and
1314 conditions of use. The MD5 algorithm was developed by Ron Rivest.
1315 </p>
1316
1317 <p />
1318
1319 <hr />
1320
1321 <p />
1322
1323 <table class="r">
1324 <tr><td align="center">
1325 <a class="i" href="http://validator.w3.org/check?uri=referer"><img
1326 class="button"
1327 src="valid-xhtml10.png"
1328 alt="Valid XHTML 1.0" height="31" width="88" /></a>
1329 </td></tr>
1330 </table>
1331
1332 <address>
1333 by <a href="/">John Walker</a><br />
1334 May 26, 1997<br />
1335
1336 Updated: November 2006
1337 </address>
1338
1339 <p class="centre">
1340 <em>This document is in the public domain.</em>
1341 </p>
1342 </body>
1343 </html>
1344

mercurial