Wed, 31 Dec 2014 06:09:35 +0100
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" /> 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 “Generate” 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 | |
michael@0 | 951 | <input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" /> |
michael@0 | 952 | |
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 “0” through “9”. |
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 | “Mixed case” 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 “telephone test”: 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, “<tt>-</tt>”, 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 “<tt>-</tt>”, 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 “User-defined”, |
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 “history log” |
michael@0 | 1236 | |
michael@0 | 1237 | or “cache” 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 “<tt>file:</tt>” 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…. |
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 “View Source” |
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–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 |