2

我想知道是否有一种方法可以使用 OpenSSL 或 Crypto++ 库生成加密随机数。除了使用自动种子池生成一组随机字节之外,还有什么其他的吗?

4

3 回答 3

6

我想知道是否有一种方法可以使用 OpenSSL 或 Crypto++ 库生成加密随机数。

加密++

SecByteBlock nonce(16);
AutoSeededRandomPool prng;

prng.GenerateBlock(nonce, nonce.size());

开放式SSL

unsigned char nonce[16];
int rc = RAND_bytes(nonce, sizeof(nonce));
unsigned long err = ERR_get_error();

if(rc != 1) {
    /* RAND_bytes failed */
    /* `err` is valid    */
}

/* OK to proceed */

除了使用自动种子池生成一组随机字节之外,还有什么其他的吗?

nonce 基本上是一个 IV。它通常被认为是一个公共参数,如 IV 或 Salt。

随机数在安全上下文中必须是唯一的。你也可能需要一个 nonce 来不可预测。

唯一性和不可预测性是两个不同的属性。例如,从 开始的计数器0000000000000000是唯一的,但它也是可预测的。

当您需要唯一性和不可预测性时,您可以将 nonce 划分为随机值和计数器。随机值将占用 16 字节 nonce 中的 8 个字节;而计数器将占用 16 字节随机数的剩余 8 字节。然后,您使用增量函数基本上在i++每次需要值时执行。

您不需要8-8拆分。12-4 和 4-12 一样有效。这取决于应用程序和重新加密之前所需的随机数。密钥更新通常由纯文本字节数驱动。

16-0 也有效。在这种情况下,您使用的是随机值,避免使用计数器,并避免使用增量函数。(增量函数基本上是级联添加)。

NIST SP800-38CSP800-38D提供了几种创建 nonce 的方法,因为 CCM 和 GCM 使用它们。

另请参阅随机数的要求是什么?在 Crypto Stack Exchange 上。

于 2015-05-09T10:45:46.860 回答
2

您需要为每个随机数设置一个唯一编号。您可以使用序列号或随机数。为了帮助确保唯一性,虽然不是必需的,但通常会向 nonce 添加时间戳。将时间戳作为单独的字段传递或将其与随机数连接。有时还会添加 IP 地址和进程 ID 等信息。

当您使用序列号时,您无需担心会跳过数字。没关系。只要确保你永远不会重复。它在您的软件重新启动时必须是唯一的。这是添加时间戳可以提供帮助的一个地方。因为毫秒时间+序列号几乎可以肯定在服务器重新启动时是唯一的。

对于伪随机数生成器,任何人都应该没问题。只需确保您使用足够大的空间,以使获得副本的机会实际上是不可能的。同样,增加时间将减少您获得重复的可能性,因为您需要在同一毫秒内两次获得相同的随机数。

您可能希望对 nonce 进行散列以隐藏其中的数据(例如:进程 ID),尽管只有在 nonce 中包含安全随机数时散列才是安全的。否则,nonce 的查看者可能会猜测组件并通过重做散列进行验证(即:他们猜测时间并尝试所有可能的 proc ID)。

于 2015-05-08T15:42:19.673 回答
2

不。如果随机数足够大,那么自动种子 DRBG(确定性随机位生成器 - NIST 命名法)就可以了。我建议使用大约 12 个字节的随机数。如果 nonce 需要 16 个字节,那么您可以将最低有效位 - 通常是最右边的字节 - 设置为零以实现最大兼容性。

只需使用 API 提供的加密安全随机数生成器就可以了——它们应该使用从操作系统获得的信息(可能还有其他数据)作为种子。只是为了确定,将系统时间添加到种子数据中永远不会有什么坏处。

或者,您可以使用序列号,但这需要您保持某种状态,这在调用中可能很难。请注意,有许多陷阱可能会让时钟重复自身(夏令时、操作系统更改、电池没电等)。

仔细检查随机数生成器是否不会重复足够大的输出永远不会有什么坏处。仅存在编程或系统配置错误的问题,例如,在对 Debian 进行静态代码分析后的修复导致 OpenSSL RNG 根本没有播种

于 2015-05-09T00:41:59.480 回答