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

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

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

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

     1 <!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     }
    17     a:hover  {
    18     	background-color:  rgb(30%, 30%, 100%);
    19     	color: rgb(100%, 100%, 100%);
    20     }
    22     a:active {
    23     	color: rgb(100%, 0%, 0%);
    24     	background-color:  rgb(30%, 30%, 100%);
    25     }
    27     a.i:link, a.i:visited, a.i:hover {
    28     	background-color:  inherit;
    29     	color: inherit;
    30 	text-decoration: none;
    31     }
    33     body {
    34         margin-left: 15%;
    35         margin-right: 10%;
    36 	background-color: #FFFFFF;
    37 	color: #000000;
    38     }
    40     body.jsgen {
    41         margin-left: 5%;
    42         margin-right: 5%;
    43     }
    45     dt {
    46     	margin-top: 0.5em;
    47     }
    49     img.button {
    50     	border: 0px;
    51 	vertical-align: middle;
    52     }
    54     img.keyicon {
    55 	vertical-align: bottom;
    56     }
    58     p, dd, li {
    59     	text-align: justify;
    60     }
    62     p.centre {
    63     	text-align: center;
    64     }
    66     table.r {
    67    	float: right;
    68     }
    70     table.c {
    71     	background-color: #E0E0E0;
    72 	color: #000000;
    73     	margin-left: auto;
    74 	margin-right: auto;
    75     }
    77     td.c {
    78     	text-align: center;
    79     }
    81     textarea {
    82     	background-color: #FFFFD0;
    83 	color: #000000;
    84     }
    85 </style>
    86 <script type="text/javascript">
    87 //<![CDATA[
    89     loadTime = (new Date()).getTime();
    91 /*
    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.
    98     Bays, C. and S. D. Durham.  ACM Trans. Math. Software: 2 (1976)
    99         59-64.
   101     L'Ecuyer, P.  Communications of the ACM: 31 (1968) 742-774.
   103     Schrage, L.  ACM Trans. Math. Software: 5 (1979) 132-138.
   105 */
   107 function uGen(old, a, q, r, m) {      // Schrage's modular multiplication algorithm
   108     var t;
   110     t = Math.floor(old / q);
   111     t = a * (old - (t * q)) - (t * r);
   112     return Math.round((t < 0) ? (t + m) : t);
   113 }
   115 function LEnext() {                   // Return next raw value
   116     var i;
   118     this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
   119     this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
   121     /* Extract shuffle table index from most significant part
   122        of the previous result. */
   124     i = Math.floor(this.state / 67108862);
   126     // New state is sum of generators modulo one of their moduli
   128     this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
   130     // Replace value in shuffle table with generator 1 result
   132     this.shuffle[i] = this.gen1;
   134     return this.state;
   135 }
   137 //  Return next random integer between 0 and n inclusive
   139 function LEnint(n) {
   140     return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
   141 }
   143 //  Constructor.  Called with seed value
   145 function LEcuyer(s) {
   146     var i;
   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     }
   154     // Fill the shuffle table with values
   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 }
   165 function sepchar() {
   166     if (rsep) {
   167         var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
   168         return seps.charAt(sepran.nextInt(seps.length - 1));
   169     }
   170     return "-";
   171 }
   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.
   189     This version contains some trivial reformatting modifications
   190     by John Walker.
   192  */
   194 function array(n) {
   195     for (i = 0; i < n; i++) {
   196         this[i] = 0;
   197     }
   198     this.length = n;
   199 }
   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  */
   207 function integer(n) {
   208     return n % (0xffffffff + 1);
   209 }
   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 }
   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 }
   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 }
   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 }
   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 }
   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 }
   305 function not(a) {
   306     a = integer(a);
   307     return 0xffffffff - a;
   308 }
   310 /* Here begin the real algorithm */
   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);
   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;
   337 function F(x, y, z) {
   338     return or(and(x, y), and(not(x), z));
   339 }
   341 function G(x, y, z) {
   342     return or(and(x, z), and(y, not(z)));
   343 }
   345 function H(x, y, z) {
   346     return xor(xor(x, y), z);
   347 }
   349 function I(x, y, z) {
   350     return xor(y ,or(x , not(z)));
   351 }
   353 function rotateLeft(a, n) {
   354     return or(shl(a, n), (shr(a, (32 - n))));
   355 }
   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 }
   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 }
   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 }
   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 }
   385 function transform(buf, offset) { 
   386     var a = 0, b = 0, c = 0, d = 0; 
   387     var x = transformBuffer;
   389     a = state[0];
   390     b = state[1];
   391     c = state[2];
   392     d = state[3];
   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     }
   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 */
   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 */
   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 */
   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 */
   473     state[0] += a;
   474     state[1] += b;
   475     state[2] += c;
   476     state[3] += d;
   478 }
   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 }
   491 function update(b) { 
   492     var index, i;
   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 }
   508 function finish() {
   509     var bits = new array(8);
   510     var padding; 
   511     var i = 0, index = 0, padLen = 0;
   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     }
   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 }
   537 /* End of the MD5 algorithm */
   539 function gen() {
   540     window.status = "Generating...";
   541     document.getElementById('onetime').pad.value = "";
   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{|}~";
   563     if (clockseed) {
   564         var n, j, ran0;
   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.  */
   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;
   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. */
   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;
   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     }
   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) {
   661             // Frequency of English digraphs (from D. Edwards 1/27/66)
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */ );
   750             // This MUST be equal to the sum of the equivalent rows above.
   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             );
   758             // Frequencies of starting characters.
   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             );
   766             // This MUST be equal to the sum of all elements in the above array.
   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             }
   813             password = letters.charAt(i = j - 1);
   814             nch = 1;
   815             for (nchars = pw_length - 1; nchars; --nchars) {
   817                 // Now find random position within the row.
   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                 }
   825                 if ((sep > 0) && ((nch % sep) == 0)) {
   826                     password += sepchar();
   827                 }
   828                 nch++;
   829                 password += letters.charAt(i = j - 1);
   830             }
   831         }
   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 	}
   842         /*  If requested, calculate the MD5 signature for this key and
   843             and save for later appending to the results.  */
   845         if (makesig) {
   846             var n, m, hex = "0123456789ABCDEF";
   848             init();
   849             for (m = 0; m < password.length; m++) {
   850                 update(32 + charcodes.indexOf(password.charAt(m)));
   851             }
   852             finish();
   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         }
   861         aline = "" + line;
   862         while (aline.length < ndig) {
   863             aline = " " + aline;
   864         }
   865         v += aline + ") " + password;
   867         if ((++lineno) >= npline) {
   868             v += "\n";
   869             lineno = 0;
   870         } else {
   871             v += "  ";
   872         }
   873     }
   875     if (makesig) {
   876         v += "\n----------  MD5 Signatures  ----------\n" + md5v;
   877     }
   879     document.getElementById('onetime').pad.value = v;
   880     window.status = "Done.";
   881 }
   883 function loadHandler() {
   884     for (var i = 0; i < 25; i++) {
   885 	gen();
   886     }
   887 };
   889 //]]>
   890 </script>
   892 </head>
   894 <body class="jsgen" onload="loadHandler();">
   896 <h1><img src="key.gif" class="keyicon" alt=""
   897     	 width="40" height="40" /> &nbsp; One-Time Pad Generator</h1>
   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>
   913 <form id="onetime" action="#" onsubmit="return false;">
   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" />
   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">
   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>
   939 <input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a>
   940 <input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a>
   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">
   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>
   964 </form>
   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>
   973 <h2><a name="details">Details</a></h2>
   975 <p>
   976 Each of the fields in the one-time pad request form is described
   977 below.
   978 </p>
   980 <h3><a name="output">Output</a></h3>
   982 <h4><a name="NumberOfKeys">Number of keys</a></h4>
   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>
   990 <h4><a name="LineLength">Line length</a></h4>
   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>
  1001 <h3><a name="format">Format</a></h3>
  1003 <h4><a name="KeyLength">Key length</a></h4>
  1005 <p>
  1006 Each key will contain this number of characters, not counting
  1007 separators between groups.
  1008 </p>
  1010 <h4><a name="GroupLength">Group length</a></h4>
  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>
  1019 <h3><a name="composition">Composition</a></h3>
  1021 <h4><a name="KeyText">Key text</a></h4>
  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>
  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>
  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>
  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>
  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>
  1058 </blockquote>
  1060 <h4><a name="LetterCase">Letters</a></h4>
  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>
  1075 <h4><a name="RandomSep">Random separators</a></h4>
  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>
  1089 <h4><a name="Signatures">Include signatures</a></h4>
  1091 <p>
  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>
  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>
  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>
  1131 <table class="c" border="border" cellpadding="4">
  1132 <tr><th>Key Composition</th> <th>Minimum Characters</th></tr>
  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>
  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>
  1151 <h3><a name="Seed">Seed</a></h3>
  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.
  1165 </p>
  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>
  1173 <h2><a name="why">Why JavaScript?</a></h2>
  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>.
  1183 </p>
  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>
  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>
  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:
  1219 </p>
  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>
  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>
  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>
  1235 <li>    Your Web browser may be keeping a &ldquo;history log&rdquo;
  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>
  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>
  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>
  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>
  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.
  1274 </p>
  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>
  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>
  1296 <h2>Credits</h2>
  1298 <p>
  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>
  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>
  1317 <p />
  1319 <hr />
  1321 <p />
  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>
  1332 <address>
  1333 by <a href="/">John Walker</a><br />
  1334 May 26, 1997<br />
  1336 Updated: November 2006
  1337 </address>
  1339 <p class="centre">
  1340 <em>This document is in the public domain.</em>
  1341 </p>
  1342 </body>
  1343 </html>

mercurial