Java UUID.randomUUID () o SecureRandom para el segmento de identificación en la URL?

6

Al crear un sistema basado en Java que necesita identificadores únicos en la URL, ¿es UUID.randomUUID() o SecureRandom una mejor opción?

Más específicamente, una llamada a POST /items devolverá un 201 Created con una ubicación al /items/{id} recién creado, donde {id} es una cadena aleatoria y la URL está destinada a ser utilizada por solicitudes HTTP anónimas para un ventana de tiempo limitado.

Este código devuelve una cadena de 22 caracteres (por ejemplo, B-KEPLFdWNZ4JTUnnEq3Og ) con 128 bits de aleatoriedad.

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[16];
random.nextBytes(bytes);
Encoder encoder = Base64.getUrlEncoder().withoutPadding();
String token = encoder.encodeToString(bytes);
System.out.println(token);

UUID.randomUUID () es una "Fábrica estática para recuperar un UUID tipo 4 (pseudoaleatorio). El UUID se genera utilizando un generador criptográficamente fuerte de números pseudoaleatorios". Este código devuelve una cadena de 36 caracteres (por ejemplo, f0803ce7-8e3d-421a-8126-e5a0bd0a865f ) con 122 bits de aleatoriedad.

UUID randomUUID = UUID.randomUUID();
System.out.println(randomUUID);

Estos identificadores también se conservarán en una base de datos relacional como un tipo CHAR de longitud fija.

    
pregunta Kevin Hakanson 24.10.2016 - 22:55
fuente

2 respuestas

8

En términos de la cantidad bruta de bits aleatorios, sí.

Viendo el fuente de la generación aleatoria de UUID de Java, puede ver que realmente utilizan la clase SecureRandom para generar los bytes sin procesar. Por lo tanto, la "calidad" de su aleatoriedad no va a cambiar.

El hecho de que tenga 6 bits más hace, técnicamente, hace que sea más difícil forzar la fuerza de un duplicado. El artículo de Wikipedia sobre UUID tiene una buena descripción de las matemáticas detrás de él. Para citarlo:

  

[A] después de generar 1 mil millones de UUID por segundo durante los próximos 100 años, la probabilidad de crear un solo duplicado sería de aproximadamente el 50%

Si estos enlaces caducarán en, digamos, 24 horas, esto es algo muy pequeño de lo que preocuparse, y eso es solo con 122 bits.

Ahora, ¿más bits van a hacer que sea más difícil para un atacante forzar bruscamente una colisión? ¡Por supuesto! ¿Vale la pena? Tal vez ... pero tal vez no. Solo usted puede realmente decidir qué es lo correcto para su caso de uso.

Cuando llegas al punto en que la fuerza bruta forzando una colisión tomaría, en promedio, más tiempo que la muerte térmica estimada del universo, podría ser un poco exagerado. Eso está llegando al territorio de la necesidad de preocuparse más por los piratas informáticos que comprometen la seguridad de su almacenamiento más que por el uso de fuerza bruta (y, honestamente, incluso con los UUID, tendrá ese problema). En última instancia, la dificultad de forzar la fuerza bruta no importa si pueden encontrar otra forma de entrar. Si está realmente preocupado, el almacenamiento es barato: almacene cadenas de 256 bits que genere con un SecureRandom y hágalo saber, pero asegúrese Usted tiene la seguridad adecuada en todo lo demás, o es inútil.

    
respondido por el childofsoong 24.10.2016 - 23:17
fuente
8

Bueno, en principio, los UUID y los RNG criptográficos prometen dos cosas diferentes:

  1. Los UUID prometen baja probabilidad de duplicados ;
  2. Los RNG criptográficos prometen imprevisibilidad a un adversario malicioso .

Si el # 2 es una preocupación, me aseguraría de usar un RNG criptográfico. Por ejemplo, si le preocupa que un atacante malintencionado que puede solicitar una gran cantidad de UUID en un corto período de tiempo, puede obtener suficiente información para predecir los dados a las solicitudes de otros usuarios.

A medida que sucede, el método UUID.randomUUID() de Java utiliza un RNG criptográfico, por lo que debería ser seguro en ese sentido. Pero el riesgo, entonces, es que los desarrolladores que luego analizan su código pueden no entender que su intención incluye una elección aleatoria criptográfica segura, y no solo la singularidad. Por ejemplo, alguien podría reescribir ese módulo en particular utilizando otro idioma o biblioteca UUID que no use un RNG criptográfico, y lo expondrá a ataques basados en predicciones que pretendía excluir. Entonces, si la seguridad criptográfica realmente fuera un factor importante, intentaría escribir el código de una manera que lo haga obvio, usando SecureRandom explícitamente. (¡El código crítico para la seguridad debe ser muy claro!)

Si todo lo que me importara fuera la singularidad en lugar de la seguridad, seguiría y usaría UUID.randomUUID() .

    
respondido por el Luis Casillas 25.10.2016 - 02:09
fuente

Lea otras preguntas en las etiquetas