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.
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 utiliseraCryptGenRandom()
.
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.
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
.
Si vous voulez un nombre aléatoire n
bits, 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()
.
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)
Où 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.