【问题标题】:Will python SystemRandom / os.urandom always have enough entropy for good cryptopython SystemRandom / os.urandom 是否总是有足够的熵来进行良好的加密
【发布时间】:2011-07-25 16:57:56
【问题描述】:

我有一个密码生成器:

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 来丢弃随机加密位。在 Linux 中,您可以从 /dev/urandom 或 /dev/random 获取随机位,它们都使用内核可以获得的任何熵。可用的熵量可以通过 tail /proc/sys/kernel/random/entropy_avail 检查,这将返回一个类似于:129 的数字。数字越高,可用的熵就越多。 /dev/urandom 和 /dev/random 之间的区别在于 /dev/random 仅在 entropy_avail 足够高(例如至少 60)时才会吐出位,而 /dev/urandom 将始终吐出位。文档说 /dev/urandom 对加密有好处,您只需将 /dev/random 用于 ssl 证书等。

我的问题是 gen_pass 是否总是适合制作强加密级密码?如果我尽快调用此函数,是否会因为熵池已耗尽而在某个时候停止获取强加密位?

问题也可能是为什么 /dev/urandom 总是 产生强加密位 不关心 entropy_avail?

有可能 /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()

然后我很可靠地得到一个如下所示的图表:

在运行 cat /dev/urandom 时制作图表看起来更微笑,而 cat /dev/random 下降到零并很快保持在低位(这也只是每 3 秒左右读取一个字节)

更新

如果我运行相同的测试但有六个 gen_pass() 实例,我会得到:

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

更新

我找到了这个email chain

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

我之前的假设是,如果 entropy_avail 足够高(比如高于 64 位),那么 /dev/urnadom 输出就很好。情况并非如此,似乎/dev/urandom 旨在为/dev/random 留下额外的熵以备不时之需。

现在我需要找出 SystemRandom 调用需要多少真正的随机位。

【问题讨论】:

  • 当然有可能——你可以从 /dev/urandom 中提取无限量的信息,而你没有无限量的熵。
  • 就像我上面说的,我认为你可以设计成这样是不可能的,但我没有理由相信这一点。我需要做更多的研究。
  • @Chris 怎么样?熵必须来自某个地方——你不能只是把它变魔术。如果可以,我们的生活会轻松很多。
  • 如果你假设熵生成的平均速率,然后你强制/dev/urandom 进程花费一定的时间(比如通过做一堆哈希),那么你可以或多或少地强制通过计算限制读取/dev/urandom 的带宽,可能存在足够的熵。这需要内核知道它通常以多快的速度生成熵并动态限制带宽,或者使用一些下限假设来生成熵。
  • @Chris urandom 的重点是返回所需的尽可能多的数据 - 如果您需要保证熵,/dev/random 存在。

标签: python linux random cryptography generator


【解决方案1】:

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

【讨论】:

  • /dev/random 实际上似乎直接从熵池中为您提供了位,并且从实验中熵很快耗尽。如果/dev/urandom 有可能失败,我想更多地了解它是如何做到的,以及你是否可以阻止它。如果您运行cat /dev/urandom 并向标准 IO 发送废话并定期检查 entropy_avail,那么 entropy_avail 似乎永远不会出现问题。这让我想知道内核是否正在使用打印/dev/urandom/的过程来制造更多的熵,我也想知道这是否可以接受。
  • 我记得他们是从同一个地方获取的,但random 会跟踪可用的熵并在需要更多时阻止。我想urandom 也会更新熵状态,因为有人可能随时使用random。你是如何检查 entropy_avail 的?无论如何,我会说使用 urandom 并通过安全哈希函数将其传递给几乎任何应用程序都足够安全。
【解决方案2】:

/dev/random/dev/urandom 的输出之间存在细微差别。正如已经指出的那样,/dev/urandom 不会阻塞。那是因为它的输出来自一个伪随机数生成器,从/dev/random 中的“真实”随机数中播种。

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

顺便说一句,如果您正在生成密码,那么您可能需要查看pwgen——它为您提供了很好的发音密码:)。

【讨论】:

  • Rite,我想我已经向自己证明了这会很好,但要确保安全的硬件是要走的路。现在我只需要弄清楚如何将我的盖革计数器连接到串行端口......
  • This answer is incorrectrandomurandom 从 PRNG 中检索它们的值。 random 会在熵池中的熵太少时阻塞,但是当您重新启动机器时,熵会被存储并重新加载,因此它几乎不会耗尽。 urandom 唯一可以给出“低熵 PRNG 值”的情况是,如果您刚刚安装了机器并立即从 /dev/urandom 读取数据。
【解决方案3】:

您可能想阅读这篇文章,了解为什么 /dev/urandom 是要走的路:

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

【讨论】:

    猜你喜欢
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 2010-09-11
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    相关资源
    最近更新 更多