简体   繁体   English

python SystemRandom / os.urandom是否总有足够的熵来获得良好的加密

[英]Will python SystemRandom / os.urandom always have enough entropy for good crypto

I have a password generator: 我有一个密码生成器:

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))

According to the docs, SystemRandom uses os.urandom which uses /dev/urandom to throw out random cryto bits. 根据文档,SystemRandom使用os.urandom,它使用/ dev / urandom来丢弃随机的cryto位。 In Linux you can get random bits from /dev/urandom or /dev/random, they both use whatever entropy the kernel can get its hands on. 在Linux中,您可以从/ dev / urandom或/ dev / random获取随机位,它们都使用内核可以获得的任何熵。 The amount of entropy available can be checked with tail /proc/sys/kernel/random/entropy_avail, this will return a number like: 129. The higher the number more entropy is available. 可以使用tail / proc / sys / kernel / random / entropy_avail检查可用的熵量,这将返回如下数字:129。可用的熵越多。 The difference between /dev/urandom and /dev/random is that /dev/random will only spit out bits if entropy_avail is high enough (like at least 60) and /dev/urandom will always spit out bits. / dev / urandom和/ dev / random之间的区别在于/ dev / random只会在entropy_avail足够高(如至少60)时吐出位,而/ dev / urandom总是吐出位。 The docs say that /dev/urandom is good for crypto and you only have to use /dev/random for ssl certs and the like. 文档说/ dev / urandom对加密有好处,你只需要使用/ dev / random来获得ssl证书等。

My question is will gen_pass be good for making strong crypto grade passwords always? 我的问题是gen_pass是否适合制作强大的加密级密码? If I call this function as quickly as possible will I stop getting strong cryto bits at some point because the entropy pool is depleted? 如果我尽快调用此函数,我会在某个时刻停止获取强大的cryto位,因为熵池已经耗尽了吗?

The question could also be why does /dev/urandom always produce strong cryto bits and not care about the entropy_avail? 这个问题也可能是为什么的/ dev / urandom的总是产生强烈cryto位不会在乎entropy_avail?

It is possible that /dev/urandom is designed so that its bandwidth is capped by the number of cycles you can guess will be correlated with an amount of entropy, but this is speculation and I can't find an answer. 有可能设计/ dev / urandom使其带宽受到可以猜测与熵量相关的周期数的限制,但这是猜测,我无法找到答案。

Also this is my first stackoverflow question so please critique me. 这也是我的第一个stackoverflow问题所以请批评我。 I am concerned that I gave to much background when someone who knows the answer probably knows the background. 我担心当知道答案的人可能知道背景时,我给了很多背景。

Thanks 谢谢

update 更新

I wrote some code to look at the entropy pool while the /dev/urandom was being read from: 我写了一些代码来查看/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)

If run this and also run: 如果运行此并运行:

while 1 > 0:
    gen_pass()

Then I pretty reliablly get a graph that looks like this: 然后我非常可靠地得到一个如下图: 在此输入图像描述

Making the graph while running cat /dev/urandom looks smiler and cat /dev/random drops off to nothing and stays low very quickly (this also only reads out like a byte every 3 seconds or so) 在运行cat /dev/urandom同时制作图形看起来smiler和cat /dev/random下降到空,并且非常快地保持低电平(这也只是每隔3秒左右读出一个字节)

update 更新

If I run the same test but with six instances of gen_pass(), I get this: 如果我运行相同的测试,但有六个gen_pass()实例,我得到这个: 在此输入图像描述

So it looks like something is making it be the case that I have enough entropy. 所以看起来有些东西让我有足够的熵。 I should measure the password generation rate and make sure that it is actually being capped, because if it is not then something fishy may be going on. 我应该测量密码生成速率,并确保它实际上被限制,因为如果不是,那么可能会发生一些可疑的事情。

update 更新

I found this email chain 我找到了这个电子邮件链

This says that urandom will stop pulling entropy once the pool only has 128 bits in it. 这表示一旦池中只有128位,urandom将停止拉熵。 This is very consistent with the above results and means that in those tests I am producing junk passwords often. 这与上述结果非常一致,意味着在那些测试中我经常生成垃圾密码。

My assumption before was that if the entropy_avail was high enough (say above 64 bits) then /dev/urnadom output was good. 我之前的假设是,如果entropy_avail足够高(比如64位以上),那么/dev/urnadom输出就好了。 This is not the case it seems that /dev/urandom was designed to leave extra entropy for /dev/random in case it needs it. 事实并非如此/dev/urandom被设计为在需要时为/dev/random留下额外的熵。

Now I need to find out how many true random bits a SystemRandom call needs. 现在我需要找出SystemRandom调用需要多少个真正的随机位。

There's a subtle difference between the output of /dev/random and /dev/urandom . /dev/random/dev/urandom的输出之间存在细微差别。 As has been pointed out, /dev/urandom doesn't block. 正如已经指出的那样, /dev/urandom不会阻塞。 That's because it gets its output from a pseudo-random number generator, seeded from the 'real' random numbers in /dev/random . 这是因为它从伪随机数生成器获取其输出,从/dev/random的“真实”随机数播种。

The output of /dev/urandom will almost always be sufficiently random -- it's a high-quality PRNG with a random seed. /dev/urandom的输出几乎总是足够随机 - 它是一个带有随机种子的高质量PRNG。 If you really need a better source of random data, you could consider getting a system with a hardware random number generator -- my netbook has a VIA C7 in it, which can generate quite a lot of properly random data (I get a consistent 99.9kb/s out of /dev/random, 545kb/s out of /dev/urandom). 如果你真的需要一个更好的随机数据源,你可以考虑使用一个带有硬件随机数生成器的系统 - 我的上网本中有一个VIA C7,它可以生成大量正确的随机数据(我得到了一致的99.9) kb / s出/ dev / random,545kb / s出/ dev / urandom)。

As an aside, if you're generating passwords then you might want to look at pwgen -- it makes nice pronounceable passwords for you :). pwgen ,如果你正在生成密码,那么你可能想看看pwgen - 它为你提供了很好的可pwgen密码:)。

/dev/random/ will block on read if it needs more entropy. 如果需要更多熵, /dev/random/将阻止读取。 /dev/urandom/ won't. /dev/urandom/不会。 So yes, if you use it too fast you'll run low on entropy. 所以,是的,如果你使用得太快,你的熵就会很低。 Probably still quite hard to guess, of course, but if you're really concerned you can read bytes from /dev/random/ instead. 当然,可能仍然很难猜测,但如果您真的担心,可以从/dev/random/读取字节。 Ideally, with a non-blocking read loop and a progress indicator so you can move the mouse around and generate entropy if needed. 理想情况下,使用非阻塞读取循环和进度指示器,以便您可以移动鼠标并在需要时生成熵。

You might want to read this about why /dev/urandom is the way to go: 您可能想要了解为什么/ dev / urandom是要走的路:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM