gpt4 book ai didi

unit-testing - 强制 OpenSSL 的 RNG 返回可重复的字节序列

转载 作者:行者123 更新时间:2023-12-01 22:27:30 26 4
gpt4 key购买 nike

对于加密实用程序的单元测试,我希望能够强制 OpenSSL 的加密随机数生成器(RAND_bytesRAND_pseudo_bytes)返回可预测、可重复的字节序列,以便各种密文反过来是可预测的,并且可以被烘焙到测试向量中。 (所有其他关键 Material 都在我的控制之下。)

I know this totally defeats security. This will only be used for unit tests.

我不能在每次测试之前简单地使用固定种子调用 RAND_seed ,因为(看起来)RNG 会自动从 /dev/urandom 中为自己播种,无论我是否希望它这样做或不,无论如何,RAND_seed 不会重置 RNG,它只是将种子添加到熵池中。

有什么办法可以做到这一点吗? (在极端情况下,看起来我可以编写自己的 PRNG 引擎,但我想有一个更简单的选择。)

最佳答案

您可以在运行时强制 FIPS ANSI X9.31 RNG 进入测试模式,但不能强制 SSLeay RNG(默认)。如果您使用 -DPREDICT 重新编译 OpenSSL,默认 RNG 将输出可预测的数字序列,但这不太方便。

RAND_pseudo_bytes 函数生成一系列可预测的数字,这意味着它不会像 RAND_bytes 那样自动向自身添加熵。但是就像您注意到的那样,只能向种子添加熵,而不能显式提供种子,因此在程序运行之间您将得到不同的数字。也没有帮助。

但是编写自己的可预测 RNG 引擎并不困难。事实上,我将通过制作一个以 stdlib 的 rand() 为其核心的 rand 引擎来引导您完成它:

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <openssl/rand.h>

// These don't need to do anything if you don't have anything for them to do.
static void stdlib_rand_cleanup() {}
static void stdlib_rand_add(const void *buf, int num, double add_entropy) {}
static int stdlib_rand_status() { return 1; }

// Seed the RNG. srand() takes an unsigned int, so we just use the first
// sizeof(unsigned int) bytes in the buffer to seed the RNG.
static void stdlib_rand_seed(const void *buf, int num)
{
assert(num >= sizeof(unsigned int));
srand( *((unsigned int *) buf) );
}

// Fill the buffer with random bytes. For each byte in the buffer, we generate
// a random number and clamp it to the range of a byte, 0-255.
static int stdlib_rand_bytes(unsigned char *buf, int num)
{
for( int index = 0; index < num; ++index )
{
buf[index] = rand() % 256;
}
return 1;
}

// Create the table that will link OpenSSL's rand API to our functions.
RAND_METHOD stdlib_rand_meth = {
stdlib_rand_seed,
stdlib_rand_bytes,
stdlib_rand_cleanup,
stdlib_rand_add,
stdlib_rand_bytes,
stdlib_rand_status
};

// This is a public-scope accessor method for our table.
RAND_METHOD *RAND_stdlib() { return &stdlib_rand_meth; }

int main()
{
// If we're in test mode, tell OpenSSL to use our special RNG. If we
// don't call this function, OpenSSL uses the SSLeay RNG.
int test_mode = 1;
if( test_mode )
{
RAND_set_rand_method(RAND_stdlib());
}

unsigned int seed = 0x00beef00;
unsigned int rnum[5];

RAND_seed(&seed, sizeof(seed));
RAND_bytes((unsigned char *)&rnum[0], sizeof(rnum));
printf("%u %u %u %u %u\n", rnum[0], rnum[1], rnum[2], rnum[3], rnum[4]);

return 0;
}

每次运行此程序时,它都会使用相同的数字为 srand() 播种,因此每次都会为您提供相同的随机数序列。

corruptor:scratch indiv$ g++ rand.cpp -o r -lcrypto -g
corruptor:scratch indiv$ ./r
1547399009 981369121 2368920148 925292993 788088604
corruptor:scratch indiv$ ./r
1547399009 981369121 2368920148 925292993 788088604
corruptor:scratch indiv$

关于unit-testing - 强制 OpenSSL 的 RNG 返回可重复的字节序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7437177/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com