¿Qué tan seguro es este generador de contraseñas de JavaScript?

3

Me pregunto qué tan seguro es este generador de contraseñas de JavaScript:

var Password = {

  _pattern : /[a-zA-Z0-9_\-\+\.\!\@\#\$\%\^\&\*\(\)\_\+\{\}\:\"\<\>\?\|\[\]\;\'\,\.\/\'\~\']/,

  _getRandomByte : function()
  {

    if(window.crypto && window.crypto.getRandomValues) 
    {
      var result = new Uint8Array(1);
      window.crypto.getRandomValues(result);
      return result[0];
    }
    else if(window.msCrypto && window.msCrypto.getRandomValues) 
    {
      var result = new Uint8Array(1);
      window.msCrypto.getRandomValues(result);
      return result[0];
    }
    else
    {
      return Math.floor(Math.random() * 256);
    }
  },

  generate : function(length)
  {
    return Array.apply(null, {'length': length})
      .map(function()
      {
        var result;
        while(true) 
        {
          result = String.fromCharCode(this._getRandomByte());
          if(this._pattern.test(result))
          {
            return result;
          }
        }        
      }, this)
      .join('');  
  }    

};

Además, si alguien tiene alguna sugerencia para hacerlo mejor o más seguro, de nada.

Una cosa más, la longitud de la contraseña generada es fija value="16" , tal vez eso puede ser una mala idea y no sería mejor generar una contraseña con una longitud aleatoria, por ejemplo. entre 12 - 16, o algo más.

    
pregunta user134969 24.01.2017 - 16:54
fuente

3 respuestas

2

Tu problema es Math.random() . Eso no es criptográficamente seguro. Sin embargo, creo que está sembrado de forma segura en la mayoría de las implementaciones, por lo que si está generando una contraseña, está bien. Pero si usa esto para generar un montón de contraseñas, serán predecibles. Eso es malo. Pero es un poco difícil trabajar con JavaScript: si no tienes un CSPRNG, no tienes un CSPRNG ...

Es posible que haya otros problemas también que me he perdido, pero eso es lo que más me llama la atención.

En cuanto a la longitud de la contraseña, hay mucho menos las contraseñas que tienen de 1 a 15 caracteres de largo que las contraseñas que tienen 16 caracteres, por lo que realmente no te estás perdiendo mucho. De todos modos, si aún desea una longitud aleatoria, debe pensar en la distribución de la que dibuja la longitud. El uso de una distribución uniforme (por ejemplo, su _getRandomByte ) le dará menos entropía y no más, ya que es probable que genere contraseñas cortas.

    
respondido por el Anders 24.01.2017 - 18:19
fuente
1

El principio general es válido: generar una contraseña seleccionando length caracteres al azar. Los detalles son donde se encuentran los problemas:

  1. Usted debe utilizar un generador de números aleatorios criptográficamente seguro. Math.random() no es así, y nunca debe usarse para esto.
  2. La forma en que está filtrando las opciones aleatorias es correcta (todos los caracteres se seleccionan con la misma probabilidad) pero ineficiente; tiene un bucle en el que dibuja un byte aleatorio (256 valores posibles) y lo desecha si no es uno de sus caracteres permitidos, repitiendo hasta que elija uno adecuado. El conjunto de caracteres permitidos es aproximadamente 95, lo que significa que la mayoría de las veces obtienes un "error". Si primero toma el resto de dividir el byte aleatorio entre 128, también obtendrá resultados correctos y mejorará notablemente la "tasa de aciertos". (Este es un truco de generación de números aleatorios estándar. ¡Debería usar una biblioteca que ya lo haga por usted!)
  3. Debe pensar claramente en el objetivo de seguridad y, por lo tanto, en la longitud de contraseña mínima permitida. Si sus contraseñas se extraen de 95 caracteres distintos, entonces cada carácter contribuye aproximadamente a log2(95) = 6.6 bits de entropía. Necesita 10 caracteres para llegar a 64 bits de entropía, lo que creo que es lo mínimo que todos deberían usar (los sitios web inician sesión en los sitios donde no se rompería el banco si alguien descifrara la contraseña, y podría quiere memorizar las contraseñas). 12 caracteres te llevan a 79 bits, lo que creo que es un buen equilibrio entre longitud y seguridad.
respondido por el Luis Casillas 24.01.2017 - 23:01
fuente
0

Debes validar el parámetro length . Si llama a Password.generate() , puede esperar que se genere una contraseña, pero en realidad devuelve una cadena vacía.

    
respondido por el Sjoerd 24.01.2017 - 20:49
fuente

Lea otras preguntas en las etiquetas