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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
michael@0 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
michael@0 3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
michael@0 4 <head>
michael@0 5 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
michael@0 6 <title>One-Time Pad Generator</title>
michael@0 7 <meta name="description" content="JavaScript One-Time Pad Generator" />
michael@0 8 <meta name="author" content="John Walker" />
michael@0 9 <meta name="keywords" content="one, time, pad, generator, onetime, cryptography, JavaScript" />
michael@0 10 <style type="text/css">
michael@0 11 a:link, a:visited {
michael@0 12 background-color: inherit;
michael@0 13 color: rgb(0%, 0%, 80%);
michael@0 14 text-decoration: none;
michael@0 15 }
michael@0 16
michael@0 17 a:hover {
michael@0 18 background-color: rgb(30%, 30%, 100%);
michael@0 19 color: rgb(100%, 100%, 100%);
michael@0 20 }
michael@0 21
michael@0 22 a:active {
michael@0 23 color: rgb(100%, 0%, 0%);
michael@0 24 background-color: rgb(30%, 30%, 100%);
michael@0 25 }
michael@0 26
michael@0 27 a.i:link, a.i:visited, a.i:hover {
michael@0 28 background-color: inherit;
michael@0 29 color: inherit;
michael@0 30 text-decoration: none;
michael@0 31 }
michael@0 32
michael@0 33 body {
michael@0 34 margin-left: 15%;
michael@0 35 margin-right: 10%;
michael@0 36 background-color: #FFFFFF;
michael@0 37 color: #000000;
michael@0 38 }
michael@0 39
michael@0 40 body.jsgen {
michael@0 41 margin-left: 5%;
michael@0 42 margin-right: 5%;
michael@0 43 }
michael@0 44
michael@0 45 dt {
michael@0 46 margin-top: 0.5em;
michael@0 47 }
michael@0 48
michael@0 49 img.button {
michael@0 50 border: 0px;
michael@0 51 vertical-align: middle;
michael@0 52 }
michael@0 53
michael@0 54 img.keyicon {
michael@0 55 vertical-align: bottom;
michael@0 56 }
michael@0 57
michael@0 58 p, dd, li {
michael@0 59 text-align: justify;
michael@0 60 }
michael@0 61
michael@0 62 p.centre {
michael@0 63 text-align: center;
michael@0 64 }
michael@0 65
michael@0 66 table.r {
michael@0 67 float: right;
michael@0 68 }
michael@0 69
michael@0 70 table.c {
michael@0 71 background-color: #E0E0E0;
michael@0 72 color: #000000;
michael@0 73 margin-left: auto;
michael@0 74 margin-right: auto;
michael@0 75 }
michael@0 76
michael@0 77 td.c {
michael@0 78 text-align: center;
michael@0 79 }
michael@0 80
michael@0 81 textarea {
michael@0 82 background-color: #FFFFD0;
michael@0 83 color: #000000;
michael@0 84 }
michael@0 85 </style>
michael@0 86 <script type="text/javascript">
michael@0 87 //<![CDATA[
michael@0 88
michael@0 89 loadTime = (new Date()).getTime();
michael@0 90
michael@0 91 /*
michael@0 92
michael@0 93 L'Ecuyer's two-sequence generator with a Bays-Durham shuffle
michael@0 94 on the back-end. Schrage's algorithm is used to perform
michael@0 95 64-bit modular arithmetic within the 32-bit constraints of
michael@0 96 JavaScript.
michael@0 97
michael@0 98 Bays, C. and S. D. Durham. ACM Trans. Math. Software: 2 (1976)
michael@0 99 59-64.
michael@0 100
michael@0 101 L'Ecuyer, P. Communications of the ACM: 31 (1968) 742-774.
michael@0 102
michael@0 103 Schrage, L. ACM Trans. Math. Software: 5 (1979) 132-138.
michael@0 104
michael@0 105 */
michael@0 106
michael@0 107 function uGen(old, a, q, r, m) { // Schrage's modular multiplication algorithm
michael@0 108 var t;
michael@0 109
michael@0 110 t = Math.floor(old / q);
michael@0 111 t = a * (old - (t * q)) - (t * r);
michael@0 112 return Math.round((t < 0) ? (t + m) : t);
michael@0 113 }
michael@0 114
michael@0 115 function LEnext() { // Return next raw value
michael@0 116 var i;
michael@0 117
michael@0 118 this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
michael@0 119 this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
michael@0 120
michael@0 121 /* Extract shuffle table index from most significant part
michael@0 122 of the previous result. */
michael@0 123
michael@0 124 i = Math.floor(this.state / 67108862);
michael@0 125
michael@0 126 // New state is sum of generators modulo one of their moduli
michael@0 127
michael@0 128 this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
michael@0 129
michael@0 130 // Replace value in shuffle table with generator 1 result
michael@0 131
michael@0 132 this.shuffle[i] = this.gen1;
michael@0 133
michael@0 134 return this.state;
michael@0 135 }
michael@0 136
michael@0 137 // Return next random integer between 0 and n inclusive
michael@0 138
michael@0 139 function LEnint(n) {
michael@0 140 return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
michael@0 141 }
michael@0 142
michael@0 143 // Constructor. Called with seed value
michael@0 144
michael@0 145 function LEcuyer(s) {
michael@0 146 var i;
michael@0 147
michael@0 148 this.shuffle = new Array(32);
michael@0 149 this.gen1 = this.gen2 = (s & 0x7FFFFFFF);
michael@0 150 for (i = 0; i < 19; i++) {
michael@0 151 this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
michael@0 152 }
michael@0 153
michael@0 154 // Fill the shuffle table with values
michael@0 155
michael@0 156 for (i = 0; i < 32; i++) {
michael@0 157 this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
michael@0 158 this.shuffle[31 - i] = this.gen1;
michael@0 159 }
michael@0 160 this.state = this.shuffle[0];
michael@0 161 this.next = LEnext;
michael@0 162 this.nextInt = LEnint;
michael@0 163 }
michael@0 164
michael@0 165 function sepchar() {
michael@0 166 if (rsep) {
michael@0 167 var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
michael@0 168 return seps.charAt(sepran.nextInt(seps.length - 1));
michael@0 169 }
michael@0 170 return "-";
michael@0 171 }
michael@0 172
michael@0 173 /*
michael@0 174 * md5.jvs 1.0b 27/06/96
michael@0 175 *
michael@0 176 * Javascript implementation of the RSA Data Security, Inc. MD5
michael@0 177 * Message-Digest Algorithm.
michael@0 178 *
michael@0 179 * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
michael@0 180 *
michael@0 181 * Permission to use, copy, modify, and distribute this software
michael@0 182 * and its documentation for any purposes and without
michael@0 183 * fee is hereby granted provided that this copyright notice
michael@0 184 * appears in all copies.
michael@0 185 *
michael@0 186 * Of course, this soft is provided "as is" without express or implied
michael@0 187 * warranty of any kind.
michael@0 188
michael@0 189 This version contains some trivial reformatting modifications
michael@0 190 by John Walker.
michael@0 191
michael@0 192 */
michael@0 193
michael@0 194 function array(n) {
michael@0 195 for (i = 0; i < n; i++) {
michael@0 196 this[i] = 0;
michael@0 197 }
michael@0 198 this.length = n;
michael@0 199 }
michael@0 200
michael@0 201 /* Some basic logical functions had to be rewritten because of a bug in
michael@0 202 * Javascript.. Just try to compute 0xffffffff >> 4 with it..
michael@0 203 * Of course, these functions are slower than the original would be, but
michael@0 204 * at least, they work!
michael@0 205 */
michael@0 206
michael@0 207 function integer(n) {
michael@0 208 return n % (0xffffffff + 1);
michael@0 209 }
michael@0 210
michael@0 211 function shr(a, b) {
michael@0 212 a = integer(a);
michael@0 213 b = integer(b);
michael@0 214 if (a - 0x80000000 >= 0) {
michael@0 215 a = a % 0x80000000;
michael@0 216 a >>= b;
michael@0 217 a += 0x40000000 >> (b - 1);
michael@0 218 } else {
michael@0 219 a >>= b;
michael@0 220 }
michael@0 221 return a;
michael@0 222 }
michael@0 223
michael@0 224 function shl1(a) {
michael@0 225 a = a % 0x80000000;
michael@0 226 if (a & 0x40000000 == 0x40000000) {
michael@0 227 a -= 0x40000000;
michael@0 228 a *= 2;
michael@0 229 a += 0x80000000;
michael@0 230 } else {
michael@0 231 a *= 2;
michael@0 232 }
michael@0 233 return a;
michael@0 234 }
michael@0 235
michael@0 236 function shl(a, b) {
michael@0 237 a = integer(a);
michael@0 238 b = integer(b);
michael@0 239 for (var i = 0; i < b; i++) {
michael@0 240 a = shl1(a);
michael@0 241 }
michael@0 242 return a;
michael@0 243 }
michael@0 244
michael@0 245 function and(a, b) {
michael@0 246 a = integer(a);
michael@0 247 b = integer(b);
michael@0 248 var t1 = a - 0x80000000;
michael@0 249 var t2 = b - 0x80000000;
michael@0 250 if (t1 >= 0) {
michael@0 251 if (t2 >= 0) {
michael@0 252 return ((t1 & t2) + 0x80000000);
michael@0 253 } else {
michael@0 254 return (t1 & b);
michael@0 255 }
michael@0 256 } else {
michael@0 257 if (t2 >= 0) {
michael@0 258 return (a & t2);
michael@0 259 } else {
michael@0 260 return (a & b);
michael@0 261 }
michael@0 262 }
michael@0 263 }
michael@0 264
michael@0 265 function or(a, b) {
michael@0 266 a = integer(a);
michael@0 267 b = integer(b);
michael@0 268 var t1 = a - 0x80000000;
michael@0 269 var t2 = b - 0x80000000;
michael@0 270 if (t1 >= 0) {
michael@0 271 if (t2 >= 0) {
michael@0 272 return ((t1 | t2) + 0x80000000);
michael@0 273 } else {
michael@0 274 return ((t1 | b) + 0x80000000);
michael@0 275 }
michael@0 276 } else {
michael@0 277 if (t2 >= 0) {
michael@0 278 return ((a | t2) + 0x80000000);
michael@0 279 } else {
michael@0 280 return (a | b);
michael@0 281 }
michael@0 282 }
michael@0 283 }
michael@0 284
michael@0 285 function xor(a, b) {
michael@0 286 a = integer(a);
michael@0 287 b = integer(b);
michael@0 288 var t1 = a - 0x80000000;
michael@0 289 var t2 = b - 0x80000000;
michael@0 290 if (t1 >= 0) {
michael@0 291 if (t2 >= 0) {
michael@0 292 return (t1 ^ t2);
michael@0 293 } else {
michael@0 294 return ((t1 ^ b) + 0x80000000);
michael@0 295 }
michael@0 296 } else {
michael@0 297 if (t2 >= 0) {
michael@0 298 return ((a ^ t2) + 0x80000000);
michael@0 299 } else {
michael@0 300 return (a ^ b);
michael@0 301 }
michael@0 302 }
michael@0 303 }
michael@0 304
michael@0 305 function not(a) {
michael@0 306 a = integer(a);
michael@0 307 return 0xffffffff - a;
michael@0 308 }
michael@0 309
michael@0 310 /* Here begin the real algorithm */
michael@0 311
michael@0 312 var state = new array(4);
michael@0 313 var count = new array(2);
michael@0 314 count[0] = 0;
michael@0 315 count[1] = 0;
michael@0 316 var buffer = new array(64);
michael@0 317 var transformBuffer = new array(16);
michael@0 318 var digestBits = new array(16);
michael@0 319
michael@0 320 var S11 = 7;
michael@0 321 var S12 = 12;
michael@0 322 var S13 = 17;
michael@0 323 var S14 = 22;
michael@0 324 var S21 = 5;
michael@0 325 var S22 = 9;
michael@0 326 var S23 = 14;
michael@0 327 var S24 = 20;
michael@0 328 var S31 = 4;
michael@0 329 var S32 = 11;
michael@0 330 var S33 = 16;
michael@0 331 var S34 = 23;
michael@0 332 var S41 = 6;
michael@0 333 var S42 = 10;
michael@0 334 var S43 = 15;
michael@0 335 var S44 = 21;
michael@0 336
michael@0 337 function F(x, y, z) {
michael@0 338 return or(and(x, y), and(not(x), z));
michael@0 339 }
michael@0 340
michael@0 341 function G(x, y, z) {
michael@0 342 return or(and(x, z), and(y, not(z)));
michael@0 343 }
michael@0 344
michael@0 345 function H(x, y, z) {
michael@0 346 return xor(xor(x, y), z);
michael@0 347 }
michael@0 348
michael@0 349 function I(x, y, z) {
michael@0 350 return xor(y ,or(x , not(z)));
michael@0 351 }
michael@0 352
michael@0 353 function rotateLeft(a, n) {
michael@0 354 return or(shl(a, n), (shr(a, (32 - n))));
michael@0 355 }
michael@0 356
michael@0 357 function FF(a, b, c, d, x, s, ac) {
michael@0 358 a = a + F(b, c, d) + x + ac;
michael@0 359 a = rotateLeft(a, s);
michael@0 360 a = a + b;
michael@0 361 return a;
michael@0 362 }
michael@0 363
michael@0 364 function GG(a, b, c, d, x, s, ac) {
michael@0 365 a = a + G(b, c, d) + x + ac;
michael@0 366 a = rotateLeft(a, s);
michael@0 367 a = a + b;
michael@0 368 return a;
michael@0 369 }
michael@0 370
michael@0 371 function HH(a, b, c, d, x, s, ac) {
michael@0 372 a = a + H(b, c, d) + x + ac;
michael@0 373 a = rotateLeft(a, s);
michael@0 374 a = a + b;
michael@0 375 return a;
michael@0 376 }
michael@0 377
michael@0 378 function II(a, b, c, d, x, s, ac) {
michael@0 379 a = a + I(b, c, d) + x + ac;
michael@0 380 a = rotateLeft(a, s);
michael@0 381 a = a + b;
michael@0 382 return a;
michael@0 383 }
michael@0 384
michael@0 385 function transform(buf, offset) {
michael@0 386 var a = 0, b = 0, c = 0, d = 0;
michael@0 387 var x = transformBuffer;
michael@0 388
michael@0 389 a = state[0];
michael@0 390 b = state[1];
michael@0 391 c = state[2];
michael@0 392 d = state[3];
michael@0 393
michael@0 394 for (i = 0; i < 16; i++) {
michael@0 395 x[i] = and(buf[i * 4 + offset], 0xFF);
michael@0 396 for (j = 1; j < 4; j++) {
michael@0 397 x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
michael@0 398 }
michael@0 399 }
michael@0 400
michael@0 401 /* Round 1 */
michael@0 402 a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
michael@0 403 d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
michael@0 404 c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
michael@0 405 b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
michael@0 406 a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
michael@0 407 d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
michael@0 408 c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
michael@0 409 b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
michael@0 410 a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
michael@0 411 d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
michael@0 412 c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
michael@0 413 b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
michael@0 414 a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
michael@0 415 d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
michael@0 416 c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
michael@0 417 b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
michael@0 418
michael@0 419 /* Round 2 */
michael@0 420 a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
michael@0 421 d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
michael@0 422 c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
michael@0 423 b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
michael@0 424 a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
michael@0 425 d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */
michael@0 426 c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
michael@0 427 b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
michael@0 428 a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
michael@0 429 d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
michael@0 430 c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
michael@0 431 b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
michael@0 432 a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
michael@0 433 d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
michael@0 434 c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
michael@0 435 b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
michael@0 436
michael@0 437 /* Round 3 */
michael@0 438 a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
michael@0 439 d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
michael@0 440 c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
michael@0 441 b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
michael@0 442 a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
michael@0 443 d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
michael@0 444 c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
michael@0 445 b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
michael@0 446 a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
michael@0 447 d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
michael@0 448 c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
michael@0 449 b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
michael@0 450 a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
michael@0 451 d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
michael@0 452 c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
michael@0 453 b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
michael@0 454
michael@0 455 /* Round 4 */
michael@0 456 a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
michael@0 457 d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
michael@0 458 c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
michael@0 459 b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
michael@0 460 a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
michael@0 461 d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
michael@0 462 c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
michael@0 463 b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
michael@0 464 a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
michael@0 465 d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
michael@0 466 c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
michael@0 467 b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
michael@0 468 a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
michael@0 469 d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
michael@0 470 c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
michael@0 471 b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
michael@0 472
michael@0 473 state[0] += a;
michael@0 474 state[1] += b;
michael@0 475 state[2] += c;
michael@0 476 state[3] += d;
michael@0 477
michael@0 478 }
michael@0 479
michael@0 480 function init() {
michael@0 481 count[0] = count[1] = 0;
michael@0 482 state[0] = 0x67452301;
michael@0 483 state[1] = 0xefcdab89;
michael@0 484 state[2] = 0x98badcfe;
michael@0 485 state[3] = 0x10325476;
michael@0 486 for (i = 0; i < digestBits.length; i++) {
michael@0 487 digestBits[i] = 0;
michael@0 488 }
michael@0 489 }
michael@0 490
michael@0 491 function update(b) {
michael@0 492 var index, i;
michael@0 493
michael@0 494 index = and(shr(count[0],3) , 0x3F);
michael@0 495 if (count[0] < 0xFFFFFFFF - 7) {
michael@0 496 count[0] += 8;
michael@0 497 } else {
michael@0 498 count[1]++;
michael@0 499 count[0] -= 0xFFFFFFFF + 1;
michael@0 500 count[0] += 8;
michael@0 501 }
michael@0 502 buffer[index] = and(b, 0xff);
michael@0 503 if (index >= 63) {
michael@0 504 transform(buffer, 0);
michael@0 505 }
michael@0 506 }
michael@0 507
michael@0 508 function finish() {
michael@0 509 var bits = new array(8);
michael@0 510 var padding;
michael@0 511 var i = 0, index = 0, padLen = 0;
michael@0 512
michael@0 513 for (i = 0; i < 4; i++) {
michael@0 514 bits[i] = and(shr(count[0], (i * 8)), 0xFF);
michael@0 515 }
michael@0 516 for (i = 0; i < 4; i++) {
michael@0 517 bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
michael@0 518 }
michael@0 519 index = and(shr(count[0], 3), 0x3F);
michael@0 520 padLen = (index < 56) ? (56 - index) : (120 - index);
michael@0 521 padding = new array(64);
michael@0 522 padding[0] = 0x80;
michael@0 523 for (i = 0; i < padLen; i++) {
michael@0 524 update(padding[i]);
michael@0 525 }
michael@0 526 for (i = 0; i < 8; i++) {
michael@0 527 update(bits[i]);
michael@0 528 }
michael@0 529
michael@0 530 for (i = 0; i < 4; i++) {
michael@0 531 for (j = 0; j < 4; j++) {
michael@0 532 digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
michael@0 533 }
michael@0 534 }
michael@0 535 }
michael@0 536
michael@0 537 /* End of the MD5 algorithm */
michael@0 538
michael@0 539 function gen() {
michael@0 540 window.status = "Generating...";
michael@0 541 document.getElementById('onetime').pad.value = "";
michael@0 542
michael@0 543 lower = document.getElementById('onetime').textcase.selectedIndex == 0;
michael@0 544 upper = document.getElementById('onetime').textcase.selectedIndex == 1;
michael@0 545 mixed = document.getElementById('onetime').textcase.selectedIndex == 2;
michael@0 546 rsep = document.getElementById('onetime').rsep.checked;
michael@0 547 if (!(numeric = document.getElementById('onetime').keytype[0].checked)) {
michael@0 548 english = document.getElementById('onetime').keytype[1].checked;
michael@0 549 gibberish = document.getElementById('onetime').keytype[3].checked;
michael@0 550 }
michael@0 551 clockseed = document.getElementById('onetime').seedy[0].checked
michael@0 552 makesig = document.getElementById('onetime').dosig.checked;
michael@0 553 npass = document.getElementById('onetime').nkeys.value;
michael@0 554 pw_length = Math.round(document.getElementById('onetime').klength.value);
michael@0 555 sep = document.getElementById('onetime').sep.value;
michael@0 556 linelen = document.getElementById('onetime').linelen.value;
michael@0 557 // 01234567890123456789012345678901
michael@0 558 charcodes = " " +
michael@0 559 "!\"#$%&'()*+,-./0123456789:;<=>?" +
michael@0 560 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
michael@0 561 "`abcdefghijklmnopqrstuvwxyz{|}~";
michael@0 562
michael@0 563 if (clockseed) {
michael@0 564 var n, j, ran0;
michael@0 565
michael@0 566 /* Obtain seed from the clock. To reduce the likelihood
michael@0 567 of the seed being guessed, we create the seed by combining
michael@0 568 the time of the request with the time the page was loaded,
michael@0 569 then use that composite value to seed an auxiliary generator
michael@0 570 which is cycled between one and 32 times based on the time
michael@0 571 derived initial seed, with the output of the generator fed
michael@0 572 back into the seed we use to generate the pad. */
michael@0 573
michael@0 574 seed = Math.round((new Date()).getTime() % Math.pow(2, 31));
michael@0 575 ran0 = new LEcuyer((seed ^ Math.round(loadTime % Math.pow(2, 31))) & 0x7FFFFFFF);
michael@0 576 for (j = 0; j < (5 + ((seed >> 3) & 0xF)); j++) {
michael@0 577 n = ran0.nextInt(31);
michael@0 578 }
michael@0 579 while (n-- >= 0) {
michael@0 580 seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next();
michael@0 581 }
michael@0 582 seed &= 0x7FFFFFFF;
michael@0 583 document.getElementById('onetime').seeder.value = seed;
michael@0 584 } else {
michael@0 585 var useed, seedNum;
michael@0 586
michael@0 587 /* Obtain seed from user specification. If the seed is a
michael@0 588 decimal number, use it as-is. If it contains any
michael@0 589 non-numeric characters, construct a hash code and
michael@0 590 use that as the seed. */
michael@0 591
michael@0 592 useed = document.getElementById('onetime').seeder.value;
michael@0 593 seedNum = true;
michael@0 594 for (i = 0; i < useed.length; i++) {
michael@0 595 if ("0123456789".indexOf(useed.charAt(i)) == -1) {
michael@0 596 seedNum = false;
michael@0 597 break;
michael@0 598 }
michael@0 599 }
michael@0 600 if (seedNum) {
michael@0 601 seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31));
michael@0 602 document.getElementById('onetime').seeder.value = seed;
michael@0 603 } else {
michael@0 604 var s, t, iso, hex;
michael@0 605
michael@0 606 iso = "";
michael@0 607 hex = "0123456789ABCDEF";
michael@0 608 for (i = 32; i < 256; i++) {
michael@0 609 if (i < 127 || i >= 160) {
michael@0 610 // Why not "s = i.toString(16);"? Doesn't work in Netscape 3.0
michael@0 611 iso += "%" + hex.charAt(i >> 4) + hex.charAt(i & 0xF);
michael@0 612 }
michael@0 613 }
michael@0 614 iso = unescape(iso);
michael@0 615 s = 0;
michael@0 616 for (i = 0; i < useed.length; i++) {
michael@0 617 t = iso.indexOf(useed.charAt(i));
michael@0 618 if (t < 0) {
michael@0 619 t = 17;
michael@0 620 }
michael@0 621 s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t);
michael@0 622 }
michael@0 623 seed = s;
michael@0 624 }
michael@0 625 }
michael@0 626 ran1 = new LEcuyer(seed);
michael@0 627 ran2 = new LEcuyer(seed);
michael@0 628 if (rsep) {
michael@0 629 /* Use a separate random generator for separators
michael@0 630 so that results are the same for a given seed
michael@0 631 for both choices of separators. */
michael@0 632 sepran = new LEcuyer(seed);
michael@0 633 }
michael@0 634
michael@0 635 ndig = 1;
michael@0 636 j = 10;
michael@0 637 while (npass >= j) {
michael@0 638 ndig++;
michael@0 639 j *= 10;
michael@0 640 }
michael@0 641 pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0);
michael@0 642 pw_item += ndig + 5;
michael@0 643 j = pw_item * 3;
michael@0 644 if (j < 132) {
michael@0 645 j = 132;
michael@0 646 }
michael@0 647 npline = Math.floor(linelen / pw_item);
michael@0 648 if (npline < 1) {
michael@0 649 npline = 0;
michael@0 650 }
michael@0 651 v = "";
michael@0 652 md5v = "";
michael@0 653 lineno = 0;
michael@0 654 if (!numeric) {
michael@0 655 letters = "abcdefghijklmnopqrstuvwxyz";
michael@0 656 if (upper) {
michael@0 657 letters = letters.toUpperCase();
michael@0 658 }
michael@0 659 if (english) {
michael@0 660
michael@0 661 // Frequency of English digraphs (from D. Edwards 1/27/66)
michael@0 662
michael@0 663 frequency = new Array(
michael@0 664 new Array(4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62,
michael@0 665 23, 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1,
michael@0 666 9, 1), /* aa - az */
michael@0 667
michael@0 668 new Array(13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0,
michael@0 669 11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0), /* ba - bz */
michael@0 670
michael@0 671 new Array(32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1,
michael@0 672 0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0), /* ca - cz */
michael@0 673
michael@0 674 new Array(40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15,
michael@0 675 6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0), /* da - dz */
michael@0 676
michael@0 677 new Array(84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4,
michael@0 678 55, 54, 146, 35, 37, 6, 191, 149, 65, 9, 26,
michael@0 679 21, 12, 5, 0), /* ea - ez */
michael@0 680
michael@0 681 new Array(19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1,
michael@0 682 0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0), /* fa - fz */
michael@0 683
michael@0 684 new Array(20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1,
michael@0 685 4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0), /* ga - gz */
michael@0 686
michael@0 687 new Array(101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3,
michael@0 688 2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0), /* ha - hz */
michael@0 689
michael@0 690 new Array(40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38,
michael@0 691 25, 202, 56, 12, 1, 46, 79, 117, 1, 22, 0,
michael@0 692 4, 0, 3), /* ia - iz */
michael@0 693
michael@0 694 new Array(3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4,
michael@0 695 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0), /* ja - jz */
michael@0 696
michael@0 697 new Array(1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2,
michael@0 698 0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0), /* ka - kz */
michael@0 699
michael@0 700 new Array(44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2,
michael@0 701 2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0), /* la - lz */
michael@0 702
michael@0 703 new Array(52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7,
michael@0 704 1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0), /* ma - mz */
michael@0 705
michael@0 706 new Array(42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6,
michael@0 707 6, 9, 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0,
michael@0 708 12, 0), /* na - nz */
michael@0 709
michael@0 710 new Array(7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19,
michael@0 711 41, 134, 13, 23, 0, 91, 23, 42, 55, 16, 28,
michael@0 712 0, 4, 1), /* oa - oz */
michael@0 713
michael@0 714 new Array(19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0,
michael@0 715 27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0), /* pa - pz */
michael@0 716
michael@0 717 new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
michael@0 718 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0), /* qa - qz */
michael@0 719
michael@0 720 new Array(83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5,
michael@0 721 26, 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0,
michael@0 722 28, 0), /* ra - rz */
michael@0 723
michael@0 724 new Array(65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7,
michael@0 725 11, 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0,
michael@0 726 4, 0), /* sa - sz */
michael@0 727
michael@0 728 new Array(57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14,
michael@0 729 10, 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0,
michael@0 730 24, 0), /* ta - tz */
michael@0 731
michael@0 732 new Array(11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31,
michael@0 733 1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0), /* ua - uz */
michael@0 734
michael@0 735 new Array(7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0,
michael@0 736 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0), /* va - vz */
michael@0 737
michael@0 738 new Array(36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1,
michael@0 739 8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0), /* wa - wz */
michael@0 740
michael@0 741 new Array(1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1,
michael@0 742 5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0), /* xa - xz */
michael@0 743
michael@0 744 new Array(14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7,
michael@0 745 5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0), /* ya - yz */
michael@0 746
michael@0 747 new Array(1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
michael@0 748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) /* za - zz */ );
michael@0 749
michael@0 750 // This MUST be equal to the sum of the equivalent rows above.
michael@0 751
michael@0 752 row_sums = new Array(
michael@0 753 796, 160, 284, 401, 1276, 262, 199, 539, 777,
michael@0 754 16, 39, 351, 243, 751, 662, 181, 17, 683,
michael@0 755 662, 968, 248, 115, 180, 17, 162, 5
michael@0 756 );
michael@0 757
michael@0 758 // Frequencies of starting characters.
michael@0 759
michael@0 760 start_freq = new Array(
michael@0 761 1299, 425, 725, 271, 375, 470, 93, 223, 1009,
michael@0 762 24, 20, 355, 379, 319, 823, 618, 21, 317,
michael@0 763 962, 1991, 271, 104, 516, 6, 16, 14
michael@0 764 );
michael@0 765
michael@0 766 // This MUST be equal to the sum of all elements in the above array.
michael@0 767
michael@0 768 total_sum = 11646;
michael@0 769 }
michael@0 770 if (gibberish) {
michael@0 771 gibber = "abcdefghijklmnopqrstuvwxyz" +
michael@0 772 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
michael@0 773 "0123456789" +
michael@0 774 "!#$%&()*+,-./:;<=>?@[]^_{|}~";
michael@0 775 if (upper) {
michael@0 776 /* Convert to upper case, leaving two copies of the
michael@0 777 alphabet for two reasons: first, to favour letters
michael@0 778 over gnarl, and second, to change only the letter case
michael@0 779 when the mode is selected. */
michael@0 780 gibber = gibber.toUpperCase();
michael@0 781 } else if (lower) {
michael@0 782 gibber = gibber.toLowerCase();
michael@0 783 }
michael@0 784 }
michael@0 785 }
michael@0 786 for (line = 1; line <= npass; line++) {
michael@0 787 password = "";
michael@0 788 if (numeric) {
michael@0 789 for (nchars = 0; nchars < pw_length; nchars++) {
michael@0 790 if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
michael@0 791 password += sepchar();
michael@0 792 }
michael@0 793 password += ran1.nextInt(9);
michael@0 794 }
michael@0 795 } else if (!english) {
michael@0 796 for (nchars = 0; nchars < pw_length; nchars++) {
michael@0 797 if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
michael@0 798 password += sepchar();
michael@0 799 }
michael@0 800 if (gibberish) {
michael@0 801 password += gibber.charAt(ran1.nextInt(gibber.length - 1));
michael@0 802 } else {
michael@0 803 password += letters.charAt(ran1.nextInt(25));
michael@0 804 }
michael@0 805 }
michael@0 806 } else {
michael@0 807 position = ran1.nextInt(total_sum - 1);
michael@0 808 for (row_position = 0, j = 0; position >= row_position;
michael@0 809 row_position += start_freq[j], j++) {
michael@0 810 continue;
michael@0 811 }
michael@0 812
michael@0 813 password = letters.charAt(i = j - 1);
michael@0 814 nch = 1;
michael@0 815 for (nchars = pw_length - 1; nchars; --nchars) {
michael@0 816
michael@0 817 // Now find random position within the row.
michael@0 818
michael@0 819 position = ran1.nextInt(row_sums[i] - 1);
michael@0 820 for (row_position = 0, j = 0;
michael@0 821 position >= row_position;
michael@0 822 row_position += frequency[i][j], j++) {
michael@0 823 }
michael@0 824
michael@0 825 if ((sep > 0) && ((nch % sep) == 0)) {
michael@0 826 password += sepchar();
michael@0 827 }
michael@0 828 nch++;
michael@0 829 password += letters.charAt(i = j - 1);
michael@0 830 }
michael@0 831 }
michael@0 832
michael@0 833 if ((!numeric) && (!gibberish) && mixed) {
michael@0 834 var pwm = '';
michael@0 835 var j;
michael@0 836 for (j = 0; j < password.length; j++) {
michael@0 837 pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase());
michael@0 838 }
michael@0 839 password = pwm;
michael@0 840 }
michael@0 841
michael@0 842 /* If requested, calculate the MD5 signature for this key and
michael@0 843 and save for later appending to the results. */
michael@0 844
michael@0 845 if (makesig) {
michael@0 846 var n, m, hex = "0123456789ABCDEF";
michael@0 847
michael@0 848 init();
michael@0 849 for (m = 0; m < password.length; m++) {
michael@0 850 update(32 + charcodes.indexOf(password.charAt(m)));
michael@0 851 }
michael@0 852 finish();
michael@0 853
michael@0 854 for (n = 0; n < 16; n++) {
michael@0 855 md5v += hex.charAt(digestBits[n] >> 4);
michael@0 856 md5v += hex.charAt(digestBits[n] & 0xF);
michael@0 857 }
michael@0 858 md5v += "\n";
michael@0 859 }
michael@0 860
michael@0 861 aline = "" + line;
michael@0 862 while (aline.length < ndig) {
michael@0 863 aline = " " + aline;
michael@0 864 }
michael@0 865 v += aline + ") " + password;
michael@0 866
michael@0 867 if ((++lineno) >= npline) {
michael@0 868 v += "\n";
michael@0 869 lineno = 0;
michael@0 870 } else {
michael@0 871 v += " ";
michael@0 872 }
michael@0 873 }
michael@0 874
michael@0 875 if (makesig) {
michael@0 876 v += "\n---------- MD5 Signatures ----------\n" + md5v;
michael@0 877 }
michael@0 878
michael@0 879 document.getElementById('onetime').pad.value = v;
michael@0 880 window.status = "Done.";
michael@0 881 }
michael@0 882
michael@0 883 function loadHandler() {
michael@0 884 for (var i = 0; i < 25; i++) {
michael@0 885 gen();
michael@0 886 }
michael@0 887 };
michael@0 888
michael@0 889 //]]>
michael@0 890 </script>
michael@0 891
michael@0 892 </head>
michael@0 893
michael@0 894 <body class="jsgen" onload="loadHandler();">
michael@0 895
michael@0 896 <h1><img src="key.gif" class="keyicon" alt=""
michael@0 897 width="40" height="40" /> &nbsp; One-Time Pad Generator</h1>
michael@0 898
michael@0 899 <p>
michael@0 900 This page, which requires that your browser support JavaScript
michael@0 901 (see <a href="#why"><cite>Why JavaScript</cite></a> below),
michael@0 902 generates one-time pads or password lists in a variety of
michael@0 903 forms. It is based a high-quality pseudorandom sequence
michael@0 904 generator, which can be seeded either from the current date
michael@0 905 and time, or from a seed you provide. Fill in the form below
michael@0 906 to select the format of the pad and press &ldquo;Generate&rdquo; to
michael@0 907 create the pad in the text box. You can then copy and paste
michael@0 908 the generated pad into another window to use as you wish.
michael@0 909 Each of the labels on the request form is linked to a description
michael@0 910 of that parameter.
michael@0 911 </p>
michael@0 912
michael@0 913 <form id="onetime" action="#" onsubmit="return false;">
michael@0 914
michael@0 915 <p class="centre">
michael@0 916 <b>Output:</b>
michael@0 917 <a href="#NumberOfKeys">Number of keys</a>: <input type="text" name="nkeys" value="20" size="4" maxlength="12" />
michael@0 918 <a href="#LineLength">Line length</a>: <input type="text" name="linelen" value="48" size="3" maxlength="12" />
michael@0 919 <br />
michael@0 920 <b>Format:</b>
michael@0 921 <a href="#KeyLength">Key length</a>: <input type="text" name="klength" value="8" size="3" maxlength="12" />
michael@0 922 <a href="#GroupLength">Group length</a>: <input type="text" name="sep" value="4" size="2" maxlength="12" />
michael@0 923
michael@0 924 <br />
michael@0 925 <b>Composition:</b>
michael@0 926 <a href="#KeyText">Key text</a>: <input type="radio" name="keytype" /> Numeric
michael@0 927 <input type="radio" name="keytype" /> Word-like
michael@0 928 <input type="radio" name="keytype" checked="checked" /> Alphabetic
michael@0 929 <input type="radio" name="keytype" /> Gibberish
michael@0 930 <br />
michael@0 931 <a href="#LetterCase">Letters:</a>
michael@0 932 <select size="i" name="textcase">
michael@0 933
michael@0 934 <option value="1" selected="selected">Lower case</option>
michael@0 935 <option value="2">Upper case</option>
michael@0 936 <option value="3">Mixed case</option>
michael@0 937 </select>
michael@0 938
michael@0 939 <input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a>
michael@0 940 <input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a>
michael@0 941
michael@0 942 <br />
michael@0 943 <b><a href="#Seed">Seed:</a></b>
michael@0 944 <input type="radio" name="seedy" checked="checked" /> From clock
michael@0 945 <input type="radio" name="seedy" /> User-defined:
michael@0 946 <input type="text" name="seeder" value="" size="12" maxlength="128"
michael@0 947 onchange="document.getElementById('onetime').seedy[1].checked=true;" />
michael@0 948 <br />
michael@0 949 <input type="button" value=" Generate " onclick="gen();" />
michael@0 950 &nbsp;
michael@0 951 <input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" />
michael@0 952 &nbsp;
michael@0 953 <input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br />
michael@0 954 <textarea name="pad" rows="12" cols="72">
michael@0 955
michael@0 956 Uh, oh. It appears your browser either does not support
michael@0 957 JavaScript or that JavaScript has been disabled. You'll
michael@0 958 have to replace your browser with one supporting JavaScript
michael@0 959 (or enable it, if that's the problem) before you can use
michael@0 960 this page.
michael@0 961 </textarea>
michael@0 962 </p>
michael@0 963
michael@0 964 </form>
michael@0 965
michael@0 966 <script type="text/javascript">
michael@0 967 //<![CDATA[
michael@0 968 // Clear out "sorry, no JavaScript" message from text box.
michael@0 969 document.getElementById('onetime').pad.value = "";
michael@0 970 //]]>
michael@0 971 </script>
michael@0 972
michael@0 973 <h2><a name="details">Details</a></h2>
michael@0 974
michael@0 975 <p>
michael@0 976 Each of the fields in the one-time pad request form is described
michael@0 977 below.
michael@0 978 </p>
michael@0 979
michael@0 980 <h3><a name="output">Output</a></h3>
michael@0 981
michael@0 982 <h4><a name="NumberOfKeys">Number of keys</a></h4>
michael@0 983
michael@0 984 <p>
michael@0 985 Enter the number of keys you'd like to generate. If you generate
michael@0 986 more than fit in the results text box, you can use the scroll
michael@0 987 bar to view the additional lines.
michael@0 988 </p>
michael@0 989
michael@0 990 <h4><a name="LineLength">Line length</a></h4>
michael@0 991
michael@0 992 <p>
michael@0 993 Lines in the output will be limited to the given length (or contain
michael@0 994 only one key if the line length is less than required for a single
michael@0 995 key). If the line length is greater than the width of the results
michael@0 996 box, you can use the horizontal scroll bar to view the rest of the
michael@0 997 line. Enter <tt>0</tt> to force one key per line; this is handy
michael@0 998 when you're preparing a list of keys to be read by a computer program.
michael@0 999 </p>
michael@0 1000
michael@0 1001 <h3><a name="format">Format</a></h3>
michael@0 1002
michael@0 1003 <h4><a name="KeyLength">Key length</a></h4>
michael@0 1004
michael@0 1005 <p>
michael@0 1006 Each key will contain this number of characters, not counting
michael@0 1007 separators between groups.
michael@0 1008 </p>
michael@0 1009
michael@0 1010 <h4><a name="GroupLength">Group length</a></h4>
michael@0 1011
michael@0 1012 <p>
michael@0 1013 If a nonzero value is entered in this field, the key will be broken
michael@0 1014 into groups of the given number of characters by separators. Humans
michael@0 1015 find it easier to read and remember sequences of characters when
michael@0 1016 divided into groups of five or fewer characters.
michael@0 1017 </p>
michael@0 1018
michael@0 1019 <h3><a name="composition">Composition</a></h3>
michael@0 1020
michael@0 1021 <h4><a name="KeyText">Key text</a></h4>
michael@0 1022
michael@0 1023 <p>
michael@0 1024 This set of radio buttons lets you select the character set used in
michael@0 1025 the keys. The alternatives are listed in order of
michael@0 1026 increasing security.
michael@0 1027 </p>
michael@0 1028
michael@0 1029 <blockquote>
michael@0 1030 <dl>
michael@0 1031 <dt><b>Numeric</b></dt>
michael@0 1032 <dd>Keys contain only the decimal digits &ldquo;0&rdquo; through &ldquo;9&rdquo;.
michael@0 1033 <em>Least secure.</em></dd>
michael@0 1034
michael@0 1035 <dt><b>Word-like</b></dt>
michael@0 1036 <dd>Keys are composed of alphabetic characters which obey the
michael@0 1037 digraph statistics of English text. Such keys contain
michael@0 1038 sequences of vowels and consonants familiar to speakers
michael@0 1039 of Western languages, and are therefore usually easier to
michael@0 1040 memorise but, for a given key length, are less secure than
michael@0 1041 purely random letters.</dd>
michael@0 1042
michael@0 1043 <dt><b>Alphabetic</b></dt>
michael@0 1044 <dd>Keys consist of letters of the alphabet chosen at random.
michael@0 1045 Each character has an equal probability of being one of
michael@0 1046 the 26 letters.</dd>
michael@0 1047
michael@0 1048 <dt><b>Gibberish</b></dt>
michael@0 1049 <dd>Keys use most of the printable ASCII character set, excluding
michael@0 1050 only characters frequently used for quoting purposes. This
michael@0 1051 option provides the greatest security for a given key length,
michael@0 1052 but most people find keys like this difficult to memorise or
michael@0 1053 even transcribe from a printed pad. If a human is in the loop,
michael@0 1054 it's often better to use a longer alphabetic or word-like key.
michael@0 1055 <em>Most secure.</em></dd>
michael@0 1056 </dl>
michael@0 1057
michael@0 1058 </blockquote>
michael@0 1059
michael@0 1060 <h4><a name="LetterCase">Letters</a></h4>
michael@0 1061
michael@0 1062 <p>
michael@0 1063 The case of letters in keys generated with Word-like, Alphabetic, and
michael@0 1064 Gibberish key text will be as chosen. Most people find it easier to
michael@0 1065 read lower case letters than all capitals, but for some applications
michael@0 1066 (for example, where keys must be scanned optically by hardware that
michael@0 1067 only recognises capital letters), capitals are required. Selecting
michael@0 1068 &ldquo;Mixed&nbsp;case&rdquo; creates keys with a mix of upper- and
michael@0 1069 lower-case letters; such keys are more secure than those with uniform
michael@0 1070 letter case, but do not pass the &ldquo;telephone test&rdquo;: you
michael@0 1071 can't read them across a (hopefully secure) voice link without having
michael@0 1072 to indicate whether each letter is or is not a capital.
michael@0 1073 </p>
michael@0 1074
michael@0 1075 <h4><a name="RandomSep">Random separators</a></h4>
michael@0 1076
michael@0 1077 <p>
michael@0 1078 When the <a href="#KeyLength">Key length</a> is longer than
michael@0 1079 a nonzero <a href="#GroupLength">Group length</a> specification,
michael@0 1080 the key is divided into sequences of the given group length
michael@0 1081 by separator characters. By default, a hyphen, &ldquo;<tt>-</tt>&rdquo;, is used
michael@0 1082 to separate groups. If you check this box, separators will be
michael@0 1083 chosen at random among punctuation marks generally acceptable
michael@0 1084 for applications such as passwords. If you're generating passwords
michael@0 1085 for a computer system, random separators dramatically increase
michael@0 1086 the difficulty of guessing passwords by exhaustive search.
michael@0 1087 </p>
michael@0 1088
michael@0 1089 <h4><a name="Signatures">Include signatures</a></h4>
michael@0 1090
michael@0 1091 <p>
michael@0 1092
michael@0 1093 When this box is checked, at the end of the list of keys, preceded by
michael@0 1094 a line beginning with ten dashes &ldquo;<tt>-</tt>&rdquo;, the 128 bit MD5 signature of
michael@0 1095 each key is given, one per line, with signatures expressed as 32
michael@0 1096 hexadecimal digits. Key signatures can be used to increase security
michael@0 1097 when keys are used to control access to computer systems or databases.
michael@0 1098 Instead of storing a copy of the keys, the computer stores their
michael@0 1099 signatures. When the user enters a key, its signature is computed
michael@0 1100 with the same MD5 algorithm used to generate it initially, and the key
michael@0 1101 is accepted only if the signature matches. Since discovering
michael@0 1102 a key which will generate a given signature is believed to be
michael@0 1103 computationally prohibitive, even if the list of signatures stored on
michael@0 1104 the computer is compromised, that information will not permit an
michael@0 1105 intruder to deduce a valid key.
michael@0 1106 </p>
michael@0 1107
michael@0 1108 <p>
michael@0 1109 Signature calculation is a computationally intense process for which
michael@0 1110 JavaScript is not ideally suited; be patient while signatures are
michael@0 1111 generated, especially if your computer has modest
michael@0 1112 processing speed.
michael@0 1113 </p>
michael@0 1114
michael@0 1115 <p>
michael@0 1116 For signature-based validation to be secure, it is essential
michael@0 1117 the original keys be long enough to prohibit discovery of matching
michael@0 1118 signatures by exhaustive search. Suppose, for example, one used
michael@0 1119 four digit numeric keys, as used for Personal Identification
michael@0 1120 Numbers (PINs) by many credit card systems. Since only 10,000
michael@0 1121 different keys exist, one could simply compute the signatures of
michael@0 1122 every possible key from 0000 through 9999, permitting an attacker who
michael@0 1123 came into possession of the table of signatures to recover the
michael@0 1124 keys by a simple lookup process. For maximum security, keys must
michael@0 1125 contain at least as much information as the 128 bit signatures
michael@0 1126 computed from them. This implies a minimum key length (not counting
michael@0 1127 non-random separator characters) for the various key formats as
michael@0 1128 follows:
michael@0 1129 </p>
michael@0 1130
michael@0 1131 <table class="c" border="border" cellpadding="4">
michael@0 1132 <tr><th>Key Composition</th> <th>Minimum Characters</th></tr>
michael@0 1133
michael@0 1134 <tr><td>Numeric</td> <td class="c">39</td></tr>
michael@0 1135 <tr><td>Word-like</td> <td class="c">30</td></tr>
michael@0 1136 <tr><td>Alphabetic</td> <td class="c">28</td></tr>
michael@0 1137 <tr><td>Gibberish</td> <td class="c">20</td></tr>
michael@0 1138 </table>
michael@0 1139
michael@0 1140 <p>
michael@0 1141 It should be noted that for many practical applications there is no
michael@0 1142 need for anything approaching 128-bit security. The guidelines above
michael@0 1143 apply only in the case where maximum protection in the event of
michael@0 1144 undetected compromise of key signatures occurs. In many
michael@0 1145 cases, much shorter keys are acceptable, especially when it is assumed
michael@0 1146 that a compromise of the system's password or signature database would
michael@0 1147 be only part of a much more serious subversion of all resources
michael@0 1148 on the system.
michael@0 1149 </p>
michael@0 1150
michael@0 1151 <h3><a name="Seed">Seed</a></h3>
michael@0 1152
michael@0 1153 <p>
michael@0 1154 The <em>seed</em> is the starting value which determines all
michael@0 1155 subsequent values in the pseudorandom sequence used to generate
michael@0 1156 the one-time pad. Given the seed, the pad can be reproduced. The
michael@0 1157 seed is a 31-bit number which can be derived from the date and
michael@0 1158 time at which the one-time pad was requested, or from a
michael@0 1159 user-defined seed value. If the user-defined seed consists
michael@0 1160 entirely of decimal digits, it is used directly as the seed,
michael@0 1161 modulo 2<sup>31</sup>; if a string containing non-digit characters
michael@0 1162 is entered, it is used to compute a <em>hash code</em> which is
michael@0 1163 used to seed the generator.
michael@0 1164
michael@0 1165 </p>
michael@0 1166
michael@0 1167 <p>
michael@0 1168 When the clock is used to create the seed, the seed value is entered
michael@0 1169 in the User-defined box to allow you, by checking &ldquo;User-defined&rdquo;,
michael@0 1170 to produce additional pads with the same seed.
michael@0 1171 </p>
michael@0 1172
michael@0 1173 <h2><a name="why">Why JavaScript?</a></h2>
michael@0 1174
michael@0 1175 <p>
michael@0 1176 At first glance, JavaScript may seem an odd choice for programming
michael@0 1177 a page such as this. The one-time pad generator program is rather
michael@0 1178 large and complicated, and downloading it to your browser takes longer
michael@0 1179 than would be required for a Java applet or to transfer a
michael@0 1180 one-time pad generated by a CGI program on the Web server. I chose
michael@0 1181 JavaScript for two reasons: <em>security</em> and <em>transparency</em>.
michael@0 1182
michael@0 1183 </p>
michael@0 1184
michael@0 1185 <p>
michael@0 1186 <b>Security.</b>
michael@0 1187 The sole reason for the existence of one-time pads is to
michael@0 1188 provide a source of information known only to people to whom
michael@0 1189 they have been distributed in a secure manner. This means
michael@0 1190 the generation process cannot involve any link whose security
michael@0 1191 is suspect. If the pad were generated on a Web server and
michael@0 1192 transmitted to you, it would have to pass over the
michael@0 1193 Internet, where any intermediate site might make a copy
michael@0 1194 of your pad before you even received it. Even if some
michael@0 1195 mechanism such as encryption could absolutely prevent the
michael@0 1196 pad's being intercepted, you'd still have no way to be sure
michael@0 1197 the site generating the pad didn't keep a copy
michael@0 1198 in a file, conveniently tagged with your Internet address.
michael@0 1199 </p>
michael@0 1200
michael@0 1201 <p>
michael@0 1202 In order to have any degree of security, it is essential
michael@0 1203 that the pad be generated on <em>your</em> computer, without
michael@0 1204 involving any transmission or interaction with other
michael@0 1205 sites on the Internet. A Web browser with JavaScript makes
michael@0 1206 this possible, since the generation program embedded in this
michael@0 1207 page runs entirely on your own computer and does not
michael@0 1208 transmit anything over the Internet. Its output appears
michael@0 1209 only in the text box, allowing you to cut and paste it
michael@0 1210 to another application. From there on, its security is
michael@0 1211 up to you.
michael@0 1212 </p>
michael@0 1213
michael@0 1214 <p>
michael@0 1215 Security is never absolute. A one-time pad generated with
michael@0 1216 this page might be compromised in a variety of ways, including
michael@0 1217 the following:
michael@0 1218
michael@0 1219 </p>
michael@0 1220
michael@0 1221 <ul>
michael@0 1222 <li> Your Web browser and/or JavaScript interpreter may
michael@0 1223 contain bugs or deliberate security violations
michael@0 1224 which report activity on your computer back to some
michael@0 1225 other Internet site.</li>
michael@0 1226
michael@0 1227 <li> Some other applet running on another page of your
michael@0 1228 browser, perhaps without your being aware of its
michael@0 1229 existence, is spying on other windows.</li>
michael@0 1230
michael@0 1231 <li> Some other application running on your computer
michael@0 1232 may have compromised your system's security and
michael@0 1233 be snooping on your activity.</li>
michael@0 1234
michael@0 1235 <li> Your Web browser may be keeping a &ldquo;history log&rdquo;
michael@0 1236
michael@0 1237 or &ldquo;cache&rdquo; of data you generate. Somebody may
michael@0 1238 come along later and recover a copy of the pad
michael@0 1239 from that log.</li>
michael@0 1240
michael@0 1241 <li> The implementation of this page may contain a bug
michael@0 1242 or deliberate error which makes its output
michael@0 1243 predictable. This is why <a href="#trans"><cite>transparency</cite></a>,
michael@0 1244 discussed below, is essential.</li>
michael@0 1245
michael@0 1246 <li> Your computer's security may have been compromised
michael@0 1247 physically; when's the last time you checked that a
michael@0 1248 bug that transmits your keystrokes and/or screen
michael@0 1249 contents to that white van parked down the street
michael@0 1250 wasn't lurking inside your computer cabinet?</li>
michael@0 1251 </ul>
michael@0 1252
michael@0 1253 <p>
michael@0 1254 One can whip oneself into a fine fever of paranoia worrying about
michael@0 1255 things like this. One way to rule out the most probable risks
michael@0 1256 is to download a copy of the generator page and run it
michael@0 1257 from a &ldquo;<tt>file:</tt>&rdquo; URL on a computer which has no network
michael@0 1258 connection whatsoever and is located in a secure location
michael@0 1259 under your control. And look very carefully at any files
michael@0 1260 created by your Web browser. You may find the most interesting
michael@0 1261 things squirreled away there&hellip;.
michael@0 1262 </p>
michael@0 1263
michael@0 1264 <p>
michael@0 1265 <b><a name="trans">Transparency</a>.</b>
michael@0 1266 Any security-related tool is only as good as its design
michael@0 1267 and implementation. <em>Transparency</em> means that, in
michael@0 1268 essence, all the moving parts are visible so you can judge
michael@0 1269 for yourself whether the tool merits your confidence. In
michael@0 1270 the case of a program, this means that source code must
michael@0 1271 be available, and that you can verify that the program
michael@0 1272 you're running corresponds to the source code provided.
michael@0 1273
michael@0 1274 </p>
michael@0 1275
michael@0 1276 <p>
michael@0 1277 The very nature of JavaScript achieves this transparency.
michael@0 1278 The program is embedded into this actual Web page; to
michael@0 1279 examine it you need only use your browser's &ldquo;View Source&rdquo;
michael@0 1280 facility, or save the page into a file on your computer
michael@0 1281 and read it with a text editor. JavaScript's being
michael@0 1282 an interpreted language eliminates the risk of your running
michael@0 1283 a program different from the purported source code: with
michael@0 1284 an interpreted language what you read is what you run.
michael@0 1285 </p>
michael@0 1286
michael@0 1287 <p>
michael@0 1288 Transparency is important even if you don't know enough about
michael@0 1289 programming or security to determine whether the program
michael@0 1290 contains any flaws. The very fact that it can be examined
michael@0 1291 by anybody allows those with the required expertise to pass
michael@0 1292 judgment, and you can form your own conclusions based on
michael@0 1293 their analysis.
michael@0 1294 </p>
michael@0 1295
michael@0 1296 <h2>Credits</h2>
michael@0 1297
michael@0 1298 <p>
michael@0 1299
michael@0 1300 The pseudorandom sequence generator is based on L'Ecuyer's
michael@0 1301 two-sequence generator as described in
michael@0 1302 <cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742.
michael@0 1303 A Bays-Durham shuffle is used to guard against regularities
michael@0 1304 lurking in L'Ecuyer's algorithm; see
michael@0 1305 <cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976)
michael@0 1306 pages 59&ndash;64 for details.
michael@0 1307 </p>
michael@0 1308
michael@0 1309 <p>
michael@0 1310 The JavaScript implementation of the
michael@0 1311 <a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a>
michael@0 1312 was developed by Henri Torgemane; please view the source code of this
michael@0 1313 page to examine the code, including the copyright notice and
michael@0 1314 conditions of use. The MD5 algorithm was developed by Ron Rivest.
michael@0 1315 </p>
michael@0 1316
michael@0 1317 <p />
michael@0 1318
michael@0 1319 <hr />
michael@0 1320
michael@0 1321 <p />
michael@0 1322
michael@0 1323 <table class="r">
michael@0 1324 <tr><td align="center">
michael@0 1325 <a class="i" href="http://validator.w3.org/check?uri=referer"><img
michael@0 1326 class="button"
michael@0 1327 src="valid-xhtml10.png"
michael@0 1328 alt="Valid XHTML 1.0" height="31" width="88" /></a>
michael@0 1329 </td></tr>
michael@0 1330 </table>
michael@0 1331
michael@0 1332 <address>
michael@0 1333 by <a href="/">John Walker</a><br />
michael@0 1334 May 26, 1997<br />
michael@0 1335
michael@0 1336 Updated: November 2006
michael@0 1337 </address>
michael@0 1338
michael@0 1339 <p class="centre">
michael@0 1340 <em>This document is in the public domain.</em>
michael@0 1341 </p>
michael@0 1342 </body>
michael@0 1343 </html>
michael@0 1344

mercurial