Las aplicaciones Java pueden y deben usar la clase java.security.SecureRandom para producir valores aleatorios criptográficamente fuertes mediante el uso de un generador de números pseudoaleatorios criptográficamente fuertes ( CSPRNG ). Las implementaciones JDK estándar de la clase java.util.Random no se consideran criptográficamente fuertes.
Los sistemas operativos tipo Unix tienen /dev/randomun archivo especial que sirve números pseudoaleatorios que acceden al ruido ambiental recolectado de los controladores de dispositivos y otras fuentes. Sin embargo, bloquea si hay menos entropía disponible que la solicitada ; /dev/urandomnormalmente nunca se bloquea, incluso si la semilla del generador de números pseudoaleatorios no se inicializó completamente con entropía desde el arranque. Todavía hay un tercer archivo especial, /dev/arandomque se bloquea después del arranque hasta que la semilla se ha inicializado de forma segura con suficiente entropía, y luego nunca se vuelve a bloquear.
Por defecto, la JVM genera la clase SecureRandom usando /dev/random, por lo tanto, su código Java puede bloquearse inesperadamente . La opción -Djava.security.egd=file:/dev/./urandomen la invocación de línea de comando utilizada para iniciar el proceso Java le dice a la JVM que la use /dev/urandomen su lugar.
El extra /./parece hacer que la JVM use el algoritmo SHA1PRNG que usa SHA-1 como la base del PRNG (generador de números pseudoaleatorios). Es más fuerte que el algoritmo NativePRNG utilizado cuando /dev/urandomse especifica.
Finalmente, existe un mito que /dev/urandomes un generador de números aleatorios pseudoaleatorios, un PRNG, mientras que /dev/randomes un generador de números aleatorios "verdadero" . Esto simplemente no es cierto, ambos /dev/randomy /dev/urandomson alimentados por el mismo CSPRNG (generador de números pseudoaleatorios criptográficamente seguro). Solo el comportamiento cuando su grupo respectivo se queda sin entropía, según algunas estimaciones, difiere: /dev/randombloques, mientras /dev/urandomque no.
¿Qué pasa con la entropía baja? No importa.
Resulta que "parecer aleatorio" es el requisito básico para muchos de nuestros bloques de construcción criptográficos. Y si toma la salida de un hash criptográfico, debe ser indistinguible de una cadena aleatoria para que los cifrados lo acepten. Esa es la razón de usar el algoritmo SHA1PRNG, ya que usa una función hash y un contador, junto con una semilla.
¿Cuándo se supone que debe aplicarse?
Siempre, yo diría.
Fuentes:
https://gist.github.com/svrc/5a8accc57219b9548fe1
https://www.2uo.de/myths-about-urandom
EDITAR 04/2020:
Un comentario menciona un cambio en el comportamiento de la clase SecureRandom en Java 8.
SHA1PRNG y NativePRNG se corrigieron para respetar adecuadamente las propiedades de origen de semilla SecureRandom en el archivo java.security. (La solución alternativa oscura que usa file: /// dev / urandom y file: / dev /./ urandom ya no es necesaria).
Esto ya había sido señalado por las pruebas a las que se hace referencia en la sección Fuentes anterior. El extra /./es necesario para cambiar el algoritmo utilizado por SecureRanom en Java 8 de NativePRNG a SHA1PRNG.
Sin embargo, tengo algunas noticias que me gustaría compartir. Según el JEP-273 , desde Java 9, la clase SecureRandom implementa los tres mecanismos del generador de bits aleatorio determinista (DRBG) descritos en NIST 800-90Ar1 . Estos mecanismos implementan algoritmos modernos tan fuertes como SHA-512 y AES-256.
El JDK tenía dos tipos de implementaciones de SecureRandom :
- Uno depende de la plataforma y se basa en llamadas nativas o dispositivos del sistema operativo, como leer
/dev/{u}randomen Unix o usar CryptoAPI en Windows. Las últimas versiones de Linux y Windows ya admiten DRBG, pero las versiones anteriores y los sistemas integrados pueden no serlo .
- El otro tipo es una implementación pura de Java que utiliza una implementación RNG basada en SHA1 más antigua, que no es tan sólida como los algoritmos utilizados por los mecanismos DRBG aprobados.
Mientras tanto, la Guía del desarrollador de seguridad de Java 13 sigue leyendo
En Linux y macOS, si el dispositivo de recopilación de entropía en java.security se establece en file:/dev/urandomo file:/dev/random, entonces NativePRNG se prefiere a SHA1PRNG. De lo contrario, se prefiere SHA1PRNG.
Para aclarar cómo los nuevos mecanismos DRBG juegan junto con los PRNG anteriores, ejecuté algunas pruebas en macOS (Darwin) con AdoptOpenJDK (compilación 13.0.2 + 8). Aquí están los resultados:
file: / dev / random
Orden de preferencia para proveedores:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
archivo: / dev / urandom
Orden de preferencia para proveedores:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
file: / dev /./ urandom
Orden de preferencia para proveedores:
SecureRandom.DRBG
SecureRandom.SHA1PRNG
SecureRandom.NativePRNG
Conclusión:
Recomiendo usar -Djava.security.egd=file:/dev/./urandompara asegurarse de aprovechar la implementación más segura de SecureRandom disponible, independientemente de la plataforma utilizada, evitando bloquear el código inesperadamente.
/dev/urandomselecciona NativePRNG alimentado por/dev/urandommientras/dev/./urandomselecciona SHA1PRNG (también alimentado por/dev/urandom) cuando se utiliza Java 8. A partir de Java 9, DRBG tiene prioridad cuando/dev/./urandomse especifica la fuente.Esto ya no es necesario si está utilizando JDK 8 o superior
El problema ha sido solucionado por Java y aquí hay algunos enlaces
contorno
Para más información (busque al azar en la página):
https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8.html
https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html
fuente
Esto está relacionado con la diferencia de Linux
/dev/randomy/dev/urandomel generador de números aleatorios.Tomado de este enlace
Para responder tu pregunta
Basado en el enlace anterior, eso es algo exclusivo de las versiones de Java 5 y siguientes que resultó de problemas con / dev / urandom en sistemas Linux en 2004.
fuente