¿Qué cifrado basado en contraseña usar con Java 6 estándar?

5

¿Qué método de cifrado basado en contraseña debo usar en Java 6? Debería ser lo más fuerte posible, pero trabajar con el archivo de la política de seguridad predeterminada (no con la exportación restringida que debe descargar e instalar por separado).

    
pregunta user12889 25.07.2011 - 05:57
fuente

2 respuestas

5

Mi recomendación: Debería intente evitar el uso de cifrado basado en contraseña , si es posible que pueda evitarlo. En particular, el cifrado basado en contraseña tiende a ser inseguro, en la práctica. El problema es que es raro que las contraseñas de los usuarios tengan suficiente entropía para resistir el ataque del diccionario. Por lo tanto, si necesita cifrado, es probable que no desee utilizar el cifrado basado en contraseña , si hay alguna alternativa .

Una mejor solución es dar a los usuarios una clave y usarla para cifrar o descifrar.

Si no sigues mi recomendación: Si absolutamente debes usar un cifrado basado en contraseña, aquí hay algunas sugerencias para reducir un poco el riesgo:

  • Use PBKDF2 para obtener la clave de la contraseña. Elija un número adecuado de iteraciones para que el proceso de obtención de claves tome, por ejemplo, 100 ms en la máquina del usuario. Esto hará que sea un poco más difícil realizar una búsqueda de diccionario en la frase de contraseña del usuario; sin embargo, no elimina el riesgo, por lo que los usuarios aún deben hacer un esfuerzo adicional para elegir una frase de contraseña muy larga.

  • Haga todo lo posible para aumentar la probabilidad de que sus usuarios utilicen una frase de paso muy larga. El mejor enfoque sería generar automáticamente la contraseña para ellos. Sugiero elegir uno con 80 bits de entropía. Si convierte esto en una contraseña que usa A-Za-z0-9 (pero no O o l, para evitar confusiones con 0 o 1), la frase de contraseña resultante tendrá una longitud de 14 caracteres. Es posible que a los usuarios no les guste tener que lidiar con una frase de contraseña tan larga, pero solo tendrán que asimilarla y negociar, si quieren estar seguros.

    Si permite a los usuarios elegir su propia frase de contraseña, la mayoría probablemente elegirá una frase de contraseña de menor calidad. Le sugiero que incluya advertencias sobre el riesgo. Debería recomendar que elijan una frase de contraseña que tenga al menos 20 caracteres y que sea lo más aleatoria posible. Es posible que desee proporcionar una pequeña aplicación para generar una frase de contraseña de muestra para que puedan cortar y pegar y usar.

    Incluso con todos sus esfuerzos, si los usuarios eligen su propia frase de contraseña, es probable que muchos usuarios elijan una que no sea lo suficientemente segura. El problema es que el cifrado requiere frases de contraseña que son considerablemente más largas y más seguras que las contraseñas que utiliza para una contraseña de cuenta web. La mayoría de los usuarios probablemente no lo saben, y de todos modos, las molestias de elegir una frase de contraseña que sea lo suficientemente larga y sólida probablemente disuadirán a muchos usuarios de hacerlo y harán que se comporten de manera insegura.

Si tiene la sensación de que el cifrado basado en contraseña es un dolor de cabeza para usar de forma segura, su percepción es absolutamente precisa.

    
respondido por el D.W. 25.09.2011 - 01:17
fuente
3

Primero lea la respuesta de @ D.W., está llena de buenos consejos. Luego, si aún desea realizar un cifrado basado en contraseña, considere lo siguiente:

  • El cifrado basado en contraseña consiste en convertir una contraseña en una clave y luego usar esa clave para el cifrado simétrico.
  • Java puede hacer un cifrado basado en contraseña, es decir, hacer los dos pasos en una API optimizada, como se muestra here . Sin embargo, solo permite algunas combinaciones de mecanismos de hashing de contraseñas y algoritmos de encriptación y, en particular, se informa que no se permite eso con AES, lo cual es un problema.
  • Nada le impide realizar la transformación de contraseña a clave y luego el cifrado en dos pasos separados en su código.

Tenga en cuenta que los mecanismos de cifrado de contraseñas generalmente no están cubiertos por las leyes criptográficas y las regulaciones de exportación, ya que no "ocultan" los datos. Luego recomiendo que solo incluya una implementación de bcrypt en su código, por ejemplo. jBCrypt que está escrito en Java, OpenSource con una licencia fácil y razonablemente compacto ( one archivo fuente). Necesitaría alterar el código un poco, porque esa implementación quiere usar cadenas , mientras que usted quiere bits sin procesar; por lo tanto, haz lo siguiente:

  • Use el método crypt_raw() para convertir la contraseña y el salt en la salida de bcrypt de 192 bits.
  • Hash estos 192 bits con SHA-512 (Java 6 incluye una implementación SHA-512). Esto produce 512 bits.
  • Utilice estos 512 bits para el cifrado AES de sus datos, con un MAC en el resultado (por ejemplo, con HMAC / SHA -256, entonces nuevamente soportado por Java 6). Vea a continuación para más detalles.

(Normalmente prefiero bcrypt sobre PBKDF2 por las razones explicadas allí , pero PBKDF2 tampoco es malo, así que si realmente desea PBKDF2 (o lo necesita por razones de cumplimiento), entonces hágalo.

Importante: hacer el cifrado correctamente, y agregar un MAC, puede verse afectado de muchas maneras sorprendentes. Usted está muy animado a no hacerlo usted mismo. Sin embargo, el siguiente método debería ser seguro:

  • Tiene 512 bits de "datos derivados de contraseñas". Divídelo en cuatro bloques de 128 bits.
  • Cifre los datos con AES-128 en modo CBC. CBC requiere un vector de inicialización , que es una matriz de 16 bytes aleatorios. Utilice el primer bloque de 128 bits (de la salida SHA-512) como clave, y el segundo bloque de 128 bits como IV. Además, use el relleno PKCS # 5 (ya que sus datos de entrada pueden tener una longitud que no es un múltiplo de 16).
  • Cuando se realice el cifrado, calcule HMAC / SHA-256 sobre una entrada que consiste en el IV, luego el resultado del cifrado , en ese orden; la clave para HMAC será el tercer bloque de 128 bits de la salida SHA-512.
  • El "archivo cifrado" debe contener la sal para bcrypt (128 bits, 16 bytes), la salida del cifrado AES / CBC y la salida HMAC (256 bits, 32 bytes).
  • Para descifrar, use el salt (del archivo cifrado) y la contraseña para volver a calcular bcrypt, luego aplique SHA-512 para obtener la clave de cifrado, IV y clave para HMAC. Verifique el valor HMAC y, si es correcto, descifre los datos.

Y, recuerda: nunca, nunca , NUNCA reutiliza el valor salt para dos instancias de cifrado (ya sea que usen la misma contraseña o no). Siempre use java.security.SecureRandom para generar un nuevo sal aleatorio cada vez que desee cifrar un archivo.

    
respondido por el Thomas Pornin 30.09.2012 - 17:52
fuente

Lea otras preguntas en las etiquetas