javascript password generator

I would probably use something like this:

function generatePassword() {
    var length = 8,
        charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        retVal = "";
    for (var i = 0, n = charset.length; i < length; ++i) {
        retVal += charset.charAt(Math.floor(Math.random() * n));
    }
    return retVal;
}

That can then be extended to have the length and charset passed by a parameter.


Real Quick-n-dirty™

Math.random().toString(36).slice(2, 10)

Voilà! 8 random alphanumeric characters.

The idea is to cast a random number (in the range 0..1) to a base36 string (lowercase a-z plus 0-9), and then fetch the first 8 characters after the leading zero and decimal point.

However, please be aware that different browsers and javascript implementations give different bit depth results for Math.random(). If you are running in an old browser, or Safari, this might mean (in worst case scenario) you get a shorter password than 8 characters. Though, you could solve this by simply concatenating two strings, and then slice it back down to 8 characters again.

Please be aware that Math.random() was never designed or meant to be cryptographically secure. Since you only want passwords 8 characters long, I assume you're not interested in this. However, for reference, I'll show a solution based on an actual CSPRNG. The idea is the same, we're just utilizing window.crypto instead.

window.crypto.getRandomValues(new BigUint64Array(1))[0].toString(36)

Here we are generating 1 word with 64 bits of random data, and cast it to a base36 string (0-9 and a-z). It should give you a truly random string roughly 10-13 characters long. However, to make it more secure we also want it to be longer and with mixed upper and lower cases.

We could do this either by just repeating the process twice:

console.log(window.crypto.getRandomValues(new BigUint64Array(1))[0].toString(36).toUpperCase() + window.crypto.getRandomValues(new BigUint64Array(1))[0].toString(36));

Or we could make a fancy generic generator which uses Array.reduce to concatenate multiple random 64 bit words, alternating between uppercasing each stanza:

window.crypto.getRandomValues(new BigUint64Array(length)).reduce(
    (prev, curr, index) => (
        !index ? prev : prev.toString(36)
    ) + (
        index % 2 ? curr.toString(36).toUpperCase() : curr.toString(36)
    )
);

length is the number of 64 bit words to join. I generally use 4, which gives me rougly 48-52 random alphanumeric characters, upper and lower cased.

You may also optionally shuffle the final order, which is easily accomplished with this chaining "oneliner"

password.split('').sort(
    () => 128 - window.crypto.getRandomValues(new Uint8Array(1))[0]
).join('')

The idea here is to split the generated string into an array of characters, and then sort that character array with cryptographical randomness, and finally joining it back into a string.

Personally, I have this little bookmarklet saved in my browser bookmarks bar, for quick and reasy access whenever I need to generate a site-specific username:

javascript:(
  function(){
    prompt('Here is your shiny new random string:', 
      window.crypto.getRandomValues(new BigUint64Array(4)).reduce(
        (prev, curr, index) => (
          !index ? prev : prev.toString(36)
        ) + (
          index % 2 ? curr.toString(36).toUpperCase() : curr.toString(36)
        )
      ).split('').sort(() => 128 -
        window.crypto.getRandomValues(new Uint8Array(1))[0]
      ).join('')
    );
  }
)();

Tags:

Javascript