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">
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">
12
background-color: inherit;
13
color: rgb(0%, 0%, 80%);
14
text-decoration: none;
18
background-color: rgb(30%, 30%, 100%);
19
color: rgb(100%, 100%, 100%);
23
color: rgb(100%, 0%, 0%);
24
background-color: rgb(30%, 30%, 100%);
27
a.i:link, a.i:visited, a.i:hover {
28
background-color: inherit;
30
text-decoration: none;
36
background-color: #FFFFFF;
51
vertical-align: middle;
55
vertical-align: bottom;
71
background-color: #E0E0E0;
82
background-color: #FFFFD0;
86
<script type="text/javascript">
89
loadTime = (new Date()).getTime();
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
98
Bays, C. and S. D. Durham. ACM Trans. Math. Software: 2 (1976)
101
L'Ecuyer, P. Communications of the ACM: 31 (1968) 742-774.
103
Schrage, L. ACM Trans. Math. Software: 5 (1979) 132-138.
107
function uGen(old, a, q, r, m) { // Schrage's modular multiplication algorithm
110
t = Math.floor(old / q);
111
t = a * (old - (t * q)) - (t * r);
112
return Math.round((t < 0) ? (t + m) : t);
115
function LEnext() { // Return next raw value
118
this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
119
this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
121
/* Extract shuffle table index from most significant part
122
of the previous result. */
124
i = Math.floor(this.state / 67108862);
126
// New state is sum of generators modulo one of their moduli
128
this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
130
// Replace value in shuffle table with generator 1 result
132
this.shuffle[i] = this.gen1;
137
// Return next random integer between 0 and n inclusive
140
return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
143
// Constructor. Called with seed value
145
function LEcuyer(s) {
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);
154
// Fill the shuffle table with values
156
for (i = 0; i < 32; i++) {
157
this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
158
this.shuffle[31 - i] = this.gen1;
160
this.state = this.shuffle[0];
162
this.nextInt = LEnint;
167
var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
168
return seps.charAt(sepran.nextInt(seps.length - 1));
174
* md5.jvs 1.0b 27/06/96
176
* Javascript implementation of the RSA Data Security, Inc. MD5
177
* Message-Digest Algorithm.
179
* Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
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.
186
* Of course, this soft is provided "as is" without express or implied
187
* warranty of any kind.
189
This version contains some trivial reformatting modifications
195
for (i = 0; i < n; i++) {
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!
207
function integer(n) {
208
return n % (0xffffffff + 1);
214
if (a - 0x80000000 >= 0) {
217
a += 0x40000000 >> (b - 1);
226
if (a & 0x40000000 == 0x40000000) {
239
for (var i = 0; i < b; i++) {
248
var t1 = a - 0x80000000;
249
var t2 = b - 0x80000000;
252
return ((t1 & t2) + 0x80000000);
268
var t1 = a - 0x80000000;
269
var t2 = b - 0x80000000;
272
return ((t1 | t2) + 0x80000000);
274
return ((t1 | b) + 0x80000000);
278
return ((a | t2) + 0x80000000);
288
var t1 = a - 0x80000000;
289
var t2 = b - 0x80000000;
294
return ((t1 ^ b) + 0x80000000);
298
return ((a ^ t2) + 0x80000000);
307
return 0xffffffff - a;
310
/* Here begin the real algorithm */
312
var state = new array(4);
313
var count = new array(2);
316
var buffer = new array(64);
317
var transformBuffer = new array(16);
318
var digestBits = new array(16);
337
function F(x, y, z) {
338
return or(and(x, y), and(not(x), z));
341
function G(x, y, z) {
342
return or(and(x, z), and(y, not(z)));
345
function H(x, y, z) {
346
return xor(xor(x, y), z);
349
function I(x, y, z) {
350
return xor(y ,or(x , not(z)));
353
function rotateLeft(a, n) {
354
return or(shl(a, n), (shr(a, (32 - n))));
357
function FF(a, b, c, d, x, s, ac) {
358
a = a + F(b, c, d) + x + ac;
359
a = rotateLeft(a, s);
364
function GG(a, b, c, d, x, s, ac) {
365
a = a + G(b, c, d) + x + ac;
366
a = rotateLeft(a, s);
371
function HH(a, b, c, d, x, s, ac) {
372
a = a + H(b, c, d) + x + ac;
373
a = rotateLeft(a, s);
378
function II(a, b, c, d, x, s, ac) {
379
a = a + I(b, c, d) + x + ac;
380
a = rotateLeft(a, s);
385
function transform(buf, offset) {
386
var a = 0, b = 0, c = 0, d = 0;
387
var x = transformBuffer;
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);
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 */
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 */
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 */
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 */
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++) {
494
index = and(shr(count[0],3) , 0x3F);
495
if (count[0] < 0xFFFFFFFF - 7) {
499
count[0] -= 0xFFFFFFFF + 1;
502
buffer[index] = and(b, 0xff);
504
transform(buffer, 0);
509
var bits = new array(8);
511
var i = 0, index = 0, padLen = 0;
513
for (i = 0; i < 4; i++) {
514
bits[i] = and(shr(count[0], (i * 8)), 0xFF);
516
for (i = 0; i < 4; i++) {
517
bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
519
index = and(shr(count[0], 3), 0x3F);
520
padLen = (index < 56) ? (56 - index) : (120 - index);
521
padding = new array(64);
523
for (i = 0; i < padLen; i++) {
526
for (i = 0; i < 8; i++) {
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);
537
/* End of the MD5 algorithm */
540
window.status = "Generating...";
541
document.getElementById('onetime').pad.value = "";
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;
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
559
"!\"#$%&'()*+,-./0123456789:;<=>?" +
560
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
561
"`abcdefghijklmnopqrstuvwxyz{|}~";
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. */
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);
580
seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next();
583
document.getElementById('onetime').seeder.value = seed;
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. */
592
useed = document.getElementById('onetime').seeder.value;
594
for (i = 0; i < useed.length; i++) {
595
if ("0123456789".indexOf(useed.charAt(i)) == -1) {
601
seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31));
602
document.getElementById('onetime').seeder.value = seed;
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);
616
for (i = 0; i < useed.length; i++) {
617
t = iso.indexOf(useed.charAt(i));
621
s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t);
626
ran1 = new LEcuyer(seed);
627
ran2 = new LEcuyer(seed);
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);
641
pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0);
647
npline = Math.floor(linelen / pw_item);
655
letters = "abcdefghijklmnopqrstuvwxyz";
657
letters = letters.toUpperCase();
661
// Frequency of English digraphs (from D. Edwards 1/27/66)
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,
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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,
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 */
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 */
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 */
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 */
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 */
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 */
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 */ );
750
// This MUST be equal to the sum of the equivalent rows above.
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
758
// Frequencies of starting characters.
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
766
// This MUST be equal to the sum of all elements in the above array.
771
gibber = "abcdefghijklmnopqrstuvwxyz" +
772
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
774
"!#$%&()*+,-./:;<=>?@[]^_{|}~";
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();
782
gibber = gibber.toLowerCase();
786
for (line = 1; line <= npass; line++) {
789
for (nchars = 0; nchars < pw_length; nchars++) {
790
if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
791
password += sepchar();
793
password += ran1.nextInt(9);
795
} else if (!english) {
796
for (nchars = 0; nchars < pw_length; nchars++) {
797
if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
798
password += sepchar();
801
password += gibber.charAt(ran1.nextInt(gibber.length - 1));
803
password += letters.charAt(ran1.nextInt(25));
807
position = ran1.nextInt(total_sum - 1);
808
for (row_position = 0, j = 0; position >= row_position;
809
row_position += start_freq[j], j++) {
813
password = letters.charAt(i = j - 1);
815
for (nchars = pw_length - 1; nchars; --nchars) {
817
// Now find random position within the row.
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++) {
825
if ((sep > 0) && ((nch % sep) == 0)) {
826
password += sepchar();
829
password += letters.charAt(i = j - 1);
833
if ((!numeric) && (!gibberish) && mixed) {
836
for (j = 0; j < password.length; j++) {
837
pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase());
842
/* If requested, calculate the MD5 signature for this key and
843
and save for later appending to the results. */
846
var n, m, hex = "0123456789ABCDEF";
849
for (m = 0; m < password.length; m++) {
850
update(32 + charcodes.indexOf(password.charAt(m)));
854
for (n = 0; n < 16; n++) {
855
md5v += hex.charAt(digestBits[n] >> 4);
856
md5v += hex.charAt(digestBits[n] & 0xF);
862
while (aline.length < ndig) {
865
v += aline + ") " + password;
867
if ((++lineno) >= npline) {
876
v += "\n---------- MD5 Signatures ----------\n" + md5v;
879
document.getElementById('onetime').pad.value = v;
880
window.status = "Done.";
883
function loadHandler() {
884
for (var i = 0; i < 25; i++) {
894
<body class="jsgen" onload="loadHandler();">
896
<h1><img src="key.gif" class="keyicon" alt=""
897
width="40" height="40" /> One-Time Pad Generator</h1>
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
913
<form id="onetime" action="#" onsubmit="return false;">
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" />
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" />
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
931
<a href="#LetterCase">Letters:</a>
932
<select size="i" name="textcase">
934
<option value="1" selected="selected">Lower case</option>
935
<option value="2">Upper case</option>
936
<option value="3">Mixed case</option>
939
<input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a>
940
<input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a>
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;" />
949
<input type="button" value=" Generate " onclick="gen();" />
951
<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" />
953
<input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br />
954
<textarea name="pad" rows="12" cols="72">
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
966
<script type="text/javascript">
968
// Clear out "sorry, no JavaScript" message from text box.
969
document.getElementById('onetime').pad.value = "";
973
<h2><a name="details">Details</a></h2>
976
Each of the fields in the one-time pad request form is described
980
<h3><a name="output">Output</a></h3>
982
<h4><a name="NumberOfKeys">Number of keys</a></h4>
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.
990
<h4><a name="LineLength">Line length</a></h4>
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.
1001
<h3><a name="format">Format</a></h3>
1003
<h4><a name="KeyLength">Key length</a></h4>
1006
Each key will contain this number of characters, not counting
1007
separators between groups.
1010
<h4><a name="GroupLength">Group length</a></h4>
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.
1019
<h3><a name="composition">Composition</a></h3>
1021
<h4><a name="KeyText">Key text</a></h4>
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.
1031
<dt><b>Numeric</b></dt>
1032
<dd>Keys contain only the decimal digits “0” through “9”.
1033
<em>Least secure.</em></dd>
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>
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>
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>
1060
<h4><a name="LetterCase">Letters</a></h4>
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.
1075
<h4><a name="RandomSep">Random separators</a></h4>
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.
1089
<h4><a name="Signatures">Include signatures</a></h4>
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.
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
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
1131
<table class="c" border="border" cellpadding="4">
1132
<tr><th>Key Composition</th> <th>Minimum Characters</th></tr>
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>
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
1151
<h3><a name="Seed">Seed</a></h3>
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.
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.
1173
<h2><a name="why">Why JavaScript?</a></h2>
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>.
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.
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
1215
Security is never absolute. A one-time pad generated with
1216
this page might be compromised in a variety of ways, including
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>
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>
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>
1235
<li> Your Web browser may be keeping a “history log”
1237
or “cache” of data you generate. Somebody may
1238
come along later and recover a copy of the pad
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>
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>
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….
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.
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.
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
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.
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.
1324
<tr><td align="center">
1325
<a class="i" href="http://validator.w3.org/check?uri=referer"><img
1327
src="valid-xhtml10.png"
1328
alt="Valid XHTML 1.0" height="31" width="88" /></a>
1333
by <a href="/">John Walker</a><br />
1336
Updated: November 2006
1340
<em>This document is in the public domain.</em>