【问题标题】:linux's /dev/urandom forward predictionlinux /dev/urandom 前向预测
【发布时间】:2011-10-19 05:59:00
【问题描述】:

这是一个关于/dev/urandom 的Linux 内核实现的问题。如果用户要求读取大量数据(千兆字节)并且熵没有添加到池中,是否可以根据当前数据预测从 urandom 生成的下一个数据?

通常的情况是熵经常被添加到池中,但在我的情况下,我们可以考虑,没有额外的熵(例如,添加它被内核补丁禁用)。所以在我的情况下,问题是关于 urandom 算法本身。

来源是 /drivers/char/random.c 或 http://www.google.com/codesearch#KMCRKdMbI4g/drivers/char/random.c&q=urandom%20linux&type=cs&l=116

http://lxr.linux.no/linux+v3.3.3/drivers/char/random.c

 // data copying loop
    while (nbytes) {
            extract_buf(r, tmp);

            memcpy(buf, tmp, i);
            nbytes -= i;
            buf += i;
            ret += i;
    }

static void extract_buf(struct entropy_store *r, __u8 *out)
{
        int i;
        __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
        __u8 extract[64];

        /* Generate a hash across the pool, 16 words (512 bits) at a time */
        sha_init(hash);
        for (i = 0; i < r->poolinfo->poolwords; i += 16)
                sha_transform(hash, (__u8 *)(r->pool + i), workspace);

        /*
         * We mix the hash back into the pool to prevent backtracking
         * attacks (where the attacker knows the state of the pool
         * plus the current outputs, and attempts to find previous
         * ouputs), unless the hash function can be inverted. By
         * mixing at least a SHA1 worth of hash data back, we make
         * brute-forcing the feedback as hard as brute-forcing the
         * hash.
         */
        mix_pool_bytes_extract(r, hash, sizeof(hash), extract);

        /*
         * To avoid duplicates, we atomically extract a portion of the
         * pool while mixing, and hash one final time.
         */
        sha_transform(hash, extract, workspace);
        memset(extract, 0, sizeof(extract));
        memset(workspace, 0, sizeof(workspace));

        /*
         * In case the hash function has some recognizable output
         * pattern, we fold it in half. Thus, we always feed back
         * twice as much data as we output.
         */
        hash[0] ^= hash[3];
        hash[1] ^= hash[4];
        hash[2] ^= rol32(hash[2], 16);
        memcpy(out, hash, EXTRACT_SIZE);
        memset(hash, 0, sizeof(hash));
}

有防止回溯的机制,但是“正向追踪”呢?

例如:我从 urandom 执行了 500 MB 的单次读取系统调用,并且知道所有高达 200 MB 的数据并且池中没有额外的熵,我可以预测第 201 MB 将是多少?

【问题讨论】:

标签: random cryptography linux-kernel


【解决方案1】:

“加密性强的伪随机数生成器”的定义是在计算上无法将其输出与真正的随机数生成器区分开来。如果您可以从过去的输出中预测未来的输出,那么您就可以区分;所以,除非Linux urandom算法很弱,否则你不能这样做。

在我看来,该代码不像任何标准的伪随机生成器——Linux 人有“自己滚动”的不幸习惯——但无论如何,打破它可能是一个可发布的结果。所以如果它是易碎的,我怀疑它并不容易。

当然,设计的目的是让“否”成为您问题的答案。

[编辑]

当然,在信息论的意义上,答案是“是”,因为你不能从有限熵中得到无限熵。但是从信息论的意义上说,除了一次性密码之外,没有其他安全密码。我假设您在询问实用/加密意义。

[编辑 2]

稍微搜索一下this paper,它声称证明了对Linux /dev/urandom 中“前向安全性”的攻击。 (也就是说,给定生成器的状态,尝试重构早期的状态。)

这就是为什么程序员应该永远尝试发明自己的密码学。不管你认为自己多么聪明,一些以此为生的以色列学者会让你看起来很愚蠢。

也就是说,我没有看到任何针对生成器的输出的攻击,这就是你要问的。

【讨论】:

  • 循环的 Sha1 是 PRNG,不是吗?我问这个,因为我很感兴趣,是否有可能将大随机输出与真正的随机(或真正的加密数据)区分开来。
  • 是的,这就是他们想要实现的目标。但我不知道这个特定的公式是否已经发布,由该领域的真正专家分析(没有一个 Linux 开发人员符合条件)等等。但是,由于他们作为输出提供的只是内部状态的 SHA-1,并且他们只会“搅拌”该输出,这不会泄漏有关内部状态本身的信息。因此,从过去确定未来的输出看起来很困难。
【解决方案2】:

原则上,是的,您可以预测。当没有可用的熵时,dev/urandom 成为 PRNG,并且一旦知道其内部状态,原则上就可以预测其输出。实际上并不是那么简单,因为内部状态相当大,并且哈希函数阻止我们从输出向后工作。可以通过反复试验来确定,但这可能需要很长时间。

【讨论】:

  • “哈希函数阻止我们向后工作”但我想继续前进。
  • 如果我们没有池内部状态,答案是否定的?
  • @osgx:散列函数意味着您必须猜测全部或部分内部状态,而不是从输出向后工作。没有内部状态和熵的 PRNG 只能输出一个数字。
  • urandom 是 CSPRNG 而不是 PRNG
猜你喜欢
  • 2017-11-17
  • 1970-01-01
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2013-04-27
  • 2020-05-15
相关资源
最近更新 更多