¿Hay alguna buena manera de generar números pseudoaleatorios (o aleatorios reales) criptográficamente sólidos en Javascript?
El requisito crucial: si el Javascript de a.com genera algunos números aleatorios, nadie más podrá predecir esos números aleatorios. Por ejemplo, Javascript en evil.com no debería poder predecir los números aleatorios que obtuvo a.com.
Resumen de lo que sé sobre este tema. Esto es lo que he podido encontrar, en mi propia investigación:
-
Todos los navegadores proporcionan
Math.random()
como una llamada de biblioteca para generar números pseudoaleatorios. Desafortunadamente, no proporciona números aleatorios de calidad criptográfica y no cumple con el requisito anterior. En los navegadores que he visto,Math.random()
usa un PRNG no criptográfico, y su estado interno se comparte en varios sitios. Por lo tanto, evil.com puede llamar aMath.random()
varias veces, recuperar el estado interno del PRNG y luego inferir qué números aleatorios obtuvo a.com cuando llamó aMath.random()
. Además, utiliza un PRNG de calidad no criptográfica, por lo que si a.com genera una clave aleatoria y un IV aleatorio utilizandoMath.random()
y luego publica el IV, podría ser posible inferir el estado interno del PRNG (del IV) y luego recuperar la clave. Entonces,Math.random()
está fuera de lugar. -
Encontré un artículo de investigación que analiza la criptografía en Javascript. Su código, la Biblioteca de criptografía de Javascript de Stanford , está disponible públicamente. Incluye un número pseudoaleatorio de fuerza criptográfica.
Sin embargo, parece que tiene una limitación considerable: si estoy leyendo el documento correctamente, se requieren entre 10 y 40 segundos de interacción del usuario con su sitio antes de que el número pseudoaleatorio se coteja adecuadamente. Además, cada sitio tiene que volver a empezar desde cero: si a.com incluye la biblioteca SJCL, parece que el script de a.com tiene que esperar a que el usuario interactúe con el sitio a.com durante 10-40 segundos (normalmente) antes de que a.com pueda generar números aleatorios de calidad criptográfica. Esta es una limitación bastante significativa.
Aquí está su papel:
- Emily Stark, Michael Hamburg, Dan Boneh. Criptografía simétrica rápida en Javascript . ACSAC 2009.
-
El ensayo clásico, Criptografía de Javascript considerada dañina , menciona la falta de una buena manera de Obtenga números aleatorios de criptografía en Javascript como una barrera importante para hacer criptografía segura en Javascript. El ensayo considera varios enfoques obvios y explica por qué tienen defectos.
La conclusión es que no conozco ninguna solución razonable; Las opciones que encontré parecen bastante problemáticas. Sin embargo, han pasado varios años desde que se escribieron esos documentos y ensayos, y sé que la tecnología web puede cambiar rápidamente. ¿Alguien sabe de alguna buena solución a este problema?