런타임시 강제로 FIPS ANSI X9.31 RNG를 테스트 모드로 설정할 수 있지만 SSLeay RNG는 기본값이 아닙니다. -DPREDICT
으로 OpenSSL을 다시 컴파일하면 기본 RNG가 예측 가능한 일련의 숫자를 출력하지만 아주 편리하지는 않습니다.
RAND_pseudo_bytes
함수는 예측 가능한 일련의 숫자를 생성합니다. 즉, 자동으로 RAND_bytes
과 같은 엔트로피를 추가하지 않습니다. 그러나 당신이 알았 듯이, 시드에 엔트로피를 추가하는 것만 가능합니다. 명시 적으로 시드를 제공하지 않습니다. 따라서 프로그램을 실행하는 동안 다른 숫자를 얻을 수 있습니다. 또한 도움이되지 않습니다.
그러나 예측 가능한 RNG 엔진을 작성하는 것은 어렵지 않습니다. 사실, 나는 그것의 핵심은 다음 stdlib의 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$
PRNG가 필요하지 않습니다. 예측 가능한 값의 흐름 만 있으면됩니다. 카운터조차 할 것이다. –