PageRenderTime 81ms CodeModel.GetById 15ms app.highlight 54ms RepoModel.GetById 1ms app.codeStats 1ms

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

http://github.com/zpao/v8monkey
HTML | 1344 lines | 1126 code | 218 blank | 0 comment | 0 complexity | 794946032aa42a6888e27f2385d2b67f MD5 | raw file
   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
 107function 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
 115function 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
 139function LEnint(n) {
 140    return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
 141}
 142
 143//  Constructor.  Called with seed value
 144
 145function 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
 165function 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
 194function 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
 207function integer(n) {
 208    return n % (0xffffffff + 1);
 209}
 210
 211function 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
 224function 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
 236function 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
 245function 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
 265function 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
 285function 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
 305function not(a) {
 306    a = integer(a);
 307    return 0xffffffff - a;
 308}
 309
 310/* Here begin the real algorithm */
 311
 312var state = new array(4); 
 313var count = new array(2);
 314    count[0] = 0;
 315    count[1] = 0;                     
 316var buffer = new array(64); 
 317var transformBuffer = new array(16); 
 318var digestBits = new array(16);
 319
 320var S11 = 7;
 321var S12 = 12;
 322var S13 = 17;
 323var S14 = 22;
 324var S21 = 5;
 325var S22 = 9;
 326var S23 = 14;
 327var S24 = 20;
 328var S31 = 4;
 329var S32 = 11;
 330var S33 = 16;
 331var S34 = 23;
 332var S41 = 6;
 333var S42 = 10;
 334var S43 = 15;
 335var S44 = 21;
 336
 337function F(x, y, z) {
 338    return or(and(x, y), and(not(x), z));
 339}
 340
 341function G(x, y, z) {
 342    return or(and(x, z), and(y, not(z)));
 343}
 344
 345function H(x, y, z) {
 346    return xor(xor(x, y), z);
 347}
 348
 349function I(x, y, z) {
 350    return xor(y ,or(x , not(z)));
 351}
 352
 353function rotateLeft(a, n) {
 354    return or(shl(a, n), (shr(a, (32 - n))));
 355}
 356
 357function 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
 364function 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
 371function 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
 378function 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
 385function 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
 480function 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
 491function 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
 508function 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
 539function 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
 883function 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>
 900This page, which requires that your browser support JavaScript
 901(see <a href="#why"><cite>Why JavaScript</cite></a> below),
 902generates one-time pads or password lists in a variety of
 903forms.  It is based a high-quality pseudorandom sequence
 904generator, which can be seeded either from the current date
 905and time, or from a seed you provide.  Fill in the form below
 906to select the format of the pad and press &ldquo;Generate&rdquo; to
 907create the pad in the text box.  You can then copy and paste
 908the generated pad into another window to use as you wish.
 909Each of the labels on the request form is linked to a description
 910of 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
 956Uh, oh.  It appears your browser either does not support
 957JavaScript or that JavaScript has been disabled.  You'll
 958have to replace your browser with one supporting JavaScript
 959(or enable it, if that's the problem) before you can use
 960this 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>
 976Each of the fields in the one-time pad request form is described
 977below.
 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>
 985Enter the number of keys you'd like to generate.  If you generate
 986more than fit in the results text box, you can use the scroll
 987bar to view the additional lines.
 988</p>
 989
 990<h4><a name="LineLength">Line length</a></h4>
 991
 992<p>
 993Lines in the output will be limited to the given length (or contain
 994only one key if the line length is less than required for a single
 995key).  If the line length is greater than the width of the results
 996box, you can use the horizontal scroll bar to view the rest of the
 997line.  Enter <tt>0</tt> to force one key per line; this is handy
 998when 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>
1006Each key will contain this number of characters, not counting
1007separators between groups.
1008</p>
1009
1010<h4><a name="GroupLength">Group length</a></h4>
1011
1012<p>
1013If a nonzero value is entered in this field, the key will be broken
1014into groups of the given number of characters by separators.  Humans
1015find it easier to read and remember sequences of characters when
1016divided 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>
1024This set of radio buttons lets you select the character set used in
1025the keys.  The alternatives are listed in order of
1026increasing 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>
1063The case of letters in keys generated with Word-like, Alphabetic, and
1064Gibberish key text will be as chosen.  Most people find it easier to
1065read lower case letters than all capitals, but for some applications
1066(for example, where keys must be scanned optically by hardware that
1067only recognises capital letters), capitals are required.  Selecting
1068&ldquo;Mixed&nbsp;case&rdquo; creates keys with a mix of upper- and
1069lower-case letters; such keys are more secure than those with uniform
1070letter case, but do not pass the &ldquo;telephone test&rdquo;: you
1071can't read them across a (hopefully secure) voice link without having
1072to 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>
1078When the <a href="#KeyLength">Key length</a> is longer than
1079a nonzero <a href="#GroupLength">Group length</a> specification,
1080the key is divided into sequences of the given group length
1081by separator characters.  By default, a hyphen, &ldquo;<tt>-</tt>&rdquo;, is used
1082to separate groups.  If you check this box, separators will be
1083chosen at random among punctuation marks generally acceptable
1084for applications such as passwords.  If you're generating passwords
1085for a computer system, random separators dramatically increase
1086the difficulty of guessing passwords by exhaustive search.
1087</p>
1088
1089<h4><a name="Signatures">Include signatures</a></h4>
1090
1091<p>
1092
1093When this box is checked, at the end of the list of keys, preceded by
1094a line beginning with ten dashes &ldquo;<tt>-</tt>&rdquo;, the 128 bit MD5 signature of
1095each key is given, one per line, with signatures expressed as 32
1096hexadecimal digits.  Key signatures can be used to increase security
1097when keys are used to control access to computer systems or databases.
1098Instead of storing a copy of the keys, the computer stores their
1099signatures.  When the user enters a key, its signature is computed
1100with the same MD5 algorithm used to generate it initially, and the key
1101is accepted only if the signature matches.  Since discovering
1102a key which will generate a given signature is believed to be
1103computationally prohibitive, even if the list of signatures stored on
1104the computer is compromised, that information will not permit an
1105intruder to deduce a valid key.
1106</p>
1107
1108<p>
1109Signature calculation is a computationally intense process for which
1110JavaScript is not ideally suited; be patient while signatures are
1111generated, especially if your computer has modest
1112processing speed.
1113</p>
1114
1115<p>
1116For signature-based validation to be secure, it is essential
1117the original keys be long enough to prohibit discovery of matching
1118signatures by exhaustive search.  Suppose, for example, one used
1119four digit numeric keys, as used for Personal Identification
1120Numbers (PINs) by many credit card systems.  Since only 10,000
1121different keys exist, one could simply compute the signatures of
1122every possible key from 0000 through 9999, permitting an attacker who
1123came into possession of the table of signatures to recover the
1124keys by a simple lookup process.  For maximum security, keys must
1125contain at least as much information as the 128 bit signatures
1126computed from them.  This implies a minimum key length (not counting
1127non-random separator characters) for the various key formats as
1128follows:
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>
1141It should be noted that for many practical applications there is no
1142need for anything approaching 128-bit security.  The guidelines above
1143apply only in the case where maximum protection in the event of
1144undetected compromise of key signatures occurs.  In many
1145cases, much shorter keys are acceptable, especially when it is assumed
1146that a compromise of the system's password or signature database would
1147be only part of a much more serious subversion of all resources
1148on the system.
1149</p>
1150
1151<h3><a name="Seed">Seed</a></h3>
1152
1153<p>
1154The <em>seed</em> is the starting value which determines all
1155subsequent values in the pseudorandom sequence used to generate
1156the one-time pad.  Given the seed, the pad can be reproduced.  The
1157seed is a 31-bit number which can be derived from the date and
1158time at which the one-time pad was requested, or from a
1159user-defined seed value.  If the user-defined seed consists
1160entirely of decimal digits, it is used directly as the seed,
1161modulo 2<sup>31</sup>; if a string containing non-digit characters
1162is entered, it is used to compute a <em>hash code</em> which is
1163used to seed the generator.
1164
1165</p>
1166
1167<p>
1168When the clock is used to create the seed, the seed value is entered
1169in the User-defined box to allow you, by checking &ldquo;User-defined&rdquo;,
1170to produce additional pads with the same seed.
1171</p>
1172
1173<h2><a name="why">Why JavaScript?</a></h2>
1174
1175<p>
1176At first glance, JavaScript may seem an odd choice for programming
1177a page such as this.  The one-time pad generator program is rather
1178large and complicated, and downloading it to your browser takes longer
1179than would be required for a Java applet or to transfer a
1180one-time pad generated by a CGI program on the Web server.  I chose
1181JavaScript for two reasons: <em>security</em> and <em>transparency</em>.
1182
1183</p>
1184
1185<p>
1186<b>Security.</b>
1187The sole reason for the existence of one-time pads is to
1188provide a source of information known only to people to whom
1189they have been distributed in a secure manner.  This means
1190the generation process cannot involve any link whose security
1191is suspect.  If the pad were generated on a Web server and
1192transmitted to you, it would have to pass over the
1193Internet, where any intermediate site might make a copy
1194of your pad before you even received it.  Even if some
1195mechanism such as encryption could absolutely prevent the
1196pad's being intercepted, you'd still have no way to be sure
1197the site generating the pad didn't keep a copy
1198in a file, conveniently tagged with your Internet address.
1199</p>
1200
1201<p>
1202In order to have any degree of security, it is essential
1203that the pad be generated on <em>your</em> computer, without
1204involving any transmission or interaction with other
1205sites on the Internet.  A Web browser with JavaScript makes
1206this possible, since the generation program embedded in this
1207page runs entirely on your own computer and does not
1208transmit anything over the Internet.  Its output appears
1209only in the text box, allowing you to cut and paste it
1210to another application.  From there on, its security is
1211up to you.
1212</p>
1213
1214<p>
1215Security is never absolute.  A one-time pad generated with
1216this page might be compromised in a variety of ways, including
1217the 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>
1254One can whip oneself into a fine fever of paranoia worrying about
1255things like this.  One way to rule out the most probable risks
1256is to download a copy of the generator page and run it
1257from a &ldquo;<tt>file:</tt>&rdquo; URL on a computer which has no network
1258connection whatsoever and is located in a secure location
1259under your control.  And look very carefully at any files
1260created by your Web browser.  You may find the most interesting
1261things squirreled away there&hellip;.
1262</p>
1263
1264<p>
1265<b><a name="trans">Transparency</a>.</b>
1266Any security-related tool is only as good as its design
1267and implementation.  <em>Transparency</em> means that, in
1268essence, all the moving parts are visible so you can judge
1269for yourself whether the tool merits your confidence.  In
1270the case of a program, this means that source code must
1271be available, and that you can verify that the program
1272you're running corresponds to the source code provided.
1273
1274</p>
1275
1276<p>
1277The very nature of JavaScript achieves this transparency.
1278The program is embedded into this actual Web page; to
1279examine it you need only use your browser's &ldquo;View Source&rdquo;
1280facility, or save the page into a file on your computer
1281and read it with a text editor.  JavaScript's being
1282an interpreted language eliminates the risk of your running
1283a program different from the purported source code: with
1284an interpreted language what you read is what you run.
1285</p>
1286
1287<p>
1288Transparency is important even if you don't know enough about
1289programming or security to determine whether the program
1290contains any flaws.  The very fact that it can be examined
1291by anybody allows those with the required expertise to pass
1292judgment, and you can form your own conclusions based on
1293their analysis.
1294</p>
1295
1296<h2>Credits</h2>
1297
1298<p>
1299
1300The pseudorandom sequence generator is based on L'Ecuyer's
1301two-sequence generator as described in
1302<cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742.
1303A Bays-Durham shuffle is used to guard against regularities
1304lurking in L'Ecuyer's algorithm; see
1305<cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976)
1306pages 59&ndash;64 for details.
1307</p>
1308
1309<p>
1310The JavaScript implementation of the
1311<a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a>
1312was developed by Henri Torgemane; please view the source code of this
1313page to examine the code, including the copyright notice and
1314conditions 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>
1333by <a href="/">John Walker</a><br />
1334May 26, 1997<br />
1335
1336Updated: 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