web-dev-qa-db-fra.com

Comment créer un nombre aléatoire sécurisé par cryptographie en python?

Je crée un projet en python et j'aimerais créer un nombre aléatoire sûr sur le plan cryptographique. Comment puis-je le faire? J'ai lu en ligne que les nombres générés par le randomizer standard ne sont pas sécurisés sur le plan cryptographique et que la fonction os.urandom(n) me renvoie une chaîne et non un nombre. 

56
user2835118

Vous pouvez obtenir une liste de nombres aléatoires en appliquant simplement ord fonction sur les octets renvoyés par os.urandom , comme ceci

>>> import os
>>> os.urandom(10)
'm\xd4\x94\x00x7\xbe\x04\xa2R'
>>> type(os.urandom(10))
<type 'str'>
>>> map(ord, os.urandom(10))
[65, 120, 218, 135, 66, 134, 141, 140, 178, 25]

En citant la documentation os.urandom,

Renvoie une chaîne de n octets aléatoires convenant à une utilisation cryptographique.

Cette fonction renvoie des octets aléatoires à partir d'une source aléatoire spécifique au système d'exploitation. Les données renvoyées doivent être suffisamment imprévisibles pour les applications cryptographiques, même si leur qualité exacte dépend de la mise en œuvre du système d'exploitation. Sur un système de type UNIX, ceci interrogera /dev/urandom et, sous Windows, il utilisera CryptGenRandom().

39
thefourtheye

Puisque vous voulez générer des entiers dans une plage spécifique, il est beaucoup plus facile d'utiliser la classe random.SystemRandom à la place. La création d'une instance de cette classe vous donne un objet qui supporte toutes les méthodes du module random, mais en utilisant os.urandom() sous les couvertures. Exemples:

>>> from random import SystemRandom
>>> cryptogen = SystemRandom()
>>> [cryptogen.randrange(3) for i in range(20)] # random ints in range(3)
[2, 2, 2, 2, 1, 2, 1, 2, 1, 0, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0]
>>> [cryptogen.random() for i in range(3)]  # random floats in [0., 1.)
[0.2710009745425236, 0.016722063038868695, 0.8207742461236148]

Etc. En utilisant urandom() directement, vous devez inventer vos propres algorithmes pour convertir les octets aléatoires qu’elle produit en résultats souhaités. Ne faites pas ça ;-) SystemRandom le fait pour vous.

Notez cette partie de la documentation:

classe random.SystemRandom ([graine]) 

Classe qui utilise la fonction os.urandom () pour générer des nombres aléatoires à partir de sources fournies par le système d'exploitation. Non disponible sur tous les systèmes. Ne repose pas sur l'état du logiciel et les séquences ne sont pas reproductibles. En conséquence, les méthodes seed () et jumpahead () sont sans effet et sont ignorées. Les méthodes getstate () et setstate () génèrent NotImplementedError si elles sont appelées.

59
Tim Peters

Python 3.6 introduit un nouveau module secrets , qui "donne accès à la source de hasard la plus sûre fournie par votre système d'exploitation". Afin de générer des numéros sécurisés sur le plan cryptographique, vous pouvez appeler secrets.randbelow() .

secrets.randbelow(n)

qui retournera un nombre compris entre 0 et n.

23
Cody Piersall

Si vous voulez un nombre aléatoire nbits, sous Python 2.4+, la méthode la plus simple que j'ai trouvée est

import random
random.SystemRandom().getrandbits(n)

Notez que SystemRandom utilise os.urandom(); le résultat de cette méthode est donc aussi bon que l'implémentation de votre système urandom().

6
jjlin

Pour générer un entier pseudo-aléatoire cryptographiquement sécurisé, vous pouvez utiliser le code suivant:

int(binascii.hexlify(os.urandom(n)),16)

n est un entier et, plus n est grand, plus l'entier généré est grand.

Vous devrez d'abord importer os et binascii.

Le résultat de ce code peut varier selon la plate-forme.

0
TheGamePlayer 40