2012-04-26 18 views
15

Estoy trabajando en un proyecto con un amigo donde tenemos que generar un hash aleatorio. Antes de tener tiempo para debatir, ambos nos presentamos con diferentes enfoques y, debido a que están utilizando diferentes módulos, quería preguntarles todo lo que sería mejor, si es que existe tal cosa.¿Qué es más aleatorio, hashlib o urandom?

hashlib.sha1(str(random.random())).hexdigest() 

o

os.urandom(16).encode('hex') 

Escribiendo a cabo esta pregunta me tiene pensando que el segundo método es mejor. Simple es mejor que complejo. Si está de acuerdo, ¿qué tan confiable es esto para generar hashes 'aleatoriamente'? ¿Cómo probaría esto?

Respuesta

36

Esta solución:

os.urandom(16).encode('hex') 

es la mejor ya que uses the OS para generar aleatoriedad, que debe ser utilizable para propósitos criptográficos (depende de la implementación del sistema operativo).

random.random() genera pseudo-random values.

Hashing un valor aleatorio no agrega ninguna nueva aleatoriedad.

+0

Estos son todos muy grandes respuestas. Gracias. – Flowpoke

+0

AttributeError: el objeto 'bytes' no tiene ningún atributo 'codificar' – treecoder

+0

@greengit: es probable (muy alto) que el fragmento pequeño anterior esté dirigido a la versión Python 2.x (no probado en 3.x) – ChristopheD

2

Probando la aleatoriedad es notoriamente difícil, sin embargo, yo elegiría el segundo método, pero ÚNICAMENTE (o, solo por lo que se me viene a la mente) para este caso, donde el hash es sembrado por un número aleatorio.

El punto de hash es la creación de un número que es muy diferente basado en ligeras diferencias en la entrada. Para su caso de uso, la aleatoriedad de la entrada debería hacer. Sin embargo, si deseaba hacer un hash de un archivo y detectar la diferencia de un solo byte, entonces es cuando brilla un algoritmo hash.

Sin embargo, tengo curiosidad: ¿por qué utilizar un algoritmo hash en absoluto? Parece que está buscando un número puramente aleatorio, y hay muchas bibliotecas que generan uuid, que tienen garantías de exclusividad mucho más sólidas que los generadores de números aleatorios.

7

random.random() es un generador de pseudo-radmom, que significa que los números se generan a partir de una secuencia. si llama al random.seed(some_number), luego de eso la secuencia generada siempre será la misma.

os.urandom() obtener los números aleatorios del os 'rng, que utiliza un grupo de entropía para recopilar números aleatorios reales, generalmente por eventos aleatorios de dispositivos de hardware, existen incluso generadores de entropía especiales aleatorios para sistemas donde hay muchos números aleatorios generado.

en el sistema unix existen tradicionalmente dos generadores de números aleatorios: /dev/random y /dev/urandom. llama al primer bloque si no hay suficiente entropía disponible, mientras que cuando lee /dev/urandom y no hay suficientes datos de entropía disponibles, usa un pseudo-rng y no bloquea.

por lo que el uso depende generalmente de lo que necesita: si necesita unos pocos números aleatorios igualmente distribuidos, entonces el prng incorporado debería ser suficiente. para el uso criptográfico siempre es mejor usar números aleatorios reales.

7

La segunda solución tiene claramente más entropía que la primera.Suponiendo que la calidad de la fuente de los bits aleatorios sería el mismo para os.urandom y random.random:

  • En la segunda solución estás obteniendo los 16 bytes = 128 bits por valor de aleatoriedad
  • En la primera solución esté recogiendo un valor de coma flotante que tiene aproximadamente 52 bits de aleatoriedad (doble IEEE 754, ignorando los números subnormales, etc.). Luego lo tienes todo, lo que, por supuesto, no agrega ninguna aleatoriedad.

Más importante aún, se espera que la calidad de la aleatoriedad procedentes de os.urandom y documentado a ser mucho mejor que el azar procedentes de random.random. El docstring os.urandom dice "adecuado para uso criptográfico".

Cuestiones relacionadas