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" /> 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 “Generate” 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 + 1.954 +<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" /> 1.955 + 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 “0” through “9”. 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 +“Mixed case” 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 “telephone test”: 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, “<tt>-</tt>”, 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 “<tt>-</tt>”, 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 “User-defined”, 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 “history log” 1.1239 + 1.1240 + or “cache” 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 “<tt>file:</tt>” 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…. 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 “View Source” 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–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 +