PassGen3: A JavaScript Password Generator

This web app was inspired by the old Java applet version created by Arnold Reinhold, the latest version of which was released in 2003. Because browsers no longer support Java applets, a JavaScript-based web app was created instead. This page is not (yet) mobile-friendly.

To use this generator, just click anywhere in the text area above to ensure it's focused and start typing. At first, dots will be displayed in the text window. After you have typed 64 characters, your password will start to appear. Continue typing to complete the password. Keep typing to generate more passwords. If you wish to save your accumulated entropy across browser sessions, click the blue "Save State" button. An RNG seed will be saved to your browser's local storage. The next time the generator loads, the seed will be loaded and you can immediately start generating passwords. Note: a seed is never saved automatically and must be done so manually.

You can type in anything you like or just close your eyes and type characters at random. For extra credit, type in the serial numbers from a couple of dollar bills or other paper currency. The web app records the time in milliseconds when you press down and release each key and uses these time values, along with the key characters you type, as a source of randomness. There will normally be enough variability in your typing times to ensure that the characters that appear in the text window are highly random.

The PassGen3 web app lets you select a pattern for the random strings it generates. Just pick a template from the selection box at the top of the text area. The following table describes each template and shows its appropriate entropy strength in bits.

Template Generated Password Keystrokes Security Sample Suggested Use
Diceware 10 Diceware words
(English 8k word list)
65 keys 130 bits plaza n8 rt tern rainy ghoul dd vx paz masque High security master passphrase
ASCII 20 graphical ASCII characters
(no whitespace)
70 keys 131 bits _0=yM2.AC)W[QLGF+R`I High security password
Pseudowords 8 pronounceable Proquints pseudowords 64 keys 128 bits zujun safig losab nigoh komug mugor rafon kikoj High security master passphrase
Alphanumeric 22 alphanumeric characters
(0-9, A-Z, a-z)
66 keys 130 bits Xn0iJQDZYyati6PpfW0qAh High security password
Alphabetic 28 uppercase ASCII characters
(A-Z)
70 keys 131 bits NZIN NGVG QFUB RDDW ILOM IPIQ SLRE One time pads
Hexadecimal 32 hexadecimal characters
(0-9, A-F)
64 keys 128 bits 9940 0FF2 AFFD 3BF2 4E3C 407B 82A3 3CCD Symmetric cipher key, Niceware
Decimal 40 decimal digits
(0-9)
80 keys 132 bits 52515 86607 84774 55383 51452 60536 55237 70725 Statistical use, one time pads
Senary 50 base-6 digits
(1-6)
75 keys 129 bits 55636 41266 42426 24335 15236 33515 46343 53154 36554 66212 Diceware, board games

This web app is not the most secure way to make your password! Traces of the passwords you create can be left behind in your computer's memory, among other risks. Clicking "Save State" will store a 32 byte seed from the RNG state to disk and save your preferred cipher. Using the ChaCha, Spritz, or Trivium stream ciphers with key presses is backtracking resistant such that an adversary should not be able to regenerate prior passwords from it. They also should not be able to predict your keystrokes, so future passwords should be improbable to generate also. But a leaked RNG state could present other risks. For maximum security we still recommend using ordinary dice to select a password or passphrase. See the Diceware page for more details.

PassGen3 awards only 2 bits of entropy per character typed. This is based on Shannon entropy of English text and synchronization between keyboard typing and neural oscillations. There may be more entropy per keystroke, but 2 bits is about as liberal as I dare award and it's enough to generate passwords very quickly. As such, you will be required to type 64 characters on page load to seed the state with at least 128 bits of entropy before passwords begin to appear. PassGen3 does track all entropy, accumulated and used, to make your typing as efficient as possible.

The security margins of each password type are as follows:

  • Diceware: 13 bits per word
  • ASCII: ~6.55 bits per character
  • Pseudowords: 16 bits per word
  • Alphanumeric: ~5.95 bits per character
  • Alphabetic: ~4.70 bits per character
  • Hexadecimal: 4 bits per character
  • Decimal: ~3.32 bits per character
  • Senary: ~2.58 bits per character

Nonetheless, using this web app to generate a password is far safer than picking your pet's name or your mother's birthday. Because JavaScript web apps download from an untrusted web server, there is risk of mischief. This web app does not make any network connections, so you can run it offline after you download it and inspect the source code. People desiring even greater assurance in security can use the dice-based password generation techniques described at https://www.diceware.com.

You should be aware that someone could substitute a bogus version of the web app that creates apparently random passwords that are, in fact, easy for the adversary to guess. To reduce this risk, the source code of the web app is published as open source. The ChaCha, Spritz, and Trivium stream ciphers were also chosen as they are easy to understand and the source code should be easy to read for those moderatly familiar with programming.

Random generation methods will very rarely create a password that is an English word or phrase or simple letter pattern. If a password looks like an ordinary word (or, with the "ASCII" template, is all the same case) simply type some more and use the next password.

PassGen3 uses a strong method for mixing randomness. The first version of PassGen used an entropy distiller with a 64-bit internal state, based on a linear congruential algorithm. PassGen2 used an entropy distiller based on the weak RC4 cipher. PassGen3 allows you to pick from the ChaCha, Spritz, or Trivium stream ciphers as an entropy distiller.

In Spritz, a 256-byte state vector that is initialized to be a null permutation. As Spritz is based on a sponge construction, both the key press time in milliseconds and the character value are absorbed to permute the Spritz state. As such, the Spritz state is highly mixed by each keystroke. Each password output character is then squeezed out of the Spritz state. Published analysis have shown that Spritz can be distinguished from true random white noise. As such, a countermeasure has been added to remove the distinguishers found in the keystream.

In ChaCha, a 64-byte state vector is initialized following RFC 8439. ChaCha is based on an ARX (add-rotate-xor) cipher that builds a keystream that is XORed with the data. Unlike Spritz, the ChaCha state is not dependent on the data it is encrypting. PassGen3 should provide a consistent API for all ciphers, so an "absorb" and "squeeze" functionality have been added to ChaCha. This is done by maintaining a 64-byte entropy pool to store key presses in milliseconds and their character values. Once the pool is filled, it is used to directly rekey ChaCha.

In Trivium, a 288-bit state vector is initialized to be a null permutation following the specification. Trivium uses three non-linear feedback shift registers in a closed loop. It is optimized for hardware so operates on individual bits instead of bytes like ChaCha and Spritz. Trivium also is not based on a sponge construction, so like ChaCha, "absorb" and "squeeze" functions have been added to keep a consistent API in PassGen3. Also like ChaCha, a 10-byte entropy pool to store key presses in milliseconds and character values is maintained. Once the pool is filled, it is used to directly key Trivium.

When using an 8-bit value to select a character from an alphabet of length "n", there is a risk of bias if "n" does not evenly divide 256. To eliminate this, candidate cipher output bytes are discarded if they are outside of the range that is the largest multiple of "n" less than or equal to 256.

PassGen3 performs extensive absorbing of initialization data via the way of a browser fingerprint and requiring the user to type at least 64 characters when the page is loaded. The key presses are required to key the cipher state with at least 128 bits of keyboard entropy.

PassGen, PassGen2 © 1996, 2003 Arnold G. Reinhold, Cambridge, MA, USA

PassGen3 © 2022 Aaron Toponce

PassGen and PassGen2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

PassGen3 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 3 as published by the Free Software Foundation, with two additional restrictions:

  1. You may not redistribute versions modified to create "malware," including versions that deliberately produce inaccurate or misleading results or that surreptitiously capture data entered by the user or that produce "random" values that are predictable or guessable.
  2. You may not redistribute this program in ways that violate the export control laws of the United States.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. If the previous link does not work, you can request a copy of the license by writing to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA.