Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use xoshiro256++ instead of RFC6979 for tests #1052

Merged
merged 2 commits into from
Dec 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/modules/schnorrsig/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down Expand Up @@ -795,18 +795,18 @@ void test_schnorrsig_sign_verify(void) {
/* Flip a few bits in the signature and in the message and check that
* verify and verify_batch (TODO) fail */
size_t sig_idx = secp256k1_testrand_int(N_SIGS);
size_t byte_idx = secp256k1_testrand_int(32);
size_t byte_idx = secp256k1_testrand_bits(5);
unsigned char xorbyte = secp256k1_testrand_int(254)+1;
sig[sig_idx][byte_idx] ^= xorbyte;
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
sig[sig_idx][byte_idx] ^= xorbyte;

byte_idx = secp256k1_testrand_int(32);
byte_idx = secp256k1_testrand_bits(5);
sig[sig_idx][32+byte_idx] ^= xorbyte;
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
sig[sig_idx][32+byte_idx] ^= xorbyte;

byte_idx = secp256k1_testrand_int(32);
byte_idx = secp256k1_testrand_bits(5);
msg[sig_idx][byte_idx] ^= xorbyte;
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
msg[sig_idx][byte_idx] ^= xorbyte;
Expand Down
7 changes: 5 additions & 2 deletions src/testrand.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16);

/** Generate a pseudorandom number in the range [0..2**32-1]. */
static uint32_t secp256k1_testrand32(void);
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void);

/** Generate a pseudorandom number in the range [0..2**64-1]. */
SECP256K1_INLINE static uint64_t secp256k1_testrand64(void);

/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or
* more. */
static uint32_t secp256k1_testrand_bits(int bits);
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits);

/** Generate a pseudorandom number in the range [0..range-1]. */
static uint32_t secp256k1_testrand_int(uint32_t range);
Expand Down
73 changes: 56 additions & 17 deletions src/testrand_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,64 @@
#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_state[4];
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);
static const unsigned char PREFIX[19] = "secp256k1 test init";
unsigned char out32[32];
secp256k1_sha256 hash;
int i;

/* Use SHA256(PREFIX || seed16) as initial state. */
secp256k1_sha256_initialize(&hash);
secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX));
secp256k1_sha256_write(&hash, seed16, 16);
secp256k1_sha256_finalize(&hash, out32);
for (i = 0; i < 4; ++i) {
uint64_t s = 0;
int j;
for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
secp256k1_test_state[i] = s;
}
secp256k1_test_rng_integer_bits_left = 0;
}

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 uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}

SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
/* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */
const uint64_t result = rotl(secp256k1_test_state[0] + secp256k1_test_state[3], 23) + secp256k1_test_state[0];
const uint64_t t = secp256k1_test_state[1] << 17;
secp256k1_test_state[2] ^= secp256k1_test_state[0];
secp256k1_test_state[3] ^= secp256k1_test_state[1];
secp256k1_test_state[1] ^= secp256k1_test_state[2];
secp256k1_test_state[0] ^= secp256k1_test_state[3];
secp256k1_test_state[2] ^= t;
secp256k1_test_state[3] = rotl(secp256k1_test_state[3], 45);
return result;
}

static uint32_t secp256k1_testrand_bits(int bits) {
uint32_t ret;
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
uint64_t ret;
if (secp256k1_test_rng_integer_bits_left < bits) {
secp256k1_test_rng_integer |= (((uint64_t)secp256k1_testrand32()) << secp256k1_test_rng_integer_bits_left);
secp256k1_test_rng_integer_bits_left += 32;
secp256k1_test_rng_integer = secp256k1_testrand64();
secp256k1_test_rng_integer_bits_left = 64;
}
ret = secp256k1_test_rng_integer;
secp256k1_test_rng_integer >>= bits;
secp256k1_test_rng_integer_bits_left -= bits;
ret &= ((~((uint32_t)0)) >> (32 - bits));
ret &= ((~((uint64_t)0)) >> (64 - bits));
return ret;
}

SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
return secp256k1_testrand_bits(32);
}

