java - nextint - ¿Debo sembrar un SecureRandom?
math.random java (4)
Creo que esto es completamente innecesario, ya que, como cita el Javadoc que usted cita claramente, las instancias de SecureRandom
construidas por defecto se SecureRandom
sí mismas. La persona que escribió esto probablemente no lo sabía.
También podrían disminuir la seguridad al forzar una longitud de semilla fija que podría ser menos que ideal para la implementación de RNG.
Finalmente, suponiendo que el fragmento de código se publique sin alteraciones, la deglución silenciosa de excepciones tampoco es un estilo de codificación muy bueno.
Encontró el siguiente código en nuestra base de código:
public static final int DEFAULT_LENGTH = 16;
private static SecureRandom SR;
static
{
try
{
SecureRandom sd0 = new SecureRandom();
SR = new SecureRandom(sd0.generateSeed(DEFAULT_LENGTH * 2));
}
catch (Exception e){}
}
Aquí se crea un SecureRandom
predeterminado, y luego se usa para crear una semilla para otra que es la que se usará más adelante en la clase. ¿Es esto realmente necesario? ¿Es el segundo de alguna manera mejor que el primero porque se hace esto?
Cuando se genera la semilla para el segundo, se da el número de bytes, ¿es esto importante? ¿Un SecureRandom
sembrado con una cantidad diferente de bytes que otro podría ser mejor o peor? ¿Debería el número de bytes utilizados para inicializarlo de alguna manera a lo que se usará?
Si no se llama a setSeed, la primera llamada a nextBytes forzará al objeto SecureRandom a inicializarse. Esta auto-siembra no ocurrirá si se llamó previamente a setSeed. - javadoc
¿La auto-siembra no es lo suficientemente buena? ¿Depende de para qué se va a utilizar?
Nota: para algún contexto, se usa en la clase que crea identificadores aleatorios para cosas almacenadas en una base de datos.
Esto no solo es completamente innecesario, sino que puede aumentar la previsibilidad de los números generados por el objeto SecureRandom.
Un SecureRandom que no tiene un conjunto de semillas explícito se auto-siembra. Utiliza una fuente de datos altamente aleatoria para realizar esta operación, y es bastante segura. El primer SecureRandom en su ejemplo de código utilizará tal semilla.
El segundo se siembra desde el primero al producir 256 bits aleatorios. Suponiendo que se utiliza el SHA1PRNG predeterminado del sistema, esto es lo suficientemente bueno. Utiliza 160 bits de estado, por lo que 256 bits aleatorios satisfarán completamente sus requisitos. Pero suponga que ahora alguien decide que esto no es suficiente y cambia el valor predeterminado a SHA512PRNG (pueden hacerlo sin siquiera mirar su código cambiando las propiedades de seguridad de Java). Ahora le está dando muy pocos bits de semilla: solo la mitad que necesita.
Deshazte de él, y solo usa el objeto auto-sembrado, a menos que tengas una mejor fuente de datos semilla que la que el sistema tiene disponible.
Evite utilizar el algoritmo predeterminado, que es el caso cuando se hace un new SecureRandom();
En su lugar haz:
SecureRandom.getInstance("SHA1PRNG", "SUN");
Si alguien cambia el algoritmo predeterminado (como lo indica @Jules), no se verá afectado.
Editado para Android:
Para Android, eche un vistazo a:
- https://android-developers.googleblog.com/2016/06/security-crypto-provider-deprecated-in.html
- http://www.infosecisland.com/blogview/24773-Android-N-Deprecating-Crypto-Provider-and-SHA1PRNG-Algorithm.html
- https://security.stackexchange.com/questions/128144/android-n-security-crypto-provider-is-deprecated
- Proveedor de seguridad "Crypto" en desuso en Android N
En Android, no recomendamos especificar el proveedor. En general, cualquier llamada a las API de Java Cryptography Extension (JCE) que especifique un proveedor solo debe hacerse si el proveedor está incluido en la aplicación o si la aplicación puede lidiar con una posible excepción ProviderNotFoundException.
...
En Android N, estamos desaprobando la implementación del algoritmo SHA1PRNG y el proveedor Crypto por completo.
Solo un addendum a esta respuesta. De acuerdo con Google, si está utilizando este código en Android, definitivamente debería inicializar SecureRandom utilizando una fuente de alta entropía como / dev / urandom o / dev / random.
Incluso la publicación de abajo tiene un año de antigüedad, quizás ya se haya corregido, pero no pude confirmar si lo fue.
https://plus.google.com/+AndroidDevelopers/posts/YxWzeNQMJS2
EDITAR:
Parece que el comportamiento predeterminado de la clase ahora es el especificado en la publicación, por lo que la siembra se considera innecesaria nuevamente:
http://developer.android.com/reference/java/security/SecureRandom.html