使用 AES 生成随机数是否安全?

信息安全 随机的
2021-09-03 18:53:58

我知道已经有工具可以生成加密随机数,但我想知道使用 AES 是否可以做到这一点。

例如,我的服务器上有一个 AES 密钥,我的数据库中有一个计数器。每次我想生成一个随机数时,我都会增加计数器,然后使用服务器上的密钥使用 AES 对其进行加密,然后将生成的位转换为正确的数字。

只要找不到我的密钥,这不会产生安全的随机数吗?

注意:如果您想说在服务器上存储密码不安全,请说明它与在服务器上存储私有 SSL 密钥有何不同。

编辑

在维基百科上找到了一些信息

通过在计数器模式下运行,可以将安全分组密码转换为 CSPRNG。这是通过选择一个随机密钥并加密 0,然后加密 1,然后加密 2 等来完成的。计数器也可以从零以外的任意数字开始。显然,对于 n 位分组密码,周期将是 2n;同样明显的是,初始值(即密钥和“明文”)不得为攻击者所知,无论这种 CSPRNG 构造有多好。否则,将失去所有安全性。

因此,它之前被用于构建 CSPRNG。

3个回答

您所描述的是一个自定义的、基于 AES 的PRNG使用 AES 和密钥加密计数器的连续值构建 PRNG 的一种合理方法(实际上,它等同于使用 AES/CTR 加密一长串零),前提是您注意以下事项:

  • 您必须“按原样”使用块密码:将计数器编码为单个 16 字节块,使用 AES 处理它(无“块密码模式”),获取接下来的 16 个伪随机字节。增加计数器,然后循环。

  • 这不会比加密密钥的保密性强。保管好钥匙!

  • 当然,这假设您已经有一个密钥,这意味着在某些时候使用了其他一些加密安全的 PRNG。PRNG 不会产生随机性,它会将一些初始随机性(“种子”,此处为 AES 密钥)扩展为长的伪随机字节流。

  • 此 PRNG 依赖于您从不重复使用计数器值。所以你必须确保计数器总是增加并且不能被强制“倒带”。这并不像看起来那么容易,特别是在嵌入式设备中,读写永久存储非常重要,用户(可能是攻击者)可以随时强制硬件重置(通过移除电池)。

  • AES 是一种分组密码,它是分组值空间的排列因此,它永远不会输出两次相同的 16 字节块,这与真正的随机源产生的结果不同。这可能会在大约 2 68个字节后(统计上)开始显示,这足够高,不会成为问题。但是,在尝试使用具有较小块(3DES、Blowfish...)的块密码的相同技巧之前,请三思而后行。

一个改进可能是在每次服务器启动时重新生成一个新的 AES 密钥,使用/dev/urandom. 这样,就没有密钥可以存储在任何地方。事实上,没有必要总是重复使用相同的密钥。

(可以说,使用已经存在的强 PRNG 甚至更简单,例如/dev/urandom。切换到像您设想的那样的自定义 PRNG 是完全没有根据的;除非您需要每秒超过 10 兆字节的伪随机字节,这可能发生在在某些情况下,但很奇怪。如果您需要大量伪随机字节,您可能需要考虑使用其他更专业的算法,例如这些流密码。)

从理论上讲,是的,但存在实际问题。

作为一个伪随机数生成器,它工作得很好。但是要从中制作 CSPRNG,您需要从加密安全的随机密钥开始......并且要获得加密安全的随机密钥,您需要一个 CSPRNG。这是一个先有鸡还是先有蛋的问题:为了使用 AES 构建 CSPRNG,您需要已经拥有一个 CSPRNG。

为什么要这么做?在大多数情况下,这没有多大意义:如果您可以访问 CSPRNG 来制作您的密钥,那么您不妨直接使用它。但是,在某些情况下它仍然有用。例如,如果您在无法访问 CSPRNG 的情况下进行编码,但您确实可以访问由一个密钥生成的密钥(并且您知道该密钥已被保密),那么您可以使用 AES 从密钥中生成加密安全的随机数。不过,其他答案中提到的实施问题仍然适用。

我认为输出确实应该看起来很随机。但是,您的私钥是已知的,这是非常可预测的。所以生成的数字几乎没有熵。我会将结果称为 PRNG,但绝不会称为 SPRNG 或 CSPRNG。