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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/build/pgo/js-input/crypto-otp.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1344 @@
     1.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     1.5 +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
     1.6 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
     1.7 +<head>
     1.8 +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
     1.9 +<title>One-Time Pad Generator</title>
    1.10 +<meta name="description" content="JavaScript One-Time Pad Generator" />
    1.11 +<meta name="author" content="John Walker" />
    1.12 +<meta name="keywords" content="one, time, pad, generator, onetime, cryptography, JavaScript" />
    1.13 +<style type="text/css">
    1.14 +    a:link,  a:visited {
    1.15 +	background-color: inherit;
    1.16 +    	color: rgb(0%, 0%, 80%);
    1.17 +	text-decoration: none;
    1.18 +    }
    1.19 +
    1.20 +    a:hover  {
    1.21 +    	background-color:  rgb(30%, 30%, 100%);
    1.22 +    	color: rgb(100%, 100%, 100%);
    1.23 +    }
    1.24 +    
    1.25 +    a:active {
    1.26 +    	color: rgb(100%, 0%, 0%);
    1.27 +    	background-color:  rgb(30%, 30%, 100%);
    1.28 +    }
    1.29 +    
    1.30 +    a.i:link, a.i:visited, a.i:hover {
    1.31 +    	background-color:  inherit;
    1.32 +    	color: inherit;
    1.33 +	text-decoration: none;
    1.34 +    }
    1.35 +    
    1.36 +    body {
    1.37 +        margin-left: 15%;
    1.38 +        margin-right: 10%;
    1.39 +	background-color: #FFFFFF;
    1.40 +	color: #000000;
    1.41 +    }
    1.42 +    
    1.43 +    body.jsgen {
    1.44 +        margin-left: 5%;
    1.45 +        margin-right: 5%;
    1.46 +    }
    1.47 +    
    1.48 +    dt {
    1.49 +    	margin-top: 0.5em;
    1.50 +    }
    1.51 +    
    1.52 +    img.button {
    1.53 +    	border: 0px;
    1.54 +	vertical-align: middle;
    1.55 +    }
    1.56 +    
    1.57 +    img.keyicon {
    1.58 +	vertical-align: bottom;
    1.59 +    }
    1.60 +    
    1.61 +    p, dd, li {
    1.62 +    	text-align: justify;
    1.63 +    }
    1.64 +    
    1.65 +    p.centre {
    1.66 +    	text-align: center;
    1.67 +    }
    1.68 +    
    1.69 +    table.r {
    1.70 +   	float: right;
    1.71 +    }
    1.72 +    
    1.73 +    table.c {
    1.74 +    	background-color: #E0E0E0;
    1.75 +	color: #000000;
    1.76 +    	margin-left: auto;
    1.77 +	margin-right: auto;
    1.78 +    }
    1.79 +
    1.80 +    td.c {
    1.81 +    	text-align: center;
    1.82 +    }
    1.83 +    
    1.84 +    textarea {
    1.85 +    	background-color: #FFFFD0;
    1.86 +	color: #000000;
    1.87 +    }
    1.88 +</style>
    1.89 +<script type="text/javascript">
    1.90 +//<![CDATA[
    1.91 +
    1.92 +    loadTime = (new Date()).getTime();
    1.93 +
    1.94 +/*
    1.95 +
    1.96 +    L'Ecuyer's two-sequence generator with a Bays-Durham shuffle
    1.97 +    on the back-end.  Schrage's algorithm is used to perform
    1.98 +    64-bit modular arithmetic within the 32-bit constraints of
    1.99 +    JavaScript.
   1.100 +
   1.101 +    Bays, C. and S. D. Durham.  ACM Trans. Math. Software: 2 (1976)
   1.102 +        59-64.
   1.103 +
   1.104 +    L'Ecuyer, P.  Communications of the ACM: 31 (1968) 742-774.
   1.105 +
   1.106 +    Schrage, L.  ACM Trans. Math. Software: 5 (1979) 132-138.
   1.107 +
   1.108 +*/
   1.109 +
   1.110 +function uGen(old, a, q, r, m) {      // Schrage's modular multiplication algorithm
   1.111 +    var t;
   1.112 +
   1.113 +    t = Math.floor(old / q);
   1.114 +    t = a * (old - (t * q)) - (t * r);
   1.115 +    return Math.round((t < 0) ? (t + m) : t);
   1.116 +}
   1.117 +
   1.118 +function LEnext() {                   // Return next raw value
   1.119 +    var i;
   1.120 +
   1.121 +    this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
   1.122 +    this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
   1.123 +
   1.124 +    /* Extract shuffle table index from most significant part
   1.125 +       of the previous result. */
   1.126 +
   1.127 +    i = Math.floor(this.state / 67108862);
   1.128 +
   1.129 +    // New state is sum of generators modulo one of their moduli
   1.130 +
   1.131 +    this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
   1.132 +
   1.133 +    // Replace value in shuffle table with generator 1 result
   1.134 +
   1.135 +    this.shuffle[i] = this.gen1;
   1.136 +
   1.137 +    return this.state;
   1.138 +}
   1.139 +
   1.140 +//  Return next random integer between 0 and n inclusive
   1.141 +
   1.142 +function LEnint(n) {
   1.143 +    return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
   1.144 +}
   1.145 +
   1.146 +//  Constructor.  Called with seed value
   1.147 +
   1.148 +function LEcuyer(s) {
   1.149 +    var i;
   1.150 +
   1.151 +    this.shuffle = new Array(32);
   1.152 +    this.gen1 = this.gen2 = (s & 0x7FFFFFFF);
   1.153 +    for (i = 0; i < 19; i++) {
   1.154 +        this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
   1.155 +    }
   1.156 +
   1.157 +    // Fill the shuffle table with values
   1.158 +
   1.159 +    for (i = 0; i < 32; i++) {
   1.160 +        this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
   1.161 +        this.shuffle[31 - i] = this.gen1;
   1.162 +    }
   1.163 +    this.state = this.shuffle[0];
   1.164 +    this.next = LEnext;
   1.165 +    this.nextInt = LEnint;
   1.166 +}
   1.167 +
   1.168 +function sepchar() {
   1.169 +    if (rsep) {
   1.170 +        var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
   1.171 +        return seps.charAt(sepran.nextInt(seps.length - 1));
   1.172 +    }
   1.173 +    return "-";
   1.174 +}
   1.175 +
   1.176 +/*
   1.177 + *  md5.jvs 1.0b 27/06/96
   1.178 + *
   1.179 + * Javascript implementation of the RSA Data Security, Inc. MD5
   1.180 + * Message-Digest Algorithm.
   1.181 + *
   1.182 + * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
   1.183 + *
   1.184 + * Permission to use, copy, modify, and distribute this software
   1.185 + * and its documentation for any purposes and without
   1.186 + * fee is hereby granted provided that this copyright notice
   1.187 + * appears in all copies. 
   1.188 + *
   1.189 + * Of course, this soft is provided "as is" without express or implied
   1.190 + * warranty of any kind.
   1.191 +
   1.192 +    This version contains some trivial reformatting modifications
   1.193 +    by John Walker.
   1.194 +
   1.195 + */
   1.196 +
   1.197 +function array(n) {
   1.198 +    for (i = 0; i < n; i++) {
   1.199 +        this[i] = 0;
   1.200 +    }
   1.201 +    this.length = n;
   1.202 +}
   1.203 +
   1.204 +/* Some basic logical functions had to be rewritten because of a bug in
   1.205 + * Javascript.. Just try to compute 0xffffffff >> 4 with it..
   1.206 + * Of course, these functions are slower than the original would be, but
   1.207 + * at least, they work!
   1.208 + */
   1.209 +
   1.210 +function integer(n) {
   1.211 +    return n % (0xffffffff + 1);
   1.212 +}
   1.213 +
   1.214 +function shr(a, b) {
   1.215 +    a = integer(a);
   1.216 +    b = integer(b);
   1.217 +    if (a - 0x80000000 >= 0) {
   1.218 +        a = a % 0x80000000;
   1.219 +        a >>= b;
   1.220 +        a += 0x40000000 >> (b - 1);
   1.221 +    } else {
   1.222 +        a >>= b;
   1.223 +    }
   1.224 +    return a;
   1.225 +}
   1.226 +
   1.227 +function shl1(a) {
   1.228 +    a = a % 0x80000000;
   1.229 +    if (a & 0x40000000 == 0x40000000) {
   1.230 +        a -= 0x40000000;  
   1.231 +        a *= 2;
   1.232 +        a += 0x80000000;
   1.233 +    } else {
   1.234 +        a *= 2;
   1.235 +    }
   1.236 +    return a;
   1.237 +}
   1.238 +
   1.239 +function shl(a, b) {
   1.240 +    a = integer(a);
   1.241 +    b = integer(b);
   1.242 +    for (var i = 0; i < b; i++) {
   1.243 +        a = shl1(a);
   1.244 +    }
   1.245 +    return a;
   1.246 +}
   1.247 +
   1.248 +function and(a, b) {
   1.249 +    a = integer(a);
   1.250 +    b = integer(b);
   1.251 +    var t1 = a - 0x80000000;
   1.252 +    var t2 = b - 0x80000000;
   1.253 +    if (t1 >= 0) {
   1.254 +        if (t2 >= 0) {
   1.255 +            return ((t1 & t2) + 0x80000000);
   1.256 +        } else {
   1.257 +            return (t1 & b);
   1.258 +        }
   1.259 +    } else {
   1.260 +        if (t2 >= 0) {
   1.261 +            return (a & t2);
   1.262 +        } else {
   1.263 +            return (a & b);  
   1.264 +        }
   1.265 +    }
   1.266 +}
   1.267 +
   1.268 +function or(a, b) {
   1.269 +    a = integer(a);
   1.270 +    b = integer(b);
   1.271 +    var t1 = a - 0x80000000;
   1.272 +    var t2 = b - 0x80000000;
   1.273 +    if (t1 >= 0) {
   1.274 +        if (t2 >= 0) {
   1.275 +            return ((t1 | t2) + 0x80000000);
   1.276 +        } else {
   1.277 +            return ((t1 | b) + 0x80000000);
   1.278 +        }
   1.279 +    } else {
   1.280 +        if (t2 >= 0) {
   1.281 +            return ((a | t2) + 0x80000000);
   1.282 +        } else {
   1.283 +            return (a | b);  
   1.284 +        }
   1.285 +    }
   1.286 +}
   1.287 +
   1.288 +function xor(a, b) {
   1.289 +    a = integer(a);
   1.290 +    b = integer(b);
   1.291 +    var t1 = a - 0x80000000;
   1.292 +    var t2 = b - 0x80000000;
   1.293 +    if (t1 >= 0) {
   1.294 +        if (t2 >= 0) {
   1.295 +            return (t1 ^ t2);
   1.296 +        } else {
   1.297 +            return ((t1 ^ b) + 0x80000000);
   1.298 +        }
   1.299 +    } else {
   1.300 +        if (t2 >= 0) {
   1.301 +            return ((a ^ t2) + 0x80000000);
   1.302 +        } else {
   1.303 +            return (a ^ b);  
   1.304 +        }
   1.305 +    }
   1.306 +}
   1.307 +
   1.308 +function not(a) {
   1.309 +    a = integer(a);
   1.310 +    return 0xffffffff - a;
   1.311 +}
   1.312 +
   1.313 +/* Here begin the real algorithm */
   1.314 +
   1.315 +var state = new array(4); 
   1.316 +var count = new array(2);
   1.317 +    count[0] = 0;
   1.318 +    count[1] = 0;                     
   1.319 +var buffer = new array(64); 
   1.320 +var transformBuffer = new array(16); 
   1.321 +var digestBits = new array(16);
   1.322 +
   1.323 +var S11 = 7;
   1.324 +var S12 = 12;
   1.325 +var S13 = 17;
   1.326 +var S14 = 22;
   1.327 +var S21 = 5;
   1.328 +var S22 = 9;
   1.329 +var S23 = 14;
   1.330 +var S24 = 20;
   1.331 +var S31 = 4;
   1.332 +var S32 = 11;
   1.333 +var S33 = 16;
   1.334 +var S34 = 23;
   1.335 +var S41 = 6;
   1.336 +var S42 = 10;
   1.337 +var S43 = 15;
   1.338 +var S44 = 21;
   1.339 +
   1.340 +function F(x, y, z) {
   1.341 +    return or(and(x, y), and(not(x), z));
   1.342 +}
   1.343 +
   1.344 +function G(x, y, z) {
   1.345 +    return or(and(x, z), and(y, not(z)));
   1.346 +}
   1.347 +
   1.348 +function H(x, y, z) {
   1.349 +    return xor(xor(x, y), z);
   1.350 +}
   1.351 +
   1.352 +function I(x, y, z) {
   1.353 +    return xor(y ,or(x , not(z)));
   1.354 +}
   1.355 +
   1.356 +function rotateLeft(a, n) {
   1.357 +    return or(shl(a, n), (shr(a, (32 - n))));
   1.358 +}
   1.359 +
   1.360 +function FF(a, b, c, d, x, s, ac) {
   1.361 +    a = a + F(b, c, d) + x + ac;
   1.362 +    a = rotateLeft(a, s);
   1.363 +    a = a + b;
   1.364 +    return a;
   1.365 +}
   1.366 +
   1.367 +function GG(a, b, c, d, x, s, ac) {
   1.368 +    a = a + G(b, c, d) + x + ac;
   1.369 +    a = rotateLeft(a, s);
   1.370 +    a = a + b;
   1.371 +    return a;
   1.372 +}
   1.373 +
   1.374 +function HH(a, b, c, d, x, s, ac) {
   1.375 +    a = a + H(b, c, d) + x + ac;
   1.376 +    a = rotateLeft(a, s);
   1.377 +    a = a + b;
   1.378 +    return a;
   1.379 +}
   1.380 +
   1.381 +function II(a, b, c, d, x, s, ac) {
   1.382 +    a = a + I(b, c, d) + x + ac;
   1.383 +    a = rotateLeft(a, s);
   1.384 +    a = a + b;
   1.385 +    return a;
   1.386 +}
   1.387 +
   1.388 +function transform(buf, offset) { 
   1.389 +    var a = 0, b = 0, c = 0, d = 0; 
   1.390 +    var x = transformBuffer;
   1.391 +    
   1.392 +    a = state[0];
   1.393 +    b = state[1];
   1.394 +    c = state[2];
   1.395 +    d = state[3];
   1.396 +    
   1.397 +    for (i = 0; i < 16; i++) {
   1.398 +        x[i] = and(buf[i * 4 + offset], 0xFF);
   1.399 +        for (j = 1; j < 4; j++) {
   1.400 +            x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
   1.401 +        }
   1.402 +    }
   1.403 +
   1.404 +    /* Round 1 */
   1.405 +    a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
   1.406 +    d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
   1.407 +    c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
   1.408 +    b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
   1.409 +    a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
   1.410 +    d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
   1.411 +    c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
   1.412 +    b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
   1.413 +    a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
   1.414 +    d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
   1.415 +    c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
   1.416 +    b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
   1.417 +    a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
   1.418 +    d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
   1.419 +    c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
   1.420 +    b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
   1.421 +
   1.422 +    /* Round 2 */
   1.423 +    a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
   1.424 +    d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
   1.425 +    c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
   1.426 +    b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
   1.427 +    a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
   1.428 +    d = GG( d, a, b, c, x[10], S22,  0x2441453); /* 22 */
   1.429 +    c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
   1.430 +    b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
   1.431 +    a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
   1.432 +    d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
   1.433 +    c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
   1.434 +    b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
   1.435 +    a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
   1.436 +    d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
   1.437 +    c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
   1.438 +    b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
   1.439 +
   1.440 +    /* Round 3 */
   1.441 +    a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
   1.442 +    d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
   1.443 +    c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
   1.444 +    b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
   1.445 +    a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
   1.446 +    d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
   1.447 +    c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
   1.448 +    b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
   1.449 +    a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
   1.450 +    d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
   1.451 +    c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
   1.452 +    b = HH( b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
   1.453 +    a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
   1.454 +    d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
   1.455 +    c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
   1.456 +    b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
   1.457 +
   1.458 +    /* Round 4 */
   1.459 +    a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
   1.460 +    d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
   1.461 +    c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
   1.462 +    b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
   1.463 +    a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
   1.464 +    d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
   1.465 +    c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
   1.466 +    b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
   1.467 +    a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
   1.468 +    d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
   1.469 +    c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
   1.470 +    b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
   1.471 +    a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
   1.472 +    d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
   1.473 +    c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
   1.474 +    b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
   1.475 +
   1.476 +    state[0] += a;
   1.477 +    state[1] += b;
   1.478 +    state[2] += c;
   1.479 +    state[3] += d;
   1.480 +
   1.481 +}
   1.482 +
   1.483 +function init() {
   1.484 +    count[0] = count[1] = 0;
   1.485 +    state[0] = 0x67452301;
   1.486 +    state[1] = 0xefcdab89;
   1.487 +    state[2] = 0x98badcfe;
   1.488 +    state[3] = 0x10325476;
   1.489 +    for (i = 0; i < digestBits.length; i++) {
   1.490 +        digestBits[i] = 0;
   1.491 +    }
   1.492 +}
   1.493 +
   1.494 +function update(b) { 
   1.495 +    var index, i;
   1.496 +    
   1.497 +    index = and(shr(count[0],3) , 0x3F);
   1.498 +    if (count[0] < 0xFFFFFFFF - 7) {
   1.499 +      count[0] += 8;
   1.500 +    } else {
   1.501 +      count[1]++;
   1.502 +      count[0] -= 0xFFFFFFFF + 1;
   1.503 +      count[0] += 8;
   1.504 +    }
   1.505 +    buffer[index] = and(b, 0xff);
   1.506 +    if (index  >= 63) {
   1.507 +        transform(buffer, 0);
   1.508 +    }
   1.509 +}
   1.510 +
   1.511 +function finish() {
   1.512 +    var bits = new array(8);
   1.513 +    var padding; 
   1.514 +    var i = 0, index = 0, padLen = 0;
   1.515 +
   1.516 +    for (i = 0; i < 4; i++) {
   1.517 +        bits[i] = and(shr(count[0], (i * 8)), 0xFF);
   1.518 +    }
   1.519 +    for (i = 0; i < 4; i++) {
   1.520 +        bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
   1.521 +    }
   1.522 +    index = and(shr(count[0], 3), 0x3F);
   1.523 +    padLen = (index < 56) ? (56 - index) : (120 - index);
   1.524 +    padding = new array(64); 
   1.525 +    padding[0] = 0x80;
   1.526 +    for (i = 0; i < padLen; i++) {
   1.527 +      update(padding[i]);
   1.528 +    }
   1.529 +    for (i = 0; i < 8; i++) {
   1.530 +      update(bits[i]);
   1.531 +    }
   1.532 +
   1.533 +    for (i = 0; i < 4; i++) {
   1.534 +        for (j = 0; j < 4; j++) {
   1.535 +            digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
   1.536 +        }
   1.537 +    } 
   1.538 +}
   1.539 +
   1.540 +/* End of the MD5 algorithm */
   1.541 +
   1.542 +function gen() {
   1.543 +    window.status = "Generating...";
   1.544 +    document.getElementById('onetime').pad.value = "";
   1.545 +
   1.546 +    lower = document.getElementById('onetime').textcase.selectedIndex == 0;
   1.547 +    upper = document.getElementById('onetime').textcase.selectedIndex == 1;
   1.548 +    mixed = document.getElementById('onetime').textcase.selectedIndex == 2;
   1.549 +    rsep = document.getElementById('onetime').rsep.checked;
   1.550 +    if (!(numeric = document.getElementById('onetime').keytype[0].checked)) {
   1.551 +        english = document.getElementById('onetime').keytype[1].checked;
   1.552 +        gibberish = document.getElementById('onetime').keytype[3].checked;
   1.553 +    }
   1.554 +    clockseed = document.getElementById('onetime').seedy[0].checked
   1.555 +    makesig = document.getElementById('onetime').dosig.checked;
   1.556 +    npass = document.getElementById('onetime').nkeys.value;
   1.557 +    pw_length = Math.round(document.getElementById('onetime').klength.value);
   1.558 +    sep = document.getElementById('onetime').sep.value;
   1.559 +    linelen = document.getElementById('onetime').linelen.value;
   1.560 +//               01234567890123456789012345678901
   1.561 +    charcodes = " " +
   1.562 +                "!\"#$%&'()*+,-./0123456789:;<=>?" +
   1.563 +                "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
   1.564 +                "`abcdefghijklmnopqrstuvwxyz{|}~";
   1.565 +
   1.566 +    if (clockseed) {
   1.567 +        var n, j, ran0;
   1.568 +
   1.569 +        /*  Obtain seed from the clock.  To reduce the likelihood
   1.570 +            of the seed being guessed, we create the seed by combining
   1.571 +            the time of the request with the time the page was loaded,
   1.572 +            then use that composite value to seed an auxiliary generator
   1.573 +            which is cycled between one and 32 times based on the time
   1.574 +            derived initial seed, with the output of the generator fed
   1.575 +            back into the seed we use to generate the pad.  */
   1.576 +
   1.577 +        seed = Math.round((new Date()).getTime() % Math.pow(2, 31));
   1.578 +        ran0 = new LEcuyer((seed ^ Math.round(loadTime % Math.pow(2, 31))) & 0x7FFFFFFF);
   1.579 +        for (j = 0; j < (5 + ((seed >> 3) & 0xF)); j++) {
   1.580 +            n = ran0.nextInt(31);
   1.581 +        }
   1.582 +        while (n-- >= 0) {
   1.583 +            seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next();
   1.584 +        }
   1.585 +        seed &= 0x7FFFFFFF;
   1.586 +        document.getElementById('onetime').seeder.value = seed;
   1.587 +    } else {
   1.588 +        var useed, seedNum;
   1.589 +
   1.590 +        /* Obtain seed from user specification.  If the seed is a
   1.591 +           decimal number, use it as-is.  If it contains any
   1.592 +           non-numeric characters, construct a hash code and
   1.593 +           use that as the seed. */
   1.594 +
   1.595 +        useed = document.getElementById('onetime').seeder.value;
   1.596 +        seedNum = true;
   1.597 +        for (i = 0; i < useed.length; i++) {
   1.598 +            if ("0123456789".indexOf(useed.charAt(i)) == -1) {
   1.599 +                seedNum = false;
   1.600 +                break;
   1.601 +            }
   1.602 +        }
   1.603 +        if (seedNum) {
   1.604 +            seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31));
   1.605 +            document.getElementById('onetime').seeder.value = seed;
   1.606 +        } else {
   1.607 +            var s, t, iso, hex;
   1.608 +
   1.609 +            iso = "";
   1.610 +            hex = "0123456789ABCDEF";
   1.611 +            for (i = 32; i < 256; i++) {
   1.612 +                if (i < 127 || i >= 160) {
   1.613 +                    // Why not "s = i.toString(16);"?  Doesn't work in Netscape 3.0
   1.614 +                    iso += "%" + hex.charAt(i >> 4) + hex.charAt(i & 0xF);
   1.615 +                }
   1.616 +            }
   1.617 +            iso = unescape(iso);
   1.618 +            s = 0;
   1.619 +            for (i = 0; i < useed.length; i++) {
   1.620 +                t = iso.indexOf(useed.charAt(i));
   1.621 +                if (t < 0) {
   1.622 +                    t = 17;
   1.623 +                }
   1.624 +                s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t);
   1.625 +            }
   1.626 +            seed = s;
   1.627 +        }
   1.628 +    }
   1.629 +    ran1 = new LEcuyer(seed);
   1.630 +    ran2 = new LEcuyer(seed);
   1.631 +    if (rsep) {
   1.632 +        /*  Use a separate random generator for separators
   1.633 +            so that results are the same for a given seed
   1.634 +            for both choices of separators.  */
   1.635 +        sepran = new LEcuyer(seed);
   1.636 +    }
   1.637 +
   1.638 +    ndig = 1;
   1.639 +    j = 10;
   1.640 +    while (npass >= j) {
   1.641 +        ndig++;
   1.642 +        j *= 10;
   1.643 +    }
   1.644 +    pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0);
   1.645 +    pw_item += ndig + 5;
   1.646 +    j = pw_item * 3;
   1.647 +    if (j < 132) {
   1.648 +        j = 132;
   1.649 +    }
   1.650 +    npline = Math.floor(linelen / pw_item);
   1.651 +    if (npline < 1) {
   1.652 +        npline = 0;
   1.653 +    }
   1.654 +    v = "";
   1.655 +    md5v = "";
   1.656 +    lineno = 0;
   1.657 +    if (!numeric) {
   1.658 +        letters = "abcdefghijklmnopqrstuvwxyz";
   1.659 +        if (upper) {
   1.660 +            letters = letters.toUpperCase();
   1.661 +        }
   1.662 +        if (english) {
   1.663 +
   1.664 +            // Frequency of English digraphs (from D. Edwards 1/27/66)
   1.665 +
   1.666 +            frequency = new Array( 
   1.667 +                new Array(4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62,
   1.668 +                          23, 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1,
   1.669 +                          9, 1), /* aa - az */
   1.670 +
   1.671 +                new Array(13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0,
   1.672 +                          11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0), /* ba - bz */
   1.673 +
   1.674 +                new Array(32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1,
   1.675 +                          0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0), /* ca - cz */
   1.676 +
   1.677 +                new Array(40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15,
   1.678 +                          6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0), /* da - dz */
   1.679 +
   1.680 +                new Array(84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4,
   1.681 +                          55, 54, 146, 35, 37, 6, 191, 149, 65, 9, 26,
   1.682 +                          21, 12, 5, 0), /* ea - ez */
   1.683 +
   1.684 +                new Array(19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1,
   1.685 +                          0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0), /* fa - fz */
   1.686 +
   1.687 +                new Array(20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1,
   1.688 +                          4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0), /* ga - gz */
   1.689 +
   1.690 +                new Array(101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3,
   1.691 +                          2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0), /* ha - hz */
   1.692 +
   1.693 +                new Array(40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38,
   1.694 +                          25, 202, 56, 12, 1, 46, 79, 117, 1, 22, 0,
   1.695 +                          4, 0, 3), /* ia - iz */
   1.696 +
   1.697 +                new Array(3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4,
   1.698 +                          0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0), /* ja - jz */
   1.699 +
   1.700 +                new Array(1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2,
   1.701 +                          0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0), /* ka - kz */
   1.702 +
   1.703 +                new Array(44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2,
   1.704 +                          2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0), /* la - lz */
   1.705 +
   1.706 +                new Array(52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7,
   1.707 +                          1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0), /* ma - mz */
   1.708 +
   1.709 +                new Array(42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6,
   1.710 +                          6, 9, 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0,
   1.711 +                          12, 0), /* na - nz */
   1.712 +
   1.713 +                new Array(7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19,
   1.714 +                          41, 134, 13, 23, 0, 91, 23, 42, 55, 16, 28,
   1.715 +                          0, 4, 1), /* oa - oz */
   1.716 +
   1.717 +                new Array(19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0,
   1.718 +                          27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0), /* pa - pz */
   1.719 +
   1.720 +                new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.721 +                          0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0), /* qa - qz */
   1.722 +
   1.723 +                new Array(83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5,
   1.724 +                          26, 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0,
   1.725 +                          28, 0), /* ra - rz */
   1.726 +
   1.727 +                new Array(65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7,
   1.728 +                          11, 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0,
   1.729 +                          4, 0), /* sa - sz */
   1.730 +
   1.731 +                new Array(57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14,
   1.732 +                          10, 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0,
   1.733 +                          24, 0), /* ta - tz */
   1.734 +
   1.735 +                new Array(11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31,
   1.736 +                          1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0), /* ua - uz */
   1.737 +
   1.738 +                new Array(7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0,
   1.739 +                          5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0), /* va - vz */
   1.740 +
   1.741 +                new Array(36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1,
   1.742 +                          8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0), /* wa - wz */
   1.743 +
   1.744 +                new Array(1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1,
   1.745 +                          5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0), /* xa - xz */
   1.746 +
   1.747 +                new Array(14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7,
   1.748 +                          5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0), /* ya - yz */
   1.749 +
   1.750 +                new Array(1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.751 +                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) /* za - zz */ );
   1.752 +
   1.753 +            // This MUST be equal to the sum of the equivalent rows above.
   1.754 +
   1.755 +            row_sums = new Array(
   1.756 +                796,   160,    284,    401,    1276,   262,    199,    539,    777,    
   1.757 +                16,    39,     351,    243,    751,    662,    181,    17,     683,    
   1.758 +                662,   968,    248,    115,    180,    17,     162,    5
   1.759 +            );
   1.760 +
   1.761 +            // Frequencies of starting characters.
   1.762 +
   1.763 +            start_freq = new Array(
   1.764 +                1299,  425,    725,    271,    375,    470,    93,     223,    1009,
   1.765 +                24,    20,     355,    379,    319,    823,    618,    21,     317,
   1.766 +                962,   1991,   271,    104,    516,    6,      16,     14
   1.767 +            );
   1.768 +
   1.769 +            // This MUST be equal to the sum of all elements in the above array.
   1.770 +
   1.771 +            total_sum = 11646;
   1.772 +        }
   1.773 +        if (gibberish) {
   1.774 +            gibber = "abcdefghijklmnopqrstuvwxyz" +
   1.775 +                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
   1.776 +                     "0123456789" +
   1.777 +                     "!#$%&()*+,-./:;<=>?@[]^_{|}~";
   1.778 +            if (upper) {
   1.779 +                /*  Convert to upper case, leaving two copies of the
   1.780 +                    alphabet for two reasons: first, to favour letters
   1.781 +                    over gnarl, and second, to change only the letter case
   1.782 +                    when the mode is selected.  */
   1.783 +                gibber = gibber.toUpperCase();
   1.784 +            } else if (lower) {
   1.785 +	    	gibber = gibber.toLowerCase();
   1.786 +	    }
   1.787 +        }
   1.788 +    }
   1.789 +    for (line = 1; line <= npass; line++) {
   1.790 +        password = "";
   1.791 +        if (numeric) {
   1.792 +            for (nchars = 0; nchars < pw_length; nchars++) {
   1.793 +                if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
   1.794 +                    password += sepchar();
   1.795 +                }
   1.796 +                password += ran1.nextInt(9);
   1.797 +            }
   1.798 +        } else if (!english) {
   1.799 +            for (nchars = 0; nchars < pw_length; nchars++) {
   1.800 +                if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
   1.801 +                    password += sepchar();
   1.802 +                }
   1.803 +                if (gibberish) {
   1.804 +                    password += gibber.charAt(ran1.nextInt(gibber.length - 1));
   1.805 +                } else {
   1.806 +                    password += letters.charAt(ran1.nextInt(25));
   1.807 +                }
   1.808 +            }
   1.809 +        } else {
   1.810 +            position = ran1.nextInt(total_sum - 1);
   1.811 +            for (row_position = 0, j = 0; position >= row_position;
   1.812 +                 row_position += start_freq[j], j++) {
   1.813 +                continue;
   1.814 +            }
   1.815 +
   1.816 +            password = letters.charAt(i = j - 1);
   1.817 +            nch = 1;
   1.818 +            for (nchars = pw_length - 1; nchars; --nchars) {
   1.819 +
   1.820 +                // Now find random position within the row.
   1.821 +
   1.822 +                position = ran1.nextInt(row_sums[i] - 1);
   1.823 +                for (row_position = 0, j = 0;
   1.824 +                     position >= row_position;
   1.825 +                     row_position += frequency[i][j], j++) {
   1.826 +                }
   1.827 +
   1.828 +                if ((sep > 0) && ((nch % sep) == 0)) {
   1.829 +                    password += sepchar();
   1.830 +                }
   1.831 +                nch++;
   1.832 +                password += letters.charAt(i = j - 1);
   1.833 +            }
   1.834 +        }
   1.835 +	
   1.836 +	if ((!numeric) && (!gibberish) && mixed) {
   1.837 +	    var pwm = '';
   1.838 +	    var j;
   1.839 +	    for (j = 0; j < password.length; j++) {
   1.840 +	    	pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase());
   1.841 +	    }
   1.842 +	    password = pwm;
   1.843 +	}
   1.844 +
   1.845 +        /*  If requested, calculate the MD5 signature for this key and
   1.846 +            and save for later appending to the results.  */
   1.847 +
   1.848 +        if (makesig) {
   1.849 +            var n, m, hex = "0123456789ABCDEF";
   1.850 +
   1.851 +            init();
   1.852 +            for (m = 0; m < password.length; m++) {
   1.853 +                update(32 + charcodes.indexOf(password.charAt(m)));
   1.854 +            }
   1.855 +            finish();
   1.856 +
   1.857 +            for (n = 0; n < 16; n++) {
   1.858 +                md5v += hex.charAt(digestBits[n] >> 4);
   1.859 +                md5v += hex.charAt(digestBits[n] & 0xF);
   1.860 +            }
   1.861 +            md5v += "\n";
   1.862 +        }
   1.863 +
   1.864 +        aline = "" + line;
   1.865 +        while (aline.length < ndig) {
   1.866 +            aline = " " + aline;
   1.867 +        }
   1.868 +        v += aline + ") " + password;
   1.869 +
   1.870 +        if ((++lineno) >= npline) {
   1.871 +            v += "\n";
   1.872 +            lineno = 0;
   1.873 +        } else {
   1.874 +            v += "  ";
   1.875 +        }
   1.876 +    }
   1.877 +
   1.878 +    if (makesig) {
   1.879 +        v += "\n----------  MD5 Signatures  ----------\n" + md5v;
   1.880 +    }
   1.881 +
   1.882 +    document.getElementById('onetime').pad.value = v;
   1.883 +    window.status = "Done.";
   1.884 +}
   1.885 +
   1.886 +function loadHandler() {
   1.887 +    for (var i = 0; i < 25; i++) {
   1.888 +	gen();
   1.889 +    }
   1.890 +};
   1.891 +
   1.892 +//]]>
   1.893 +</script>
   1.894 +
   1.895 +</head>
   1.896 +
   1.897 +<body class="jsgen" onload="loadHandler();">
   1.898 +
   1.899 +<h1><img src="key.gif" class="keyicon" alt=""
   1.900 +    	 width="40" height="40" /> &nbsp; One-Time Pad Generator</h1>
   1.901 +
   1.902 +<p>
   1.903 +This page, which requires that your browser support JavaScript
   1.904 +(see <a href="#why"><cite>Why JavaScript</cite></a> below),
   1.905 +generates one-time pads or password lists in a variety of
   1.906 +forms.  It is based a high-quality pseudorandom sequence
   1.907 +generator, which can be seeded either from the current date
   1.908 +and time, or from a seed you provide.  Fill in the form below
   1.909 +to select the format of the pad and press &ldquo;Generate&rdquo; to
   1.910 +create the pad in the text box.  You can then copy and paste
   1.911 +the generated pad into another window to use as you wish.
   1.912 +Each of the labels on the request form is linked to a description
   1.913 +of that parameter.
   1.914 +</p>
   1.915 +
   1.916 +<form id="onetime" action="#" onsubmit="return false;">
   1.917 +
   1.918 +<p class="centre">
   1.919 +<b>Output:</b>
   1.920 +<a href="#NumberOfKeys">Number of keys</a>: <input type="text" name="nkeys" value="20" size="4" maxlength="12" />
   1.921 +<a href="#LineLength">Line length</a>: <input type="text" name="linelen" value="48" size="3" maxlength="12" />
   1.922 +<br />
   1.923 +<b>Format:</b>
   1.924 +<a href="#KeyLength">Key length</a>: <input type="text" name="klength" value="8" size="3" maxlength="12" />
   1.925 +<a href="#GroupLength">Group length</a>: <input type="text" name="sep" value="4" size="2" maxlength="12" />
   1.926 +
   1.927 +<br />
   1.928 +<b>Composition:</b>
   1.929 +<a href="#KeyText">Key text</a>: <input type="radio" name="keytype" /> Numeric
   1.930 +<input type="radio" name="keytype" /> Word-like
   1.931 +<input type="radio" name="keytype" checked="checked" /> Alphabetic
   1.932 +<input type="radio" name="keytype" /> Gibberish
   1.933 +<br />
   1.934 +<a href="#LetterCase">Letters:</a>
   1.935 +<select size="i" name="textcase">
   1.936 +
   1.937 +    <option value="1" selected="selected">Lower case</option>
   1.938 +    <option value="2">Upper case</option>
   1.939 +    <option value="3">Mixed case</option>
   1.940 +</select>
   1.941 +
   1.942 +<input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a>
   1.943 +<input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a>
   1.944 +
   1.945 +<br />
   1.946 +<b><a href="#Seed">Seed:</a></b>
   1.947 +<input type="radio" name="seedy" checked="checked" /> From clock
   1.948 +<input type="radio" name="seedy" /> User-defined:
   1.949 +<input type="text" name="seeder" value="" size="12" maxlength="128" 
   1.950 +       onchange="document.getElementById('onetime').seedy[1].checked=true;" />
   1.951 +<br />
   1.952 +<input type="button" value=" Generate " onclick="gen();" />
   1.953 +&nbsp;
   1.954 +<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" />
   1.955 +&nbsp;
   1.956 +<input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br />
   1.957 +<textarea name="pad" rows="12" cols="72">
   1.958 +
   1.959 +Uh, oh.  It appears your browser either does not support
   1.960 +JavaScript or that JavaScript has been disabled.  You'll
   1.961 +have to replace your browser with one supporting JavaScript
   1.962 +(or enable it, if that's the problem) before you can use
   1.963 +this page.
   1.964 +</textarea>
   1.965 +</p>
   1.966 +
   1.967 +</form>
   1.968 +
   1.969 +<script type="text/javascript">
   1.970 +//<![CDATA[
   1.971 +    //  Clear out "sorry, no JavaScript" message from text box.
   1.972 +    document.getElementById('onetime').pad.value = "";
   1.973 +//]]>
   1.974 +</script>
   1.975 +
   1.976 +<h2><a name="details">Details</a></h2>
   1.977 +
   1.978 +<p>
   1.979 +Each of the fields in the one-time pad request form is described
   1.980 +below.
   1.981 +</p>
   1.982 +
   1.983 +<h3><a name="output">Output</a></h3>
   1.984 +
   1.985 +<h4><a name="NumberOfKeys">Number of keys</a></h4>
   1.986 +
   1.987 +<p>
   1.988 +Enter the number of keys you'd like to generate.  If you generate
   1.989 +more than fit in the results text box, you can use the scroll
   1.990 +bar to view the additional lines.
   1.991 +</p>
   1.992 +
   1.993 +<h4><a name="LineLength">Line length</a></h4>
   1.994 +
   1.995 +<p>
   1.996 +Lines in the output will be limited to the given length (or contain
   1.997 +only one key if the line length is less than required for a single
   1.998 +key).  If the line length is greater than the width of the results
   1.999 +box, you can use the horizontal scroll bar to view the rest of the
  1.1000 +line.  Enter <tt>0</tt> to force one key per line; this is handy
  1.1001 +when you're preparing a list of keys to be read by a computer program.
  1.1002 +</p>
  1.1003 +
  1.1004 +<h3><a name="format">Format</a></h3>
  1.1005 +
  1.1006 +<h4><a name="KeyLength">Key length</a></h4>
  1.1007 +
  1.1008 +<p>
  1.1009 +Each key will contain this number of characters, not counting
  1.1010 +separators between groups.
  1.1011 +</p>
  1.1012 +
  1.1013 +<h4><a name="GroupLength">Group length</a></h4>
  1.1014 +
  1.1015 +<p>
  1.1016 +If a nonzero value is entered in this field, the key will be broken
  1.1017 +into groups of the given number of characters by separators.  Humans
  1.1018 +find it easier to read and remember sequences of characters when
  1.1019 +divided into groups of five or fewer characters.
  1.1020 +</p>
  1.1021 +
  1.1022 +<h3><a name="composition">Composition</a></h3>
  1.1023 +
  1.1024 +<h4><a name="KeyText">Key text</a></h4>
  1.1025 +
  1.1026 +<p>
  1.1027 +This set of radio buttons lets you select the character set used in
  1.1028 +the keys.  The alternatives are listed in order of
  1.1029 +increasing security.
  1.1030 +</p>
  1.1031 +
  1.1032 +<blockquote>
  1.1033 +<dl>
  1.1034 +<dt><b>Numeric</b></dt>
  1.1035 +<dd>Keys contain only the decimal digits &ldquo;0&rdquo; through &ldquo;9&rdquo;.
  1.1036 +    <em>Least secure.</em></dd>
  1.1037 +
  1.1038 +<dt><b>Word-like</b></dt>
  1.1039 +<dd>Keys are composed of alphabetic characters which obey the
  1.1040 +    digraph statistics of English text.  Such keys contain
  1.1041 +    sequences of vowels and consonants familiar to speakers
  1.1042 +    of Western languages, and are therefore usually easier to
  1.1043 +    memorise but, for a given key length, are less secure than
  1.1044 +    purely random letters.</dd>
  1.1045 +
  1.1046 +<dt><b>Alphabetic</b></dt>
  1.1047 +<dd>Keys consist of letters of the alphabet chosen at random. 
  1.1048 +    Each character has an equal probability of being one of
  1.1049 +    the 26 letters.</dd>
  1.1050 +
  1.1051 +<dt><b>Gibberish</b></dt>
  1.1052 +<dd>Keys use most of the printable ASCII character set, excluding
  1.1053 +    only characters frequently used for quoting purposes.  This
  1.1054 +    option provides the greatest security for a given key length,
  1.1055 +    but most people find keys like this difficult to memorise or
  1.1056 +    even transcribe from a printed pad.  If a human is in the loop,
  1.1057 +    it's often better to use a longer alphabetic or word-like key.
  1.1058 +    <em>Most secure.</em></dd>
  1.1059 +</dl>
  1.1060 +
  1.1061 +</blockquote>
  1.1062 +
  1.1063 +<h4><a name="LetterCase">Letters</a></h4>
  1.1064 +
  1.1065 +<p>
  1.1066 +The case of letters in keys generated with Word-like, Alphabetic, and
  1.1067 +Gibberish key text will be as chosen.  Most people find it easier to
  1.1068 +read lower case letters than all capitals, but for some applications
  1.1069 +(for example, where keys must be scanned optically by hardware that
  1.1070 +only recognises capital letters), capitals are required.  Selecting
  1.1071 +&ldquo;Mixed&nbsp;case&rdquo; creates keys with a mix of upper- and
  1.1072 +lower-case letters; such keys are more secure than those with uniform
  1.1073 +letter case, but do not pass the &ldquo;telephone test&rdquo;: you
  1.1074 +can't read them across a (hopefully secure) voice link without having
  1.1075 +to indicate whether each letter is or is not a capital.
  1.1076 +</p>
  1.1077 +
  1.1078 +<h4><a name="RandomSep">Random separators</a></h4>
  1.1079 +
  1.1080 +<p>
  1.1081 +When the <a href="#KeyLength">Key length</a> is longer than
  1.1082 +a nonzero <a href="#GroupLength">Group length</a> specification,
  1.1083 +the key is divided into sequences of the given group length
  1.1084 +by separator characters.  By default, a hyphen, &ldquo;<tt>-</tt>&rdquo;, is used
  1.1085 +to separate groups.  If you check this box, separators will be
  1.1086 +chosen at random among punctuation marks generally acceptable
  1.1087 +for applications such as passwords.  If you're generating passwords
  1.1088 +for a computer system, random separators dramatically increase
  1.1089 +the difficulty of guessing passwords by exhaustive search.
  1.1090 +</p>
  1.1091 +
  1.1092 +<h4><a name="Signatures">Include signatures</a></h4>
  1.1093 +
  1.1094 +<p>
  1.1095 +
  1.1096 +When this box is checked, at the end of the list of keys, preceded by
  1.1097 +a line beginning with ten dashes &ldquo;<tt>-</tt>&rdquo;, the 128 bit MD5 signature of
  1.1098 +each key is given, one per line, with signatures expressed as 32
  1.1099 +hexadecimal digits.  Key signatures can be used to increase security
  1.1100 +when keys are used to control access to computer systems or databases.
  1.1101 +Instead of storing a copy of the keys, the computer stores their
  1.1102 +signatures.  When the user enters a key, its signature is computed
  1.1103 +with the same MD5 algorithm used to generate it initially, and the key
  1.1104 +is accepted only if the signature matches.  Since discovering
  1.1105 +a key which will generate a given signature is believed to be
  1.1106 +computationally prohibitive, even if the list of signatures stored on
  1.1107 +the computer is compromised, that information will not permit an
  1.1108 +intruder to deduce a valid key.
  1.1109 +</p>
  1.1110 +
  1.1111 +<p>
  1.1112 +Signature calculation is a computationally intense process for which
  1.1113 +JavaScript is not ideally suited; be patient while signatures are
  1.1114 +generated, especially if your computer has modest
  1.1115 +processing speed.
  1.1116 +</p>
  1.1117 +
  1.1118 +<p>
  1.1119 +For signature-based validation to be secure, it is essential
  1.1120 +the original keys be long enough to prohibit discovery of matching
  1.1121 +signatures by exhaustive search.  Suppose, for example, one used
  1.1122 +four digit numeric keys, as used for Personal Identification
  1.1123 +Numbers (PINs) by many credit card systems.  Since only 10,000
  1.1124 +different keys exist, one could simply compute the signatures of
  1.1125 +every possible key from 0000 through 9999, permitting an attacker who
  1.1126 +came into possession of the table of signatures to recover the
  1.1127 +keys by a simple lookup process.  For maximum security, keys must
  1.1128 +contain at least as much information as the 128 bit signatures
  1.1129 +computed from them.  This implies a minimum key length (not counting
  1.1130 +non-random separator characters) for the various key formats as
  1.1131 +follows:
  1.1132 +</p>
  1.1133 +
  1.1134 +<table class="c" border="border" cellpadding="4">
  1.1135 +<tr><th>Key Composition</th> <th>Minimum Characters</th></tr>
  1.1136 +
  1.1137 +<tr><td>Numeric</td> <td class="c">39</td></tr>
  1.1138 +<tr><td>Word-like</td> <td class="c">30</td></tr>
  1.1139 +<tr><td>Alphabetic</td> <td class="c">28</td></tr>
  1.1140 +<tr><td>Gibberish</td> <td class="c">20</td></tr>
  1.1141 +</table>
  1.1142 +
  1.1143 +<p>
  1.1144 +It should be noted that for many practical applications there is no
  1.1145 +need for anything approaching 128-bit security.  The guidelines above
  1.1146 +apply only in the case where maximum protection in the event of
  1.1147 +undetected compromise of key signatures occurs.  In many
  1.1148 +cases, much shorter keys are acceptable, especially when it is assumed
  1.1149 +that a compromise of the system's password or signature database would
  1.1150 +be only part of a much more serious subversion of all resources
  1.1151 +on the system.
  1.1152 +</p>
  1.1153 +
  1.1154 +<h3><a name="Seed">Seed</a></h3>
  1.1155 +
  1.1156 +<p>
  1.1157 +The <em>seed</em> is the starting value which determines all
  1.1158 +subsequent values in the pseudorandom sequence used to generate
  1.1159 +the one-time pad.  Given the seed, the pad can be reproduced.  The
  1.1160 +seed is a 31-bit number which can be derived from the date and
  1.1161 +time at which the one-time pad was requested, or from a
  1.1162 +user-defined seed value.  If the user-defined seed consists
  1.1163 +entirely of decimal digits, it is used directly as the seed,
  1.1164 +modulo 2<sup>31</sup>; if a string containing non-digit characters
  1.1165 +is entered, it is used to compute a <em>hash code</em> which is
  1.1166 +used to seed the generator.
  1.1167 +
  1.1168 +</p>
  1.1169 +
  1.1170 +<p>
  1.1171 +When the clock is used to create the seed, the seed value is entered
  1.1172 +in the User-defined box to allow you, by checking &ldquo;User-defined&rdquo;,
  1.1173 +to produce additional pads with the same seed.
  1.1174 +</p>
  1.1175 +
  1.1176 +<h2><a name="why">Why JavaScript?</a></h2>
  1.1177 +
  1.1178 +<p>
  1.1179 +At first glance, JavaScript may seem an odd choice for programming
  1.1180 +a page such as this.  The one-time pad generator program is rather
  1.1181 +large and complicated, and downloading it to your browser takes longer
  1.1182 +than would be required for a Java applet or to transfer a
  1.1183 +one-time pad generated by a CGI program on the Web server.  I chose
  1.1184 +JavaScript for two reasons: <em>security</em> and <em>transparency</em>.
  1.1185 +
  1.1186 +</p>
  1.1187 +
  1.1188 +<p>
  1.1189 +<b>Security.</b>
  1.1190 +The sole reason for the existence of one-time pads is to
  1.1191 +provide a source of information known only to people to whom
  1.1192 +they have been distributed in a secure manner.  This means
  1.1193 +the generation process cannot involve any link whose security
  1.1194 +is suspect.  If the pad were generated on a Web server and
  1.1195 +transmitted to you, it would have to pass over the
  1.1196 +Internet, where any intermediate site might make a copy
  1.1197 +of your pad before you even received it.  Even if some
  1.1198 +mechanism such as encryption could absolutely prevent the
  1.1199 +pad's being intercepted, you'd still have no way to be sure
  1.1200 +the site generating the pad didn't keep a copy
  1.1201 +in a file, conveniently tagged with your Internet address.
  1.1202 +</p>
  1.1203 +
  1.1204 +<p>
  1.1205 +In order to have any degree of security, it is essential
  1.1206 +that the pad be generated on <em>your</em> computer, without
  1.1207 +involving any transmission or interaction with other
  1.1208 +sites on the Internet.  A Web browser with JavaScript makes
  1.1209 +this possible, since the generation program embedded in this
  1.1210 +page runs entirely on your own computer and does not
  1.1211 +transmit anything over the Internet.  Its output appears
  1.1212 +only in the text box, allowing you to cut and paste it
  1.1213 +to another application.  From there on, its security is
  1.1214 +up to you.
  1.1215 +</p>
  1.1216 +
  1.1217 +<p>
  1.1218 +Security is never absolute.  A one-time pad generated with
  1.1219 +this page might be compromised in a variety of ways, including
  1.1220 +the following:
  1.1221 +
  1.1222 +</p>
  1.1223 +
  1.1224 +<ul>
  1.1225 +<li>    Your Web browser and/or JavaScript interpreter may
  1.1226 +        contain bugs or deliberate security violations
  1.1227 +        which report activity on your computer back to some
  1.1228 +        other Internet site.</li>
  1.1229 +
  1.1230 +<li>    Some other applet running on another page of your
  1.1231 +        browser, perhaps without your being aware of its
  1.1232 +        existence, is spying on other windows.</li>
  1.1233 +
  1.1234 +<li>    Some other application running on your computer
  1.1235 +        may have compromised your system's security and
  1.1236 +        be snooping on your activity.</li>
  1.1237 +
  1.1238 +<li>    Your Web browser may be keeping a &ldquo;history log&rdquo;
  1.1239 +
  1.1240 +        or &ldquo;cache&rdquo; of data you generate.  Somebody may
  1.1241 +        come along later and recover a copy of the pad
  1.1242 +        from that log.</li>
  1.1243 +
  1.1244 +<li>    The implementation of this page may contain a bug
  1.1245 +        or deliberate error which makes its output
  1.1246 +        predictable.  This is why <a href="#trans"><cite>transparency</cite></a>,
  1.1247 +        discussed below, is essential.</li>
  1.1248 +
  1.1249 +<li>    Your computer's security may have been compromised
  1.1250 +        physically; when's the last time you checked that a
  1.1251 +        bug that transmits your keystrokes and/or screen
  1.1252 +        contents to that white van parked down the street
  1.1253 +        wasn't lurking inside your computer cabinet?</li>
  1.1254 +</ul>
  1.1255 +
  1.1256 +<p>
  1.1257 +One can whip oneself into a fine fever of paranoia worrying about
  1.1258 +things like this.  One way to rule out the most probable risks
  1.1259 +is to download a copy of the generator page and run it
  1.1260 +from a &ldquo;<tt>file:</tt>&rdquo; URL on a computer which has no network
  1.1261 +connection whatsoever and is located in a secure location
  1.1262 +under your control.  And look very carefully at any files
  1.1263 +created by your Web browser.  You may find the most interesting
  1.1264 +things squirreled away there&hellip;.
  1.1265 +</p>
  1.1266 +
  1.1267 +<p>
  1.1268 +<b><a name="trans">Transparency</a>.</b>
  1.1269 +Any security-related tool is only as good as its design
  1.1270 +and implementation.  <em>Transparency</em> means that, in
  1.1271 +essence, all the moving parts are visible so you can judge
  1.1272 +for yourself whether the tool merits your confidence.  In
  1.1273 +the case of a program, this means that source code must
  1.1274 +be available, and that you can verify that the program
  1.1275 +you're running corresponds to the source code provided.
  1.1276 +
  1.1277 +</p>
  1.1278 +
  1.1279 +<p>
  1.1280 +The very nature of JavaScript achieves this transparency.
  1.1281 +The program is embedded into this actual Web page; to
  1.1282 +examine it you need only use your browser's &ldquo;View Source&rdquo;
  1.1283 +facility, or save the page into a file on your computer
  1.1284 +and read it with a text editor.  JavaScript's being
  1.1285 +an interpreted language eliminates the risk of your running
  1.1286 +a program different from the purported source code: with
  1.1287 +an interpreted language what you read is what you run.
  1.1288 +</p>
  1.1289 +
  1.1290 +<p>
  1.1291 +Transparency is important even if you don't know enough about
  1.1292 +programming or security to determine whether the program
  1.1293 +contains any flaws.  The very fact that it can be examined
  1.1294 +by anybody allows those with the required expertise to pass
  1.1295 +judgment, and you can form your own conclusions based on
  1.1296 +their analysis.
  1.1297 +</p>
  1.1298 +
  1.1299 +<h2>Credits</h2>
  1.1300 +
  1.1301 +<p>
  1.1302 +
  1.1303 +The pseudorandom sequence generator is based on L'Ecuyer's
  1.1304 +two-sequence generator as described in
  1.1305 +<cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742.
  1.1306 +A Bays-Durham shuffle is used to guard against regularities
  1.1307 +lurking in L'Ecuyer's algorithm; see
  1.1308 +<cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976)
  1.1309 +pages 59&ndash;64 for details.
  1.1310 +</p>
  1.1311 +
  1.1312 +<p>
  1.1313 +The JavaScript implementation of the
  1.1314 +<a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a>
  1.1315 +was developed by Henri Torgemane; please view the source code of this
  1.1316 +page to examine the code, including the copyright notice and
  1.1317 +conditions of use.  The MD5 algorithm was developed by Ron Rivest.
  1.1318 +</p>
  1.1319 +
  1.1320 +<p />
  1.1321 +
  1.1322 +<hr />
  1.1323 +
  1.1324 +<p />
  1.1325 +
  1.1326 +<table class="r">
  1.1327 +<tr><td align="center">
  1.1328 +    <a class="i" href="http://validator.w3.org/check?uri=referer"><img
  1.1329 +       class="button"
  1.1330 +       src="valid-xhtml10.png"
  1.1331 +       alt="Valid XHTML 1.0" height="31" width="88" /></a>
  1.1332 +</td></tr>
  1.1333 +</table>
  1.1334 +
  1.1335 +<address>
  1.1336 +by <a href="/">John Walker</a><br />
  1.1337 +May 26, 1997<br />
  1.1338 +
  1.1339 +Updated: November 2006
  1.1340 +</address>
  1.1341 +
  1.1342 +<p class="centre">
  1.1343 +<em>This document is in the public domain.</em>
  1.1344 +</p>
  1.1345 +</body>
  1.1346 +</html>
  1.1347 +

mercurial