~ubuntu-branches/ubuntu/quantal/enigmail/quantal-security

« back to all changes in this revision

Viewing changes to build/pgo/js-input/crypto-otp.html

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-09-13 16:02:15 UTC
  • mfrom: (0.12.16)
  • Revision ID: package-import@ubuntu.com-20130913160215-u3g8nmwa0pdwagwc
Tags: 2:1.5.2-0ubuntu0.12.10.1
* New upstream release v1.5.2 for Thunderbird 24

* Build enigmail using a stripped down Thunderbird 17 build system, as it's
  now quite difficult to build the way we were doing previously, with the
  latest Firefox build system
* Add debian/patches/no_libxpcom.patch - Don't link against libxpcom, as it
  doesn't exist anymore (but exists in the build system)
* Add debian/patches/use_sdk.patch - Use the SDK version of xpt.py and
  friends
* Drop debian/patches/ipc-pipe_rename.diff (not needed anymore)
* Drop debian/patches/makefile_depth.diff (not needed anymore)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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" /> &nbsp; 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 &ldquo;Generate&rdquo; 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
 
&nbsp;
951
 
<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" />
952
 
&nbsp;
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 &ldquo;0&rdquo; through &ldquo;9&rdquo;.
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
 
&ldquo;Mixed&nbsp;case&rdquo; 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 &ldquo;telephone test&rdquo;: 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, &ldquo;<tt>-</tt>&rdquo;, 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 &ldquo;<tt>-</tt>&rdquo;, 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 &ldquo;User-defined&rdquo;,
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 &ldquo;history log&rdquo;
1236
 
 
1237
 
        or &ldquo;cache&rdquo; 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 &ldquo;<tt>file:</tt>&rdquo; 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&hellip;.
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 &ldquo;View Source&rdquo;
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&ndash;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