I currently use LastPass for all of my password generation and management. After reading Diceware, I realized that LastPass' password generator might be insecure, as somebody could potentially attempt to generate the same password I did.

I'm cautious about posting their code on this website, but from inspecting their code here, I've seen that for each character, they pick a character type (Upper, Lower, Number, Symbol, or All), and then pick a random character out of a predefined list.

I've attempted to look at their random number generation code, and it looks like they use the time as the seed. I'm not entirely sure where rng_pool comes from, and how it works to generate the password.

What method of generation are they using, and is it secure?

(The important functions on the page are lpCreatePass and getRandom)

  • 1
    I typically also add a phrase I generate from site, date towards the end/middle of the generated password. – Liasssa Lurkrof Feb 25 '15 at 10:55

If appears to seed the RNG with window.crypto, which if not available window.msCrypto is used and finally falls back onto current time. The relevant code is:

var rng_state;
var rng_pool;
var rng_pptr;

// Mix in a 32-bit integer into the pool
function rng_seed_int(x) {
  rng_pool[rng_pptr++] ^= x & 255;
  rng_pool[rng_pptr++] ^= (x >> 8) & 255;
  rng_pool[rng_pptr++] ^= (x >> 16) & 255;
  rng_pool[rng_pptr++] ^= (x >> 24) & 255;
  if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;

// Mix in the current time (w/milliseconds) into the pool
function rng_seed_time() {
  rng_seed_int(new Date().getTime());

// Initialize the pool with junk if needed.
if(rng_pool == null) {
  rng_pool = new Array();
  rng_pptr = 0;
  var t;
  if(typeof(navigator) != 'undefined' && navigator.appName == "Netscape" && navigator.appVersion < "5" && typeof(window) != 'undefined' && window.crypto) {
    // Extract entropy (256 bits) from NS4 RNG if available
    var z = window.crypto.random(32);
    for(t = 0; t < z.length; ++t)
      rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;

  //First try to use browser's PRNG over Math.random
    var crypt_obj = null;
    if (typeof(window) != "undefined" && typeof(window.crypto) != "undefined") {
      crypt_obj = window.crypto;
    } else if (typeof(window) != "undefined" && typeof(window.msCrypto) != "undefined") {
      crypt_obj = window.msCrypto;

 if(typeof(crypt_obj) != 'undefined' && typeof(crypt_obj.getRandomValues) == 'function') {
      if(rng_pptr < rng_psize){
        var num = Math.floor((rng_psize - rng_pptr) / 2) + 1;
        var buf = new Uint16Array(num);
        for(var i = 0; i < buf.length; i++){
          var t = buf[i];
          rng_pool[rng_pptr++] = t >>> 8;
          rng_pool[rng_pptr++] = t & 255;

  //Fall back to Math.random if needed
  while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
    t = Math.floor(65536 * Math.random());
    rng_pool[rng_pptr++] = t & 255;
  rng_pptr = 0;

Window.crpto is part of the Web Cryptography API:

[The Web Cryptography API] specification describes a JavaScript API for performing basic cryptographic operations in web applications, such as hashing, signature generation and verification, and encryption and decryption. Additionally, it describes an API for applications to generate and/or manage the keying material necessary to perform these operations. Uses for this API range from user or service authentication, document or code signing, and the confidentiality and integrity of communications.

window.msCrypto is Microsoft's implementation of this.

If you are using a supported browser then this generation method appears secure (well it as secure as your browser's implementation of the Web Cryptography API). If not, then it appears to use Math.random seeded with current time which is not secure - it would be good if the web page warned you if this was the case.

This page shows the current status of browser support for the Web Cryptography API.

|improve this answer|||||

Your Answer

