java - password - ¿Es UUID.randomUUID() adecuado para usar como contraseña de un solo uso?
random java (7)
Creo que esto debería ser adecuado, ya que se genera de forma aleatoria en lugar de hacerlo desde cualquier entrada específica (es decir, no la está alimentando con un nombre de usuario o algo así), por lo que las llamadas múltiples a este código darán resultados diferentes. Indica que es una clave de 128 bits, por lo que es lo suficientemente largo como para ser poco práctico de romper.
¿Va a utilizar esta clave para cifrar un valor, o espera usar esto como la contraseña real? De todos modos, deberá volver a interpretar la clave en un formato que pueda ingresar con un teclado. Por ejemplo, haga una conversión Base64 o Hex, o de alguna manera asigne los valores a alfanuméricos, de lo contrario, el usuario intentará ingresar valores de bytes que no existen en el teclado.
Como se discutió anteriormente , los correos electrónicos de confirmación deben tener un código único, (prácticamente) inaplicable, esencialmente una contraseña de un solo uso, en el enlace de confirmación.
Los documentos UUID.randomUUID () dicen:
El UUID se genera utilizando un generador de números pseudoaleatorios criptográficamente fuerte.
¿Implica esto que el generador aleatorio UUID en una JVM correctamente implementada es adecuado para su uso como el OTP único (prácticamente) inaplicable?
El punto del código aleatorio para un enlace de confirmación es que el atacante no debería poder adivinar ni predecir el valor. Como puede ver, para encontrar el código correcto en su enlace de confirmación, un UUID de 128 bits de longitud produce 2 ^ 128 códigos diferentes posibles, es decir, 340,282,366,920,938,463,463,374,607,431,768,211,456 códigos posibles para probar. Creo que su enlace de confirmación no es para lanzar un arma nuclear, ¿verdad? Esto es bastante difícil de adivinar para el atacante. Es seguro.
- actualización -
Si no confía en el generador de números aleatorios criptográficamente fuerte proporcionado, puede poner algunos parámetros más impredecibles con el código UUID y hash ellos. Por ejemplo,
código = SHA1 (UUID, PID de proceso, ID de subproceso, número de puerto de conexión local, temperatura de CPU)
Esto hace que sea aún más difícil de predecir.
Es perfecto como contraseña de un solo uso, ya que incluso yo había implementado lo mismo para la aplicación en la que estoy trabajando. Además, el enlace que compartió lo dice todo.
Sí, usar un java.util.UUID
está bien. No hay mucho más que decir.
Aquí está mi sugerencia:
- Envíe al usuario un enlace con una gran contraseña como argumento de URL.
- Cuando el usuario hace clic en el enlace, escriba su servidor para que determine si el argumento es correcto y si el usuario ha iniciado sesión.
- Invalida el UUID 24 horas después de que se haya emitido.
Esto requerirá cierto trabajo, pero es necesario si realmente te importa escribir un sistema robusto y seguro.
Si es generado por un CSRNG, entonces es impredecible y puede ser utilizado.
Pero el problema que vas a perder se desperdicia si estás enviando correos electrónicos de confirmación sin cifrar: si un atacante tiene los medios para predecir los resultados de RNG de tu sistema, es probable que también puedan interceptar los correos electrónicos.
Los UUID también son cadenas largas (128 bits entonces típicamente Base64 (22 caracteres) o codificados en Base16 (32 caracteres)): piense en lo fácil que será su sistema. Personalmente, utilizaría un CSRNG para seleccionar 8 caracteres alfanuméricos al azar y devolverlos.
si lee el RFC que define los UUID y al que está vinculado desde los documentos API, verá que no todos los bits del UUID son realmente aleatorios (la "variante" y la "versión" no son aleatorias). por lo tanto, un UUID de tipo 4 (del tipo que se pretende usar), si se implementa correctamente, debe tener 122 bits de (seguro, para esta implementación) información aleatoria, de un tamaño total de 128 bits.
así que sí, funcionará tan bien como un número aleatorio de 122 bits de un generador "seguro". pero un valor más corto puede contener una cantidad suficiente de aleatoriedad y puede ser más fácil para un usuario (tal vez soy la única persona anticuada que todavía lee un correo electrónico en un terminal, pero las URL de confirmación que envuelven líneas son molestas ...) .
No. Según la especificación UUID :
No suponga que los UUID son difíciles de adivinar; no deben usarse como capacidades de seguridad (identificadores cuya mera posesión concede acceso), por ejemplo. Una fuente de números aleatorios predecibles exacerbará la situación.
Además, los UUID solo tienen 16 caracteres posibles (de 0 a F). Puede generar una contraseña aleatoria mucho más compacta y explícitamente segura utilizando SecureRandom
(gracias a @erickson).
import java.security.SecureRandom;
import java.math.BigInteger;
public final class PasswordGenerator {
private SecureRandom random = new SecureRandom();
public String nextPassword() {
return new BigInteger(130, random).toString(32);
}
}