2014-12-04 46 views
5

说我有一些Python代码:Python:其中是random.random()播种?

import random 
r=random.random() 

哪里是r的值在一般接种?
而如果我的操作系统没有随机的话,那么它在哪里播种?
为什么不推荐用于密码学?有什么方法可以知道随机数是什么?

+0

[这里](http://stackoverflow.com/questions/10341112/whats-more来到-random-hashlib-or-urandom)你有类似的问题。 – Marcin 2014-12-04 02:01:06

回答

10

关注da代码

要看看那里的random模块“住”在你的系统,你可以在终端中执行:

>>> import random 
>>> random.__file__ 
'/usr/lib/python2.7/random.pyc' 

这使你的路径.pyc(“编译”)的文件,通常是与原始.py并排放置,其中可以找到可读代码。

让我们看看这是怎么回事在/usr/lib/python2.7/random.py

你会看到,它创建了Random类的一个实例,然后(在文件的底部),“促进”该实例的方法,以模块的功能。整洁的把戏。当random模块被导入到任何地方时,将创建该类Random的新实例,然后对其值进行初始化并将方法重新分配为模块的功能(使其在每次导入的基础上非常随机)

_inst = Random() 
seed = _inst.seed 
random = _inst.random 
uniform = _inst.uniform 
triangular = _inst.triangular 
randint = _inst.randint 

,这Random类确实在其__init__方法的唯一事情是播种之:

class Random(_random.Random): 
    ... 
    def __init__(self, x=None): 
     self.seed(x)  
... 
_inst = Random() 
seed = _inst.seed 

所以...如果xNone会发生什么(无种子已指定)?好吧,让我们检查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 

Tadaaa ...种子是从os.urandom

来到一个16字节数比方说,我们正处在一个文明的操作系统,如Linux(具有真实随机数发生器)。由random模块使用的种子是一样的做:

>>> long(binascii.hexlify(os.urandom(16)), 16) 
46313715670266209791161509840588935391L 

为什么指定的种子值的原因被认为没有那么大是,random功能是不是真正的“随机” ......他们这只是一个非常奇怪的数字序列。但是,鉴于相同的种子,该序列将是相同的。你可以试试这个自己:

>>> import random 
>>> random.seed(1) 
>>> random.randint(0,100) 
13 
>>> random.randint(0,100) 
85 
>>> random.randint(0,100) 
77 

无论何时或如何,甚至在那里您运行的代码(只要用于生成随机数的算法保持不变),如果你的种子是1,你总是会得到整数13,85,77 ......哪种破坏目的(见this关于伪随机数的产生)另一方面,有use cases这实际上可能是一个理想的功能,但。

这就是为什么依靠操作系统随机数生成器被认为是“更好”的原因。这些通常基于硬件中断进行计算,这些中断非常非常随机(它包括用于硬盘驱动器读取的interruptions,由用户键入的击键,移动鼠标......)在Linux中,该O.S.发电机是/dev/random。或者,有点挑剔,/dev/urandom(这是Python的os.urandom实际内部使用的)。区别在于(如前所述)/dev/random使用硬件中断来生成随机序列。如果没有中断,/dev/random可能会用尽,你可能要等一会儿,直到你可以得到下一个随机数。 /dev/urandom在内部使用/dev/random,但它保证它将始终为您准备随机数。

如果您正在使用Linux,只是做cat /dev/random终端上(并准备打按Ctrl + C,因为这将真正开始输出,真正随机的东西)

[email protected]:/tmp$ cat /dev/random 
_+�_�?zta����K�����q�ߤk��/���qSlV��{�Gzk`���#p$�*C�F"�B9��o~,�QH���ɭ�f�޺�̬po�2o�(=��t�0�p|m�e 
���-�5�߁ٵ�ED�l�Qt�/��,uD�w&m���ѩ/��;��5Ce�+�M���� 
~ �4D��XN��?ס�d��$7Ā�kte▒s��ȿ7_���-  �d|����cY-�j>� 
        �b}#�W<դ���8���{�1» 
.  75���c4$3z���/̾�(�(���`���k�fC_^C 

Python使用OS随机发电机或时间作为种子。这意味着,当它用在我能想象用Python的random模块潜在的弱点的地方是:

  • 在OS没有实际的随机数发生器,
  • 在一个装置,其time.time是始终报告相同时间(有一个破碎的时钟,基本上)

如果你关心random模块的实际随机性,你可以直接去os.urandom或使用随机数根儿ator pycrypto加密库。那些大概是更随机。我说更随机因为......

https://stackoverflow.com/a/2146062/289011

形象的灵感来自这个其他SO answer

+0

拥有真正的随机性并不总是更好。 OP确实询问了密码学问题,但即使如此,您应该知道您使用的数据是什么(例如,Salsa将始终从0开始产生0)。播种一个伪随机数发生器对于可复制但任意的数据非常有用,特别是对于随机生成的游戏中的可重复测试或共享水平。 – 2014-12-04 14:33:42

+0

@YannVernier,正确,正确。这就是为什么我添加了一个澄清,说有时使用相同的种子作为一个功能是可取的。 – BorrajaX 2014-12-04 14:35:43

+2

非常详细的答案。 – LonelyWebCrawler 2014-12-04 17:20:54