¿Para qué sirve la opción java.security.egd?

23

En un proyecto en el que estoy trabajando, la aplicación se inicia utilizando un comando similar a este:

java -Djava.security.egd=file:/dev/urandom -jar app.jar

Nunca he visto la java.security.egdopción antes. Al buscar un poco, parece que se usa para configurar la generación de números aleatorios en una aplicación Java.

¿Es correcto? ¿Cuándo se supone que debe aplicarse?

davioooh
fuente

Respuestas:

30

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.

dbaltor
fuente
1
A partir de Java 8, ya no se requiere la "solución oscura" del extra ./ en el nombre del archivo, por lo que puede usar "/ dev / urandom", consulte: docs.oracle.com/javase/8/docs / notas técnicas / guías / seguridad / ...
Kamal
Gracias por actualizar la respuesta (especialmente sobre los cambios en Java 9 y 13). Sin embargo, según tengo entendido, a partir de Java 8, configurar el "dispositivo de recolección de entropía" en / dev / urandom o /dev/./urandom debería producir exactamente los mismos resultados, de lo contrario la solución no tendría sentido. Desde la perspectiva del sistema operativo, esos apuntan al mismo archivo idéntico, por lo que no debería afectar a Java (lo hizo antes de la corrección, pero eso fue un error, no una función prevista). Por lo tanto, su declaración "El /./ adicional es necesario para influir en la selección de PRNG" ya no debería ser cierto, a partir de Java 8.
Kamal
Gracias @Kamal por tus comentarios. Mi frase anterior "selección de PRNG" no era lo suficientemente clara. Lo he reformulado para aclarar que estoy hablando del algoritmo utilizado: NativePRNG o SHA1PRNG. El uso de /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.
Dbaltor
1

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

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).

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

Venu Madhav
fuente
No creo que esto sea correcto. Para antecedentes: tersesystems.com/blog/2015/12/17/… Las correcciones en Java 8 solo dicen que ahora respetan las propiedades de origen de semilla de SecureRandom en el archivo java.security. Pero, de manera predeterminada, todavía contiene: securerandom.source = file: / dev / random La "solución oscura" se refiere al extra ./ en el nombre del archivo, también mencionado por la respuesta aceptada (y más votada) aquí.
Kamal
La "solución oscura" fue sólo se requiere en circunstancias específicas, consulte: bugs.java.com/bugdatabase/view_bug.do?bug_id=6202721
Kamal
@Kamal Los enlaces que publicaste se refieren a Java 6 y anteriores,
Venu Madhav
Ese es exactamente el punto, se solucionó en Java 8. De acuerdo con el informe de error, la "solución alternativa oscura" (agregando el ./ extra en el nombre del archivo) era necesaria después de Java 1.4.2 y hasta 6. Estoy asumiendo en Java 7 también, de lo contrario no se mencionaría como arreglado en Java 8. Sin embargo, aún es necesario configurar / dev / urandom en lugar de / dev / random, si desea utilizar un dispositivo sin bloqueo.
Kamal
0

Esto está relacionado con la diferencia de Linux /dev/randomy /dev/urandomel generador de números aleatorios.

Tomado de este enlace

El error de Java 6202721 establece que java.security.SecureRandom usa / dev / random en lugar de / dev / urandom incluso si se especifica / dev / urandom porque en ese momento (alrededor de 2004) / dev / urandom no funcionaba correctamente. El error nunca se ha revertido ahora que / dev / urandom funciona bastante bien. Por lo tanto, debe simularlo ocultando la configuración utilizando /dev/./urandom para forzar el uso de SHA1PRNG en lugar de / dev / random.

Para responder tu pregunta

¿Cuándo se supone que debe aplicarse?

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.

Ruelos Joel
fuente
Probablemente hay un error tipográfico en ese artículo, ya que Java Bug 6202721 en realidad dice "Esto es un problema si / dev / urandom fue elegido porque / dev / random no funciona correctamente". Por lo tanto, su conclusión "como resultado de problemas con / dev / urandom" es incorrecta. Consulte la respuesta aceptada para obtener una explicación sobre cómo elegir / dev / urandom en lugar del predeterminado (/ dev / random). Es una buena idea en la mayoría de los casos.
Kamal