crypto-otp.html 43 KB

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