【问题标题】:Generate nonce c++生成随机数 c++
【发布时间】:2015-07-19 12:55:47
【问题描述】:

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

【问题讨论】:

  • AFAIAA 它只是一个伪随机的字节序列。当然,您需要使用真正的随机源作为序列生成器的种子。
  • @RichardHodges:感谢您的回复。从必须保证在“会话”中仅生成一次的意义上说,nonce 应该是顺序的。与使用 RNG 生成 IV 相比,nonce 不会有任何额外的要求或需要做的事情吗?
  • @SkypeMeSM - 另见 Crypto++ wiki 上的 RandomNumberGenerator;和 Random Numbers 在 OpenSSL wiki 上。此外,NIST SP800-38CSP800-38D 有几种创建 nonce 的方法,因为 CCM 和 GCM 使用它们。另请参阅有关 CTR 模式的文档。我似乎还记得那里的讨论。
  • 谢谢@jww。 NIST 的建议将非常有帮助。我去看看。

标签: c++ openssl cryptography crypto++ nonce


【解决方案1】:

我想知道是否有办法使用 OpenSSL 或 Crypto++ 库生成加密随机数。

加密++

SecByteBlock nonce(16);
AutoSeededRandomPool prng;

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

OpenSSL

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 上的 What are the requirements of a nonce?

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      仅使用 API 提供的加密安全随机数生成器应该没问题 - 它们应该使用从操作系统获得的信息(可能还有其他数据)作为种子。将系统时间添加到种子数据中绝对不会有什么坏处。

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

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

      【讨论】:

      • @jww 抱歉,应该是最低有效位。有时随机数被用作计数器的起点,例如在 CTR 模式下(也用于大多数 AEAD 密码)。在这种情况下,实际的计数器有时只有 32 位宽。现在,如果随机数是完全随机的,那么这些位可能会全为零,这意味着与实现不兼容,例如使用所有 128 位作为计数器(并在 0xFFFFFFFF 之后创建一个进位)。
      猜你喜欢
      • 2012-03-18
      • 1970-01-01
      • 2011-01-24
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多