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