tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

crypto-otp.html (43991B)


      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".includes(useed.charAt(i))) {
    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>