我想知道是否有办法使用OpenSSL或Crypto ++库生成Cryptographic Nonce。还有什么比使用autoseeded池生成一组随机字节更多的东西吗?
我想知道是否有办法使用OpenSSL或Crypto ++库生成加密nonce。
加密+:
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 */
还有什么比使用autoseeded池生成一组随机字节更多的东西吗?
nonce基本上是IV。它通常被认为是一个公共参数,如IV或Salt。
nonce在安全上下文中必须是唯一的。您可能还需要一个nonce不可预测。
唯一性和不可预测性是两个不同的属性。例如,从0000000000000000
开始的计数器是唯一的,但它也是可预测的。
当您需要唯一性和不可预测性时,可以将随机数分区为随机值和计数器。随机值将占用16字节随机数的8个字节;而计数器将占用16字节随机数的剩余8个字节。然后你使用增量函数基本上每次需要一个值时执行i++
。
你不需要8-8分裂。 12-4工作,4-12工作。这取决于应用程序和重新加密前所需的随机数。重新加密通常由纯文本字节计数驱动。
16-0也有效。在这种情况下,您使用随机值,避开计数器,并避免增量函数。 (增量函数基本上是级联添加)。
NIST SP800-38C和SP800-38D提供了几种创建nonce的方法,因为CCM和GCM使用它们。
另请参阅Crypto Stack Exchange上的What are the requirements of a nonce?。
每个随机数需要一个唯一的编号。您可以使用序列号或随机数。为了帮助确保唯一性,通常(尽管不是必需的)向nonce添加时间戳。将时间戳作为单独的字段传递或将其与nonce连接。有时还会添加IP地址和进程ID等信息。
使用序列号时,无需担心跳过数字。没关系。只要确保你永远不会重复。在重新启动软件时,它必须是唯一的。这是添加时间戳可以提供帮助的地方。因为time-in-millis + serial-number在重新启动服务器时几乎肯定是唯一的。
对于伪随机数发生器,任何人都应该没问题。只要确保你使用足够大的空间,就有可能无法获得复制品。同样,添加时间会降低重复的可能性,因为您需要在相同的毫秒内两次获得相同的随机数。
您可能希望对nonce进行散列以隐藏其中的数据(例如:进程ID),但如果在nonce中包含安全随机数,则散列将仅是安全的。否则,随机数的观察者可能猜测组件并通过重做哈希来验证(即:他们猜测时间并尝试所有可能的proc ID)。
不。如果nonce足够大,那么自动DRBG(确定性随机位发生器 - NIST命名法)就可以了。我建议一个大约12个字节的随机数。如果nonce需要是16个字节,那么你可以将最低有效位(通常是最右边的字节)设置为零以获得最大兼容性。
只使用API提供的加密安全随机数生成器应该没问题 - 它们应该使用从操作系统获得的信息(可能还有其他数据)进行播种。为了确保将种子数据添加到种子数据中永远不会受到伤害。
或者,您可以使用序列号,但这需要您保留某种状态,这种状态在调用时可能很难。请注意,有许多陷阱可能允许时钟重复(夏令时,操作系统更改,电池耗尽等)。
双重检查随机数发生器不会重复足够大的输出永远不会伤害。编程或系统配置错误只会出现问题,例如:当Debian的静态代码分析后修复导致OpenSSL RNG根本没有播种时。