From 59ae5a28f16c72baaa483e9b7e83dbbdca348c69 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 23 Dec 2021 11:03:48 -0500 Subject: [PATCH] Use Squares RNG instead of RFC6979 for tests --- src/modules/schnorrsig/tests_impl.h | 2 +- src/testrand.h | 2 +- src/testrand_impl.h | 71 +++++++++++++++++------------ 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 2efec8a2b9..3187ff1170 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -87,7 +87,7 @@ void run_nonce_function_bip340_tests(void) { CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0); CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); /* Other algo is fine */ - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, algo, algolen); + secp256k1_testrand_bytes_test(algo, algolen); CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); for (i = 0; i < count; i++) { diff --git a/src/testrand.h b/src/testrand.h index 667d1867bd..704ba05cac 100644 --- a/src/testrand.h +++ b/src/testrand.h @@ -14,7 +14,7 @@ /* A non-cryptographic RNG used only for test infrastructure. */ /** Seed the pseudorandom number generator for testing. */ -SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16); +SECP256K1_INLINE static void secp256k1_testrand_seed(uint64_t seed); /** Generate a pseudorandom number in the range [0..2**32-1]. */ static uint32_t secp256k1_testrand32(void); diff --git a/src/testrand_impl.h b/src/testrand_impl.h index c8d30ef6a8..7ea942696e 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -1,5 +1,5 @@ /*********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * + * Copyright (c) 2013-2015, 2021 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ @@ -14,22 +14,26 @@ #include "testrand.h" #include "hash.h" -static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng; -static uint32_t secp256k1_test_rng_precomputed[8]; -static int secp256k1_test_rng_precomputed_used = 8; +static uint64_t secp256k1_test_rng_key; +static uint64_t secp256k1_test_rng_cnt = 0; static uint64_t secp256k1_test_rng_integer; static int secp256k1_test_rng_integer_bits_left = 0; -SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) { - secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); +SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) { + /* Test-only RNG based on https://arxiv.org/abs/2004.06278. */ + uint64_t x, y, z; + y = x = (secp256k1_test_rng_cnt++) * secp256k1_test_rng_key; + z = y + secp256k1_test_rng_key; + x = x*x + y; x = (x>>32) | (x<<32); /* round 1 */ + x = x*x + z; x = (x>>32) | (x<<32); /* round 2 */ + x = x*x + y; x = (x>>32) | (x<<32); /* round 3 */ + return (x*x + z) >> 32; /* round 4 */ } -SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) { - if (secp256k1_test_rng_precomputed_used == 8) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed)); - secp256k1_test_rng_precomputed_used = 0; - } - return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++]; +SECP256K1_INLINE static void secp256k1_testrand_seed(uint64_t seed) { + secp256k1_test_rng_key = seed; + secp256k1_test_rng_cnt = 0; + secp256k1_test_rng_integer_bits_left = 0; } static uint32_t secp256k1_testrand_bits(int bits) { @@ -85,7 +89,15 @@ static uint32_t secp256k1_testrand_int(uint32_t range) { } static void secp256k1_testrand256(unsigned char *b32) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); + int i; + for (i = 0; i < 8; ++i) { + uint32_t val = secp256k1_testrand32(); + b32[0] = val; + b32[1] = val >> 8; + b32[2] = val >> 16; + b32[3] = val >> 24; + b32 += 4; + } } static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) { @@ -113,13 +125,13 @@ static void secp256k1_testrand_flip(unsigned char *b, size_t len) { } static void secp256k1_testrand_init(const char* hexseed) { - unsigned char seed16[16] = {0}; + uint64_t seed = 0; if (hexseed && strlen(hexseed) != 0) { int pos = 0; - while (pos < 16 && hexseed[0] != 0 && hexseed[1] != 0) { + while (pos < 8 && hexseed[0] != 0 && hexseed[1] != 0) { unsigned short sh; if ((sscanf(hexseed, "%2hx", &sh)) == 1) { - seed16[pos] = sh; + seed = (seed << 8) | sh; } else { break; } @@ -127,26 +139,27 @@ static void secp256k1_testrand_init(const char* hexseed) { pos++; } } else { + unsigned char seed8[8] = {0}; FILE *frand = fopen("/dev/urandom", "rb"); - if ((frand == NULL) || fread(&seed16, 1, sizeof(seed16), frand) != sizeof(seed16)) { - uint64_t t = time(NULL) * (uint64_t)1337; - fprintf(stderr, "WARNING: could not read 16 bytes from /dev/urandom; falling back to insecure PRNG\n"); - seed16[0] ^= t; - seed16[1] ^= t >> 8; - seed16[2] ^= t >> 16; - seed16[3] ^= t >> 24; - seed16[4] ^= t >> 32; - seed16[5] ^= t >> 40; - seed16[6] ^= t >> 48; - seed16[7] ^= t >> 56; + if (frand == NULL || fread(&seed8, 1, sizeof(seed8), frand) != sizeof(seed8)) { + fprintf(stderr, "WARNING: could not read 8 bytes from /dev/urandom; falling back to insecure PRNG\n"); } + seed ^= ((uint64_t)seed8[0]) << 0; + seed ^= ((uint64_t)seed8[1]) << 8; + seed ^= ((uint64_t)seed8[2]) << 16; + seed ^= ((uint64_t)seed8[3]) << 24; + seed ^= ((uint64_t)seed8[4]) << 32; + seed ^= ((uint64_t)seed8[5]) << 40; + seed ^= ((uint64_t)seed8[6]) << 48; + seed ^= ((uint64_t)seed8[7]) << 56; + seed += time(NULL) * (uint64_t)1337; if (frand) { fclose(frand); } } - printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); - secp256k1_testrand_seed(seed16); + printf("random seed = %08lx%08lx\n", (unsigned long)(seed >> 32), (unsigned long)(seed & 0xffffffff)); + secp256k1_testrand_seed(seed); } static void secp256k1_testrand_finish(void) {