Python:random.random()种子在哪里?
假设我有一些python代码:Python:random.random()种子在哪里?,python,random,cryptography,random-seed,Python,Random,Cryptography,Random Seed,假设我有一些python代码: import random r=random.random() 一般来说,r的值是从哪里来的? 如果我的操作系统没有随机,那么它的种子在哪里呢? 为什么不建议将其用于加密?有没有办法知道随机数是什么?遵循da代码 要查看random模块在系统中的位置,您只需在终端中执行以下操作: >>> import random >>> random.__file__ '/usr/lib/python2.7/random.pyc' 这为您
import random
r=random.random()
一般来说,r的值是从哪里来的?如果我的操作系统没有随机,那么它的种子在哪里呢?
为什么不建议将其用于加密?有没有办法知道随机数是什么?遵循da代码 要查看
random
模块在系统中的位置,您只需在终端中执行以下操作:
>>> import random
>>> random.__file__
'/usr/lib/python2.7/random.pyc'
这为您提供了.pyc
(“已编译”)文件的路径,该文件通常与原始.py
并排放置,在那里可以找到可读的代码
让我们看看/usr/lib/python2.7/random.py中发生了什么:
您将看到,它创建了Random
类的一个实例,然后(在文件底部)将该实例的方法“升级”为模块函数。巧妙的把戏。当random
模块被导入到任何地方时,就会创建该random
类的一个新实例,然后初始化它的值,并将这些方法重新分配为模块的函数,使得它在每次导入(erm…或每个python解释器实例)的基础上都是随机的
这个Random
类在其\uuuuu init\uuuuu
方法中所做的唯一一件事就是对其进行种子设定:
class Random(_random.Random):
...
def __init__(self, x=None):
self.seed(x)
...
_inst = Random()
seed = _inst.seed
所以。。。如果x
为None
(未指定种子),会发生什么情况?好的,让我们检查一下self.seed
方法:
def seed(self, a=None):
"""Initialize internal state from hashable object.
None or no argument seeds from current time or from an operating
system specific randomness source if available.
If a is not None or an int or long, hash(a) is used instead.
"""
if a is None:
try:
a = long(_hexlify(_urandom(16)), 16)
except NotImplementedError:
import time
a = long(time.time() * 256) # use fractional seconds
super(Random, self).seed(a)
self.gauss_next = None
评论已经告诉我们发生了什么。。。此方法尝试使用操作系统提供的默认随机生成器,如果没有,则将使用当前时间作为种子值
但是,等等。。。那是什么鬼东西
答案就在这个random.py
文件的开头:
from os import urandom as _urandom
from binascii import hexlify as _hexlify
塔达阿。。。种子是一个16字节的数字,来自
假设我们在一个文明的操作系统中,比如Linux(带有一个真正的随机数生成器)。随机
模块使用的种子与执行以下操作相同:
>>> long(binascii.hexlify(os.urandom(16)), 16)
46313715670266209791161509840588935391L
之所以认为指定种子值不是很好,是因为随机
函数不是真正的“随机”。。。它们只是一个非常奇怪的数字序列。但如果是同一个种子,那么序列将是相同的。您可以自己尝试:
>>> import random
>>> random.seed(1)
>>> random.randint(0,100)
13
>>> random.randint(0,100)
85
>>> random.randint(0,100)
77
无论何时、如何或在何处运行该代码(只要用于生成随机数的算法保持不变),如果种子为1
,则始终会得到整数13
,85
,77
。。。另一方面,哪种类型会破坏目的(请参阅关于伪随机数生成的内容),这实际上是一种可取的特性
这就是为什么依赖操作系统随机数生成器被认为“更好”的原因。这些通常是基于硬件中断来计算的,在Linux中,O.S.generator是非常非常随机的(包括硬盘读取、用户键入的按键、移动鼠标……)。或者,有点挑剔,/dev/urandom
(这就是Python的os.urandom
实际上在内部使用的)区别在于(如前所述)/dev/random
使用硬件中断来生成随机序列。如果没有中断,/dev/random
可能会耗尽,您可能需要等待一段时间,直到获得下一个随机数/dev/urandom
在内部使用/dev/random
,但它保证它始终为您准备好随机数
如果您使用的是linux,只需在终端上执行cat/dev/random
(并准备点击Ctrl+C,因为它将开始输出非常非常随机的东西)
borrajax@borrajax:/tmp$cat/dev/random
_+�_�?zta����K�����Q�ߤk��/���qSlV��{�Gzk`���#p$�*C�F“�B9��o~,�QH���ɭ�F��̬po�你有一个类似的问题。拥有真正的随机性并不总是更好的。OP确实询问了加密技术,但即使这样,你也应该知道你使用数据的目的(例如,Salsa总是从0生成0)。植入伪随机数生成器对于可复制但任意的数据非常有用,特别是对于可重复测试或在随机生成的游戏中共享级别。@YannVernier,correct,correct。这就是为什么我添加了一个澄清注释,指出有时使用相同的种子作为一个功能是可取的。非常详细的答案。
>>> import random
>>> random.seed(1)
>>> random.randint(0,100)
13
>>> random.randint(0,100)
85
>>> random.randint(0,100)
77