diff options
Diffstat (limited to 'build/pgo/js-input/crypto-otp.html')
-rw-r--r-- | build/pgo/js-input/crypto-otp.html | 1344 |
1 files changed, 1344 insertions, 0 deletions
diff --git a/build/pgo/js-input/crypto-otp.html b/build/pgo/js-input/crypto-otp.html new file mode 100644 index 000000000..f6e1ca295 --- /dev/null +++ b/build/pgo/js-input/crypto-otp.html @@ -0,0 +1,1344 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<title>One-Time Pad Generator</title> +<meta name="description" content="JavaScript One-Time Pad Generator" /> +<meta name="author" content="John Walker" /> +<meta name="keywords" content="one, time, pad, generator, onetime, cryptography, JavaScript" /> +<style type="text/css"> + a:link, a:visited { + background-color: inherit; + color: rgb(0%, 0%, 80%); + text-decoration: none; + } + + a:hover { + background-color: rgb(30%, 30%, 100%); + color: rgb(100%, 100%, 100%); + } + + a:active { + color: rgb(100%, 0%, 0%); + background-color: rgb(30%, 30%, 100%); + } + + a.i:link, a.i:visited, a.i:hover { + background-color: inherit; + color: inherit; + text-decoration: none; + } + + body { + margin-left: 15%; + margin-right: 10%; + background-color: #FFFFFF; + color: #000000; + } + + body.jsgen { + margin-left: 5%; + margin-right: 5%; + } + + dt { + margin-top: 0.5em; + } + + img.button { + border: 0px; + vertical-align: middle; + } + + img.keyicon { + vertical-align: bottom; + } + + p, dd, li { + text-align: justify; + } + + p.centre { + text-align: center; + } + + table.r { + float: right; + } + + table.c { + background-color: #E0E0E0; + color: #000000; + margin-left: auto; + margin-right: auto; + } + + td.c { + text-align: center; + } + + textarea { + background-color: #FFFFD0; + color: #000000; + } +</style> +<script type="text/javascript"> +//<![CDATA[ + + loadTime = (new Date()).getTime(); + +/* + + L'Ecuyer's two-sequence generator with a Bays-Durham shuffle + on the back-end. Schrage's algorithm is used to perform + 64-bit modular arithmetic within the 32-bit constraints of + JavaScript. + + Bays, C. and S. D. Durham. ACM Trans. Math. Software: 2 (1976) + 59-64. + + L'Ecuyer, P. Communications of the ACM: 31 (1968) 742-774. + + Schrage, L. ACM Trans. Math. Software: 5 (1979) 132-138. + +*/ + +function uGen(old, a, q, r, m) { // Schrage's modular multiplication algorithm + var t; + + t = Math.floor(old / q); + t = a * (old - (t * q)) - (t * r); + return Math.round((t < 0) ? (t + m) : t); +} + +function LEnext() { // Return next raw value + var i; + + this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563); + this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399); + + /* Extract shuffle table index from most significant part + of the previous result. */ + + i = Math.floor(this.state / 67108862); + + // New state is sum of generators modulo one of their moduli + + this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563); + + // Replace value in shuffle table with generator 1 result + + this.shuffle[i] = this.gen1; + + return this.state; +} + +// Return next random integer between 0 and n inclusive + +function LEnint(n) { + return Math.floor(this.next() / (1 + 2147483562 / (n + 1))); +} + +// Constructor. Called with seed value + +function LEcuyer(s) { + var i; + + this.shuffle = new Array(32); + this.gen1 = this.gen2 = (s & 0x7FFFFFFF); + for (i = 0; i < 19; i++) { + this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563); + } + + // Fill the shuffle table with values + + for (i = 0; i < 32; i++) { + this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563); + this.shuffle[31 - i] = this.gen1; + } + this.state = this.shuffle[0]; + this.next = LEnext; + this.nextInt = LEnint; +} + +function sepchar() { + if (rsep) { + var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~"; + return seps.charAt(sepran.nextInt(seps.length - 1)); + } + return "-"; +} + +/* + * md5.jvs 1.0b 27/06/96 + * + * Javascript implementation of the RSA Data Security, Inc. MD5 + * Message-Digest Algorithm. + * + * Copyright (c) 1996 Henri Torgemane. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + + This version contains some trivial reformatting modifications + by John Walker. + + */ + +function array(n) { + for (i = 0; i < n; i++) { + this[i] = 0; + } + this.length = n; +} + +/* Some basic logical functions had to be rewritten because of a bug in + * Javascript.. Just try to compute 0xffffffff >> 4 with it.. + * Of course, these functions are slower than the original would be, but + * at least, they work! + */ + +function integer(n) { + return n % (0xffffffff + 1); +} + +function shr(a, b) { + a = integer(a); + b = integer(b); + if (a - 0x80000000 >= 0) { + a = a % 0x80000000; + a >>= b; + a += 0x40000000 >> (b - 1); + } else { + a >>= b; + } + return a; +} + +function shl1(a) { + a = a % 0x80000000; + if (a & 0x40000000 == 0x40000000) { + a -= 0x40000000; + a *= 2; + a += 0x80000000; + } else { + a *= 2; + } + return a; +} + +function shl(a, b) { + a = integer(a); + b = integer(b); + for (var i = 0; i < b; i++) { + a = shl1(a); + } + return a; +} + +function and(a, b) { + a = integer(a); + b = integer(b); + var t1 = a - 0x80000000; + var t2 = b - 0x80000000; + if (t1 >= 0) { + if (t2 >= 0) { + return ((t1 & t2) + 0x80000000); + } else { + return (t1 & b); + } + } else { + if (t2 >= 0) { + return (a & t2); + } else { + return (a & b); + } + } +} + +function or(a, b) { + a = integer(a); + b = integer(b); + var t1 = a - 0x80000000; + var t2 = b - 0x80000000; + if (t1 >= 0) { + if (t2 >= 0) { + return ((t1 | t2) + 0x80000000); + } else { + return ((t1 | b) + 0x80000000); + } + } else { + if (t2 >= 0) { + return ((a | t2) + 0x80000000); + } else { + return (a | b); + } + } +} + +function xor(a, b) { + a = integer(a); + b = integer(b); + var t1 = a - 0x80000000; + var t2 = b - 0x80000000; + if (t1 >= 0) { + if (t2 >= 0) { + return (t1 ^ t2); + } else { + return ((t1 ^ b) + 0x80000000); + } + } else { + if (t2 >= 0) { + return ((a ^ t2) + 0x80000000); + } else { + return (a ^ b); + } + } +} + +function not(a) { + a = integer(a); + return 0xffffffff - a; +} + +/* Here begin the real algorithm */ + +var state = new array(4); +var count = new array(2); + count[0] = 0; + count[1] = 0; +var buffer = new array(64); +var transformBuffer = new array(16); +var digestBits = new array(16); + +var S11 = 7; +var S12 = 12; +var S13 = 17; +var S14 = 22; +var S21 = 5; +var S22 = 9; +var S23 = 14; +var S24 = 20; +var S31 = 4; +var S32 = 11; +var S33 = 16; +var S34 = 23; +var S41 = 6; +var S42 = 10; +var S43 = 15; +var S44 = 21; + +function F(x, y, z) { + return or(and(x, y), and(not(x), z)); +} + +function G(x, y, z) { + return or(and(x, z), and(y, not(z))); +} + +function H(x, y, z) { + return xor(xor(x, y), z); +} + +function I(x, y, z) { + return xor(y ,or(x , not(z))); +} + +function rotateLeft(a, n) { + return or(shl(a, n), (shr(a, (32 - n)))); +} + +function FF(a, b, c, d, x, s, ac) { + a = a + F(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function GG(a, b, c, d, x, s, ac) { + a = a + G(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function HH(a, b, c, d, x, s, ac) { + a = a + H(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function II(a, b, c, d, x, s, ac) { + a = a + I(b, c, d) + x + ac; + a = rotateLeft(a, s); + a = a + b; + return a; +} + +function transform(buf, offset) { + var a = 0, b = 0, c = 0, d = 0; + var x = transformBuffer; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + for (i = 0; i < 16; i++) { + x[i] = and(buf[i * 4 + offset], 0xFF); + for (j = 1; j < 4; j++) { + x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8); + } + } + + /* Round 1 */ + a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + +} + +function init() { + count[0] = count[1] = 0; + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + for (i = 0; i < digestBits.length; i++) { + digestBits[i] = 0; + } +} + +function update(b) { + var index, i; + + index = and(shr(count[0],3) , 0x3F); + if (count[0] < 0xFFFFFFFF - 7) { + count[0] += 8; + } else { + count[1]++; + count[0] -= 0xFFFFFFFF + 1; + count[0] += 8; + } + buffer[index] = and(b, 0xff); + if (index >= 63) { + transform(buffer, 0); + } +} + +function finish() { + var bits = new array(8); + var padding; + var i = 0, index = 0, padLen = 0; + + for (i = 0; i < 4; i++) { + bits[i] = and(shr(count[0], (i * 8)), 0xFF); + } + for (i = 0; i < 4; i++) { + bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF); + } + index = and(shr(count[0], 3), 0x3F); + padLen = (index < 56) ? (56 - index) : (120 - index); + padding = new array(64); + padding[0] = 0x80; + for (i = 0; i < padLen; i++) { + update(padding[i]); + } + for (i = 0; i < 8; i++) { + update(bits[i]); + } + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF); + } + } +} + +/* End of the MD5 algorithm */ + +function gen() { + window.status = "Generating..."; + document.getElementById('onetime').pad.value = ""; + + lower = document.getElementById('onetime').textcase.selectedIndex == 0; + upper = document.getElementById('onetime').textcase.selectedIndex == 1; + mixed = document.getElementById('onetime').textcase.selectedIndex == 2; + rsep = document.getElementById('onetime').rsep.checked; + if (!(numeric = document.getElementById('onetime').keytype[0].checked)) { + english = document.getElementById('onetime').keytype[1].checked; + gibberish = document.getElementById('onetime').keytype[3].checked; + } + clockseed = document.getElementById('onetime').seedy[0].checked + makesig = document.getElementById('onetime').dosig.checked; + npass = document.getElementById('onetime').nkeys.value; + pw_length = Math.round(document.getElementById('onetime').klength.value); + sep = document.getElementById('onetime').sep.value; + linelen = document.getElementById('onetime').linelen.value; +// 01234567890123456789012345678901 + charcodes = " " + + "!\"#$%&'()*+,-./0123456789:;<=>?" + + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + + "`abcdefghijklmnopqrstuvwxyz{|}~"; + + if (clockseed) { + var n, j, ran0; + + /* Obtain seed from the clock. To reduce the likelihood + of the seed being guessed, we create the seed by combining + the time of the request with the time the page was loaded, + then use that composite value to seed an auxiliary generator + which is cycled between one and 32 times based on the time + derived initial seed, with the output of the generator fed + back into the seed we use to generate the pad. */ + + seed = Math.round((new Date()).getTime() % Math.pow(2, 31)); + ran0 = new LEcuyer((seed ^ Math.round(loadTime % Math.pow(2, 31))) & 0x7FFFFFFF); + for (j = 0; j < (5 + ((seed >> 3) & 0xF)); j++) { + n = ran0.nextInt(31); + } + while (n-- >= 0) { + seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next(); + } + seed &= 0x7FFFFFFF; + document.getElementById('onetime').seeder.value = seed; + } else { + var useed, seedNum; + + /* Obtain seed from user specification. If the seed is a + decimal number, use it as-is. If it contains any + non-numeric characters, construct a hash code and + use that as the seed. */ + + useed = document.getElementById('onetime').seeder.value; + seedNum = true; + for (i = 0; i < useed.length; i++) { + if ("0123456789".indexOf(useed.charAt(i)) == -1) { + seedNum = false; + break; + } + } + if (seedNum) { + seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31)); + document.getElementById('onetime').seeder.value = seed; + } else { + var s, t, iso, hex; + + iso = ""; + hex = "0123456789ABCDEF"; + for (i = 32; i < 256; i++) { + if (i < 127 || i >= 160) { + // Why not "s = i.toString(16);"? Doesn't work in Netscape 3.0 + iso += "%" + hex.charAt(i >> 4) + hex.charAt(i & 0xF); + } + } + iso = unescape(iso); + s = 0; + for (i = 0; i < useed.length; i++) { + t = iso.indexOf(useed.charAt(i)); + if (t < 0) { + t = 17; + } + s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t); + } + seed = s; + } + } + ran1 = new LEcuyer(seed); + ran2 = new LEcuyer(seed); + if (rsep) { + /* Use a separate random generator for separators + so that results are the same for a given seed + for both choices of separators. */ + sepran = new LEcuyer(seed); + } + + ndig = 1; + j = 10; + while (npass >= j) { + ndig++; + j *= 10; + } + pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0); + pw_item += ndig + 5; + j = pw_item * 3; + if (j < 132) { + j = 132; + } + npline = Math.floor(linelen / pw_item); + if (npline < 1) { + npline = 0; + } + v = ""; + md5v = ""; + lineno = 0; + if (!numeric) { + letters = "abcdefghijklmnopqrstuvwxyz"; + if (upper) { + letters = letters.toUpperCase(); + } + if (english) { + + // Frequency of English digraphs (from D. Edwards 1/27/66) + + frequency = new Array( + new Array(4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62, + 23, 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1, + 9, 1), /* aa - az */ + + new Array(13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0, + 11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0), /* ba - bz */ + + new Array(32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1, + 0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0), /* ca - cz */ + + new Array(40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15, + 6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0), /* da - dz */ + + new Array(84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4, + 55, 54, 146, 35, 37, 6, 191, 149, 65, 9, 26, + 21, 12, 5, 0), /* ea - ez */ + + new Array(19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1, + 0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0), /* fa - fz */ + + new Array(20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1, + 4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0), /* ga - gz */ + + new Array(101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3, + 2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0), /* ha - hz */ + + new Array(40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38, + 25, 202, 56, 12, 1, 46, 79, 117, 1, 22, 0, + 4, 0, 3), /* ia - iz */ + + new Array(3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0), /* ja - jz */ + + new Array(1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0), /* ka - kz */ + + new Array(44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2, + 2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0), /* la - lz */ + + new Array(52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7, + 1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0), /* ma - mz */ + + new Array(42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6, + 6, 9, 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0, + 12, 0), /* na - nz */ + + new Array(7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19, + 41, 134, 13, 23, 0, 91, 23, 42, 55, 16, 28, + 0, 4, 1), /* oa - oz */ + + new Array(19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0, + 27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0), /* pa - pz */ + + new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0), /* qa - qz */ + + new Array(83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5, + 26, 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0, + 28, 0), /* ra - rz */ + + new Array(65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7, + 11, 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0, + 4, 0), /* sa - sz */ + + new Array(57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14, + 10, 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0, + 24, 0), /* ta - tz */ + + new Array(11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31, + 1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0), /* ua - uz */ + + new Array(7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0), /* va - vz */ + + new Array(36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1, + 8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0), /* wa - wz */ + + new Array(1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1, + 5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0), /* xa - xz */ + + new Array(14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7, + 5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0), /* ya - yz */ + + new Array(1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) /* za - zz */ ); + + // This MUST be equal to the sum of the equivalent rows above. + + row_sums = new Array( + 796, 160, 284, 401, 1276, 262, 199, 539, 777, + 16, 39, 351, 243, 751, 662, 181, 17, 683, + 662, 968, 248, 115, 180, 17, 162, 5 + ); + + // Frequencies of starting characters. + + start_freq = new Array( + 1299, 425, 725, 271, 375, 470, 93, 223, 1009, + 24, 20, 355, 379, 319, 823, 618, 21, 317, + 962, 1991, 271, 104, 516, 6, 16, 14 + ); + + // This MUST be equal to the sum of all elements in the above array. + + total_sum = 11646; + } + if (gibberish) { + gibber = "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "0123456789" + + "!#$%&()*+,-./:;<=>?@[]^_{|}~"; + if (upper) { + /* Convert to upper case, leaving two copies of the + alphabet for two reasons: first, to favour letters + over gnarl, and second, to change only the letter case + when the mode is selected. */ + gibber = gibber.toUpperCase(); + } else if (lower) { + gibber = gibber.toLowerCase(); + } + } + } + for (line = 1; line <= npass; line++) { + password = ""; + if (numeric) { + for (nchars = 0; nchars < pw_length; nchars++) { + if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) { + password += sepchar(); + } + password += ran1.nextInt(9); + } + } else if (!english) { + for (nchars = 0; nchars < pw_length; nchars++) { + if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) { + password += sepchar(); + } + if (gibberish) { + password += gibber.charAt(ran1.nextInt(gibber.length - 1)); + } else { + password += letters.charAt(ran1.nextInt(25)); + } + } + } else { + position = ran1.nextInt(total_sum - 1); + for (row_position = 0, j = 0; position >= row_position; + row_position += start_freq[j], j++) { + continue; + } + + password = letters.charAt(i = j - 1); + nch = 1; + for (nchars = pw_length - 1; nchars; --nchars) { + + // Now find random position within the row. + + position = ran1.nextInt(row_sums[i] - 1); + for (row_position = 0, j = 0; + position >= row_position; + row_position += frequency[i][j], j++) { + } + + if ((sep > 0) && ((nch % sep) == 0)) { + password += sepchar(); + } + nch++; + password += letters.charAt(i = j - 1); + } + } + + if ((!numeric) && (!gibberish) && mixed) { + var pwm = ''; + var j; + for (j = 0; j < password.length; j++) { + pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase()); + } + password = pwm; + } + + /* If requested, calculate the MD5 signature for this key and + and save for later appending to the results. */ + + if (makesig) { + var n, m, hex = "0123456789ABCDEF"; + + init(); + for (m = 0; m < password.length; m++) { + update(32 + charcodes.indexOf(password.charAt(m))); + } + finish(); + + for (n = 0; n < 16; n++) { + md5v += hex.charAt(digestBits[n] >> 4); + md5v += hex.charAt(digestBits[n] & 0xF); + } + md5v += "\n"; + } + + aline = "" + line; + while (aline.length < ndig) { + aline = " " + aline; + } + v += aline + ") " + password; + + if ((++lineno) >= npline) { + v += "\n"; + lineno = 0; + } else { + v += " "; + } + } + + if (makesig) { + v += "\n---------- MD5 Signatures ----------\n" + md5v; + } + + document.getElementById('onetime').pad.value = v; + window.status = "Done."; +} + +function loadHandler() { + for (var i = 0; i < 25; i++) { + gen(); + } +}; + +//]]> +</script> + +</head> + +<body class="jsgen" onload="loadHandler();"> + +<h1><img src="key.gif" class="keyicon" alt="" + width="40" height="40" /> One-Time Pad Generator</h1> + +<p> +This page, which requires that your browser support JavaScript +(see <a href="#why"><cite>Why JavaScript</cite></a> below), +generates one-time pads or password lists in a variety of +forms. It is based a high-quality pseudorandom sequence +generator, which can be seeded either from the current date +and time, or from a seed you provide. Fill in the form below +to select the format of the pad and press “Generate” to +create the pad in the text box. You can then copy and paste +the generated pad into another window to use as you wish. +Each of the labels on the request form is linked to a description +of that parameter. +</p> + +<form id="onetime" action="#" onsubmit="return false;"> + +<p class="centre"> +<b>Output:</b> +<a href="#NumberOfKeys">Number of keys</a>: <input type="text" name="nkeys" value="20" size="4" maxlength="12" /> +<a href="#LineLength">Line length</a>: <input type="text" name="linelen" value="48" size="3" maxlength="12" /> +<br /> +<b>Format:</b> +<a href="#KeyLength">Key length</a>: <input type="text" name="klength" value="8" size="3" maxlength="12" /> +<a href="#GroupLength">Group length</a>: <input type="text" name="sep" value="4" size="2" maxlength="12" /> + +<br /> +<b>Composition:</b> +<a href="#KeyText">Key text</a>: <input type="radio" name="keytype" /> Numeric +<input type="radio" name="keytype" /> Word-like +<input type="radio" name="keytype" checked="checked" /> Alphabetic +<input type="radio" name="keytype" /> Gibberish +<br /> +<a href="#LetterCase">Letters:</a> +<select size="i" name="textcase"> + + <option value="1" selected="selected">Lower case</option> + <option value="2">Upper case</option> + <option value="3">Mixed case</option> +</select> + +<input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a> +<input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a> + +<br /> +<b><a href="#Seed">Seed:</a></b> +<input type="radio" name="seedy" checked="checked" /> From clock +<input type="radio" name="seedy" /> User-defined: +<input type="text" name="seeder" value="" size="12" maxlength="128" + onchange="document.getElementById('onetime').seedy[1].checked=true;" /> +<br /> +<input type="button" value=" Generate " onclick="gen();" /> + +<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" /> + +<input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br /> +<textarea name="pad" rows="12" cols="72"> + +Uh, oh. It appears your browser either does not support +JavaScript or that JavaScript has been disabled. You'll +have to replace your browser with one supporting JavaScript +(or enable it, if that's the problem) before you can use +this page. +</textarea> +</p> + +</form> + +<script type="text/javascript"> +//<![CDATA[ + // Clear out "sorry, no JavaScript" message from text box. + document.getElementById('onetime').pad.value = ""; +//]]> +</script> + +<h2><a name="details">Details</a></h2> + +<p> +Each of the fields in the one-time pad request form is described +below. +</p> + +<h3><a name="output">Output</a></h3> + +<h4><a name="NumberOfKeys">Number of keys</a></h4> + +<p> +Enter the number of keys you'd like to generate. If you generate +more than fit in the results text box, you can use the scroll +bar to view the additional lines. +</p> + +<h4><a name="LineLength">Line length</a></h4> + +<p> +Lines in the output will be limited to the given length (or contain +only one key if the line length is less than required for a single +key). If the line length is greater than the width of the results +box, you can use the horizontal scroll bar to view the rest of the +line. Enter <tt>0</tt> to force one key per line; this is handy +when you're preparing a list of keys to be read by a computer program. +</p> + +<h3><a name="format">Format</a></h3> + +<h4><a name="KeyLength">Key length</a></h4> + +<p> +Each key will contain this number of characters, not counting +separators between groups. +</p> + +<h4><a name="GroupLength">Group length</a></h4> + +<p> +If a nonzero value is entered in this field, the key will be broken +into groups of the given number of characters by separators. Humans +find it easier to read and remember sequences of characters when +divided into groups of five or fewer characters. +</p> + +<h3><a name="composition">Composition</a></h3> + +<h4><a name="KeyText">Key text</a></h4> + +<p> +This set of radio buttons lets you select the character set used in +the keys. The alternatives are listed in order of +increasing security. +</p> + +<blockquote> +<dl> +<dt><b>Numeric</b></dt> +<dd>Keys contain only the decimal digits “0” through “9”. + <em>Least secure.</em></dd> + +<dt><b>Word-like</b></dt> +<dd>Keys are composed of alphabetic characters which obey the + digraph statistics of English text. Such keys contain + sequences of vowels and consonants familiar to speakers + of Western languages, and are therefore usually easier to + memorise but, for a given key length, are less secure than + purely random letters.</dd> + +<dt><b>Alphabetic</b></dt> +<dd>Keys consist of letters of the alphabet chosen at random. + Each character has an equal probability of being one of + the 26 letters.</dd> + +<dt><b>Gibberish</b></dt> +<dd>Keys use most of the printable ASCII character set, excluding + only characters frequently used for quoting purposes. This + option provides the greatest security for a given key length, + but most people find keys like this difficult to memorise or + even transcribe from a printed pad. If a human is in the loop, + it's often better to use a longer alphabetic or word-like key. + <em>Most secure.</em></dd> +</dl> + +</blockquote> + +<h4><a name="LetterCase">Letters</a></h4> + +<p> +The case of letters in keys generated with Word-like, Alphabetic, and +Gibberish key text will be as chosen. Most people find it easier to +read lower case letters than all capitals, but for some applications +(for example, where keys must be scanned optically by hardware that +only recognises capital letters), capitals are required. Selecting +“Mixed case” creates keys with a mix of upper- and +lower-case letters; such keys are more secure than those with uniform +letter case, but do not pass the “telephone test”: you +can't read them across a (hopefully secure) voice link without having +to indicate whether each letter is or is not a capital. +</p> + +<h4><a name="RandomSep">Random separators</a></h4> + +<p> +When the <a href="#KeyLength">Key length</a> is longer than +a nonzero <a href="#GroupLength">Group length</a> specification, +the key is divided into sequences of the given group length +by separator characters. By default, a hyphen, “<tt>-</tt>”, is used +to separate groups. If you check this box, separators will be +chosen at random among punctuation marks generally acceptable +for applications such as passwords. If you're generating passwords +for a computer system, random separators dramatically increase +the difficulty of guessing passwords by exhaustive search. +</p> + +<h4><a name="Signatures">Include signatures</a></h4> + +<p> + +When this box is checked, at the end of the list of keys, preceded by +a line beginning with ten dashes “<tt>-</tt>”, the 128 bit MD5 signature of +each key is given, one per line, with signatures expressed as 32 +hexadecimal digits. Key signatures can be used to increase security +when keys are used to control access to computer systems or databases. +Instead of storing a copy of the keys, the computer stores their +signatures. When the user enters a key, its signature is computed +with the same MD5 algorithm used to generate it initially, and the key +is accepted only if the signature matches. Since discovering +a key which will generate a given signature is believed to be +computationally prohibitive, even if the list of signatures stored on +the computer is compromised, that information will not permit an +intruder to deduce a valid key. +</p> + +<p> +Signature calculation is a computationally intense process for which +JavaScript is not ideally suited; be patient while signatures are +generated, especially if your computer has modest +processing speed. +</p> + +<p> +For signature-based validation to be secure, it is essential +the original keys be long enough to prohibit discovery of matching +signatures by exhaustive search. Suppose, for example, one used +four digit numeric keys, as used for Personal Identification +Numbers (PINs) by many credit card systems. Since only 10,000 +different keys exist, one could simply compute the signatures of +every possible key from 0000 through 9999, permitting an attacker who +came into possession of the table of signatures to recover the +keys by a simple lookup process. For maximum security, keys must +contain at least as much information as the 128 bit signatures +computed from them. This implies a minimum key length (not counting +non-random separator characters) for the various key formats as +follows: +</p> + +<table class="c" border="border" cellpadding="4"> +<tr><th>Key Composition</th> <th>Minimum Characters</th></tr> + +<tr><td>Numeric</td> <td class="c">39</td></tr> +<tr><td>Word-like</td> <td class="c">30</td></tr> +<tr><td>Alphabetic</td> <td class="c">28</td></tr> +<tr><td>Gibberish</td> <td class="c">20</td></tr> +</table> + +<p> +It should be noted that for many practical applications there is no +need for anything approaching 128-bit security. The guidelines above +apply only in the case where maximum protection in the event of +undetected compromise of key signatures occurs. In many +cases, much shorter keys are acceptable, especially when it is assumed +that a compromise of the system's password or signature database would +be only part of a much more serious subversion of all resources +on the system. +</p> + +<h3><a name="Seed">Seed</a></h3> + +<p> +The <em>seed</em> is the starting value which determines all +subsequent values in the pseudorandom sequence used to generate +the one-time pad. Given the seed, the pad can be reproduced. The +seed is a 31-bit number which can be derived from the date and +time at which the one-time pad was requested, or from a +user-defined seed value. If the user-defined seed consists +entirely of decimal digits, it is used directly as the seed, +modulo 2<sup>31</sup>; if a string containing non-digit characters +is entered, it is used to compute a <em>hash code</em> which is +used to seed the generator. + +</p> + +<p> +When the clock is used to create the seed, the seed value is entered +in the User-defined box to allow you, by checking “User-defined”, +to produce additional pads with the same seed. +</p> + +<h2><a name="why">Why JavaScript?</a></h2> + +<p> +At first glance, JavaScript may seem an odd choice for programming +a page such as this. The one-time pad generator program is rather +large and complicated, and downloading it to your browser takes longer +than would be required for a Java applet or to transfer a +one-time pad generated by a CGI program on the Web server. I chose +JavaScript for two reasons: <em>security</em> and <em>transparency</em>. + +</p> + +<p> +<b>Security.</b> +The sole reason for the existence of one-time pads is to +provide a source of information known only to people to whom +they have been distributed in a secure manner. This means +the generation process cannot involve any link whose security +is suspect. If the pad were generated on a Web server and +transmitted to you, it would have to pass over the +Internet, where any intermediate site might make a copy +of your pad before you even received it. Even if some +mechanism such as encryption could absolutely prevent the +pad's being intercepted, you'd still have no way to be sure +the site generating the pad didn't keep a copy +in a file, conveniently tagged with your Internet address. +</p> + +<p> +In order to have any degree of security, it is essential +that the pad be generated on <em>your</em> computer, without +involving any transmission or interaction with other +sites on the Internet. A Web browser with JavaScript makes +this possible, since the generation program embedded in this +page runs entirely on your own computer and does not +transmit anything over the Internet. Its output appears +only in the text box, allowing you to cut and paste it +to another application. From there on, its security is +up to you. +</p> + +<p> +Security is never absolute. A one-time pad generated with +this page might be compromised in a variety of ways, including +the following: + +</p> + +<ul> +<li> Your Web browser and/or JavaScript interpreter may + contain bugs or deliberate security violations + which report activity on your computer back to some + other Internet site.</li> + +<li> Some other applet running on another page of your + browser, perhaps without your being aware of its + existence, is spying on other windows.</li> + +<li> Some other application running on your computer + may have compromised your system's security and + be snooping on your activity.</li> + +<li> Your Web browser may be keeping a “history log” + + or “cache” of data you generate. Somebody may + come along later and recover a copy of the pad + from that log.</li> + +<li> The implementation of this page may contain a bug + or deliberate error which makes its output + predictable. This is why <a href="#trans"><cite>transparency</cite></a>, + discussed below, is essential.</li> + +<li> Your computer's security may have been compromised + physically; when's the last time you checked that a + bug that transmits your keystrokes and/or screen + contents to that white van parked down the street + wasn't lurking inside your computer cabinet?</li> +</ul> + +<p> +One can whip oneself into a fine fever of paranoia worrying about +things like this. One way to rule out the most probable risks +is to download a copy of the generator page and run it +from a “<tt>file:</tt>” URL on a computer which has no network +connection whatsoever and is located in a secure location +under your control. And look very carefully at any files +created by your Web browser. You may find the most interesting +things squirreled away there…. +</p> + +<p> +<b><a name="trans">Transparency</a>.</b> +Any security-related tool is only as good as its design +and implementation. <em>Transparency</em> means that, in +essence, all the moving parts are visible so you can judge +for yourself whether the tool merits your confidence. In +the case of a program, this means that source code must +be available, and that you can verify that the program +you're running corresponds to the source code provided. + +</p> + +<p> +The very nature of JavaScript achieves this transparency. +The program is embedded into this actual Web page; to +examine it you need only use your browser's “View Source” +facility, or save the page into a file on your computer +and read it with a text editor. JavaScript's being +an interpreted language eliminates the risk of your running +a program different from the purported source code: with +an interpreted language what you read is what you run. +</p> + +<p> +Transparency is important even if you don't know enough about +programming or security to determine whether the program +contains any flaws. The very fact that it can be examined +by anybody allows those with the required expertise to pass +judgment, and you can form your own conclusions based on +their analysis. +</p> + +<h2>Credits</h2> + +<p> + +The pseudorandom sequence generator is based on L'Ecuyer's +two-sequence generator as described in +<cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742. +A Bays-Durham shuffle is used to guard against regularities +lurking in L'Ecuyer's algorithm; see +<cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976) +pages 59–64 for details. +</p> + +<p> +The JavaScript implementation of the +<a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a> +was developed by Henri Torgemane; please view the source code of this +page to examine the code, including the copyright notice and +conditions of use. The MD5 algorithm was developed by Ron Rivest. +</p> + +<p /> + +<hr /> + +<p /> + +<table class="r"> +<tr><td align="center"> + <a class="i" href="http://validator.w3.org/check?uri=referer"><img + class="button" + src="valid-xhtml10.png" + alt="Valid XHTML 1.0" height="31" width="88" /></a> +</td></tr> +</table> + +<address> +by <a href="/">John Walker</a><br /> +May 26, 1997<br /> + +Updated: November 2006 +</address> + +<p class="centre"> +<em>This document is in the public domain.</em> +</p> +</body> +</html> + |