python SystemRandom/os.urandom总是有足够的熵来实现好的cryp吗

2024-05-16 09:33:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个密码生成器:

import random, string

def gen_pass():
    foo = random.SystemRandom()
    length = 64
    chars = string.letters + string.digits
    return ''.join(foo.choice(chars) for _ in xrange(length))

根据文档,SystemRandom使用os.urandom,它使用/dev/urandom抛出随机cryto位。在Linux中,您可以从/dev/urandom或/dev/random中获取随机位,它们都使用内核可以使用的任何熵。可用的熵量可以用tail/proc/sys/kernel/random/entropy-avail进行检查,这将返回一个类似于:129的数字。数值越高,可用的熵就越多。/dev/urandom和/dev/random的区别在于,只有当熵可用性足够高(至少60)时,/dev/random才会吐出位,/dev/urandom总是吐出位。文档中说/dev/urandom适合加密,您只需要对ssl证书等使用/dev/random。

我的问题是,genúpass是否有助于始终生成强加密级密码?如果我尽快调用这个函数,我会不会因为熵池耗尽而在某个时刻停止得到强cryto比特?

问题还可能是为什么/dev/urandom总是产生强cryto位不关心熵的效用?

有可能是/dev/urandom的设计使其带宽被你能猜到的循环次数所限制,这将与熵量相关,但这是推测,我找不到答案。

这也是我的第一个stackoverflow问题,请批评我。我担心,当知道答案的人可能知道背景时,我给了很多背景。

谢谢

更新

当从中读取/dev/urandom时,我编写了一些代码来查看熵池:

import subprocess
import time

from pygooglechart import Chart
from pygooglechart import SimpleLineChart
from pygooglechart import Axis

def check_entropy():
    arg = ['cat', '/proc/sys/kernel/random/entropy_avail']
    ps = subprocess.Popen(arg,stdout=subprocess.PIPE)
    return int(ps.communicate()[0])

def run(number_of_tests,resolution,entropy = []):
    i = 0
    while i < number_of_tests:        
        time.sleep(resolution)
        entropy += [check_entropy()]
        i += 1
    graph(entropy,int(number_of_tests*resolution))

def graph(entropy,rng):    
    max_y = 200    
    chart = SimpleLineChart(600, 375, y_range=[0, max_y])
    chart.add_data(entropy)
    chart.set_colours(['0000FF'])
    left_axis = range(0, max_y + 1, 32)
    left_axis[0] = 'entropy'
    chart.set_axis_labels(Axis.LEFT, left_axis)    
    chart.set_axis_labels(Axis.BOTTOM,['time in second']+get_x_axis(rng))
    chart.download('line-stripes.png')

def get_x_axis(rng):
    global modnum        
    if len(filter(lambda x:x%modnum == 0,range(rng + 1)[1:])) > 10:
        modnum += 1
        return get_x_axis(rng)
    return filter(lambda x:x%modnum == 0,range(rng + 1)[1:])

modnum = 1
run(500,.1)

如果运行此命令并同时运行:

while 1 > 0:
    gen_pass()

然后我很可靠地得到了一个这样的图表: enter image description here

在运行cat /dev/urandom时生成图形看起来更可笑,并且cat /dev/random会变得毫无意义,并且很快保持低位(这也只是每3秒左右读取一个字节)

更新

如果我运行相同的测试,但使用了6个gen_pass()实例,则会得到以下结果: enter image description here

所以看起来好像有什么东西使我有足够的熵。我应该测量密码生成率,并确保它实际上是被封顶的,因为如果不是,那么可能会发生一些可疑的事情。

更新

我找到这个email chain

这表明,一旦池中只有128位,天王星将停止拉熵。这与上述结果非常一致,意味着在这些测试中,我经常生成垃圾密码。

我以前的假设是,如果熵效用足够高(比如64位以上),那么/dev/urnadom输出是好的。不是这样的,似乎/dev/urandom是为了给/dev/random留下额外的熵,以备需要。

现在我需要找出一个系统随机调用需要多少真正的随机位。


Tags: devimport密码returndefchartrangerandom
3条回答

您可能想了解一下为什么/dev/urandom是解决问题的方法:

http://www.2uo.de/myths-about-urandom/

如果需要更多的熵,/dev/random/将在读取时阻塞。/dev/urandom/不会。所以是的,如果你用得太快,你的熵就会很低。当然,可能仍然很难猜测,但是如果您真的很担心,可以从/dev/random/读取字节。理想情况下,有一个非阻塞的读取循环和一个进度指示器,这样您可以移动鼠标,并在需要时生成熵。

/dev/random/dev/urandom的输出之间有一个细微的区别。正如已经指出的,/dev/urandom不会阻塞。这是因为它的输出来自一个伪随机数生成器,它的种子来自/dev/random中的“实”随机数。

/dev/urandom的输出几乎总是足够随机的——它是一个带有随机种子的高质量PRNG。如果你真的需要一个更好的随机数据源,你可以考虑使用硬件随机数生成器——我的上网本有一个VIA C7,它可以生成大量正确的随机数据(我从/dev/random中得到一致的99.9kb/s,从/dev/urandom中得到545kb/s)。

另外,如果您正在生成密码,那么您可能需要查看^{}——它为您提供了很好的可发音密码:)。

相关问题 更多 >