static uint32_t secp256k1_testrand_int(uint32_t range) {
/* We want a uniform integer between 0 and range-1, inclusive.
* B is the smallest number such that range <= 2**B.
Expand Down Expand Up @@ -85,7 +112,19 @@ 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 < 4; ++i) {
uint64_t val = secp256k1_testrand64();
b32[0] = val;
b32[1] = val >> 8;
b32[2] = val >> 16;
b32[3] = val >> 24;
b32[4] = val >> 32;
b32[5] = val >> 40;
b32[6] = val >> 48;
b32[7] = val >> 56;
b32 += 8;
}
}

static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) {
Expand All @@ -109,7 +148,7 @@ static void secp256k1_testrand256_test(unsigned char *b32) {
}

static void secp256k1_testrand_flip(unsigned char *b, size_t len) {
b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_int(8));
b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_bits(3));
}

static void secp256k1_testrand_init(const char* hexseed) {
Expand Down
18 changes: 9 additions & 9 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ void signed30_to_uint16(uint16_t* out, const secp256k1_modinv32_signed30* in) {
void mutate_sign_signed30(secp256k1_modinv32_signed30* x) {
int i;
for (i = 0; i < 16; ++i) {
int pos = secp256k1_testrand_int(8);
int pos = secp256k1_testrand_bits(3);
if (x->v[pos] > 0 && x->v[pos + 1] <= 0x3fffffff) {
x->v[pos] -= 0x40000000;
x->v[pos + 1] += 1;
Expand Down Expand Up @@ -862,7 +862,7 @@ void mutate_sign_signed62(secp256k1_modinv64_signed62* x) {
static const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
int i;
for (i = 0; i < 8; ++i) {
int pos = secp256k1_testrand_int(4);
int pos = secp256k1_testrand_bits(2);
if (x->v[pos] > 0 && x->v[pos + 1] <= M62) {
x->v[pos] -= (M62 + 1);
x->v[pos + 1] += 1;
Expand Down Expand Up @@ -4261,7 +4261,7 @@ void test_secp256k1_pippenger_bucket_window_inv(void) {
* for a given scratch space.
*/
void test_ecmult_multi_pippenger_max_points(void) {
size_t scratch_size = secp256k1_testrand_int(256);
size_t scratch_size = secp256k1_testrand_bits(8);
size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12);
secp256k1_scratch *scratch;
size_t n_points_supported;
Expand Down Expand Up @@ -6023,14 +6023,14 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
/* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */
nlow[n] = der ? 1 : (secp256k1_testrand_bits(3) != 0);
/* The length of the number in bytes (the first byte of which will always be nonzero) */
nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_int(8) / 8;
nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_bits(3) / 8;
CHECK(nlen[n] <= 232);
/* The top bit of the number. */
nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_testrand_bits(1));
/* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */
nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_testrand_bits(7) : 1 + secp256k1_testrand_int(127));
/* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */
nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_int(8) / 8);
nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_bits(3) / 8);
if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) {
*certainly_not_der = 1;
}
Expand All @@ -6039,7 +6039,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2);
if (!der) {
/* nlenlen[n] max 127 bytes */
int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_int(16) * secp256k1_testrand_int(16) / 256;
int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256;
nlenlen[n] += add;
if (add != 0) {
*certainly_not_der = 1;
Expand All @@ -6053,15 +6053,15 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
CHECK(tlen <= 856);

/* The length of the garbage inside the tuple. */
elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_int(8) / 8;
elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_bits(3) / 8;
if (elen != 0) {
*certainly_not_der = 1;
}
tlen += elen;
CHECK(tlen <= 980);

/* The length of the garbage after the end of the tuple. */
glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_int(8) / 8;
glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_bits(3) / 8;
if (glen != 0) {
*certainly_not_der = 1;
}
Expand All @@ -6076,7 +6076,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
} else {
int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2);
if (!der) {
int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_int(16) * secp256k1_testrand_int(16) / 256;
int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256;
tlenlen += add;
if (add != 0) {
*certainly_not_der = 1;
Expand Down