Skip to content

Commit c545fdc

Browse files
committed
Merge #1298: Remove randomness tests
6ec3731 Simplify test PRNG implementation (Pieter Wuille) fb5bfa4 Add static test vector for Xoshiro256++ (Tim Ruffing) 723e8ca Remove randomness tests (Pieter Wuille) Pull request description: ACKs for top commit: real-or-random: utACK 6ec3731 jonasnick: ACK 6ec3731 Tree-SHA512: 4cbbb9c42e31f067b17dd9169ae5d5e68bce77d1253452db9df523d3be2b5d61002d5a4203e5a153f257ec63c5ff2113555743eeb402d4b6c573069ea494d407
2 parents b40e2d3 + 6ec3731 commit c545fdc

File tree

2 files changed

+49
-124
lines changed

2 files changed

+49
-124
lines changed

Diff for: src/testrand_impl.h

+17-48
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include "util.h"
1717

1818
static uint64_t secp256k1_test_state[4];
19-
static uint64_t secp256k1_test_rng_integer;
20-
static int secp256k1_test_rng_integer_bits_left = 0;
2119

2220
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
2321
static const unsigned char PREFIX[19] = "secp256k1 test init";
@@ -36,7 +34,6 @@ SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16
3634
for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
3735
secp256k1_test_state[i] = s;
3836
}
39-
secp256k1_test_rng_integer_bits_left = 0;
4037
}
4138

4239
SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
@@ -57,58 +54,30 @@ SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
5754
}
5855

5956
SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
60-
uint64_t ret;
61-
if (secp256k1_test_rng_integer_bits_left < bits) {
62-
secp256k1_test_rng_integer = secp256k1_testrand64();
63-
secp256k1_test_rng_integer_bits_left = 64;
64-
}
65-
ret = secp256k1_test_rng_integer;
66-
secp256k1_test_rng_integer >>= bits;
67-
secp256k1_test_rng_integer_bits_left -= bits;
68-
ret &= ((~((uint64_t)0)) >> (64 - bits));
69-
return ret;
57+
if (bits == 0) return 0;
58+
return secp256k1_testrand64() >> (64 - bits);
7059
}
7160

7261
SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
73-
return secp256k1_testrand_bits(32);
62+
return secp256k1_testrand64() >> 32;
7463
}
7564

7665
static uint32_t secp256k1_testrand_int(uint32_t range) {
77-
/* We want a uniform integer between 0 and range-1, inclusive.
78-
* B is the smallest number such that range <= 2**B.
79-
* two mechanisms implemented here:
80-
* - generate B bits numbers until one below range is found, and return it
81-
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
82-
* bits numbers until one below M is found, and return it modulo range
83-
* The second mechanism consumes A more bits of entropy in every iteration,
84-
* but may need fewer iterations due to M being closer to 2**(B+A) then
85-
* range is to 2**B. The array below (indexed by B) contains a 0 when the
86-
* first mechanism is to be used, and the number A otherwise.
87-
*/
88-
static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0};
89-
uint32_t trange, mult;
90-
int bits = 0;
91-
if (range <= 1) {
92-
return 0;
93-
}
94-
trange = range - 1;
95-
while (trange > 0) {
96-
trange >>= 1;
97-
bits++;
66+
uint32_t mask = 0;
67+
uint32_t range_copy;
68+
/* Reduce range by 1, changing its meaning to "maximum value". */
69+
VERIFY_CHECK(range != 0);
70+
range -= 1;
71+
/* Count the number of bits in range. */
72+
range_copy = range;
73+
while (range_copy) {
74+
mask = (mask << 1) | 1U;
75+
range_copy >>= 1;
9876
}
99-
if (addbits[bits]) {
100-
bits = bits + addbits[bits];
101-
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
102-
trange = range * mult;
103-
} else {
104-
trange = range;
105-
mult = 1;
106-
}
107-
while(1) {
108-
uint32_t x = secp256k1_testrand_bits(bits);
109-
if (x < trange) {
110-
return (mult == 1) ? x : (x % range);
111-
}
77+
/* Generation loop. */
78+
while (1) {
79+
uint32_t val = secp256k1_testrand64() & mask;
80+
if (val <= range) return val;
11281
}
11382
}
11483

Diff for: src/tests.c

+32-76
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,35 @@ static void random_scalar_order_b32(unsigned char *b32) {
181181
secp256k1_scalar_get_b32(b32, &num);
182182
}
183183

184+
static void run_xoshiro256pp_tests(void) {
185+
{
186+
size_t i;
187+
/* Sanity check that we run before the actual seeding. */
188+
for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) {
189+
CHECK(secp256k1_test_state[i] == 0);
190+
}
191+
}
192+
{
193+
int i;
194+
unsigned char buf32[32];
195+
unsigned char seed16[16] = {
196+
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
197+
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
198+
};
199+
unsigned char buf32_expected[32] = {
200+
0xAF, 0xCC, 0xA9, 0x16, 0xB5, 0x6C, 0xE3, 0xF0,
201+
0x44, 0x3F, 0x45, 0xE0, 0x47, 0xA5, 0x08, 0x36,
202+
0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF,
203+
0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30,
204+
};
205+
secp256k1_testrand_seed(seed16);
206+
for (i = 0; i < 17; i++) {
207+
secp256k1_testrand256(buf32);
208+
}
209+
CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0);
210+
}
211+
}
212+
184213
static void run_selftest_tests(void) {
185214
/* Test public API */
186215
secp256k1_selftest();
@@ -824,78 +853,6 @@ static void run_tagged_sha256_tests(void) {
824853
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
825854
}
826855

827-
/***** RANDOM TESTS *****/
828-
829-
static void test_rand_bits(int rand32, int bits) {
830-
/* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to
831-
* get a false negative chance below once in a billion */
832-
static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316};
833-
/* We try multiplying the results with various odd numbers, which shouldn't
834-
* influence the uniform distribution modulo a power of 2. */
835-
static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011};
836-
/* We only select up to 6 bits from the output to analyse */
837-
unsigned int usebits = bits > 6 ? 6 : bits;
838-
unsigned int maxshift = bits - usebits;
839-
/* For each of the maxshift+1 usebits-bit sequences inside a bits-bit
840-
number, track all observed outcomes, one per bit in a uint64_t. */
841-
uint64_t x[6][27] = {{0}};
842-
unsigned int i, shift, m;
843-
/* Multiply the output of all rand calls with the odd number m, which
844-
should not change the uniformity of its distribution. */
845-
for (i = 0; i < rounds[usebits]; i++) {
846-
uint32_t r = (rand32 ? secp256k1_testrand32() : secp256k1_testrand_bits(bits));
847-
CHECK((((uint64_t)r) >> bits) == 0);
848-
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
849-
uint32_t rm = r * mults[m];
850-
for (shift = 0; shift <= maxshift; shift++) {
851-
x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1)));
852-
}
853-
}
854-
}
855-
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
856-
for (shift = 0; shift <= maxshift; shift++) {
857-
/* Test that the lower usebits bits of x[shift] are 1 */
858-
CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0);
859-
}
860-
}
861-
}
862-
863-
/* Subrange must be a whole divisor of range, and at most 64 */
864-
static void test_rand_int(uint32_t range, uint32_t subrange) {
865-
/* (1-1/subrange)^rounds < 1/10^9 */
866-
int rounds = (subrange * 2073) / 100;
867-
int i;
868-
uint64_t x = 0;
869-
CHECK((range % subrange) == 0);
870-
for (i = 0; i < rounds; i++) {
871-
uint32_t r = secp256k1_testrand_int(range);
872-
CHECK(r < range);
873-
r = r % subrange;
874-
x |= (((uint64_t)1) << r);
875-
}
876-
/* Test that the lower subrange bits of x are 1. */
877-
CHECK(((~x) << (64 - subrange)) == 0);
878-
}
879-
880-
static void run_rand_bits(void) {
881-
size_t b;
882-
test_rand_bits(1, 32);
883-
for (b = 1; b <= 32; b++) {
884-
test_rand_bits(0, b);
885-
}
886-
}
887-
888-
static void run_rand_int(void) {
889-
static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432};
890-
static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64};
891-
unsigned int m, s;
892-
for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) {
893-
for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) {
894-
test_rand_int(ms[m] * ss[s], ss[s]);
895-
}
896-
}
897-
}
898-
899856
/***** MODINV TESTS *****/
900857

901858
/* Compute the modular inverse of (odd) x mod 2^64. */
@@ -7735,6 +7692,9 @@ int main(int argc, char **argv) {
77357692
}
77367693
printf("test count = %i\n", COUNT);
77377694

7695+
/* run test RNG tests (must run before we really initialize the test RNG) */
7696+
run_xoshiro256pp_tests();
7697+
77387698
/* find random seed */
77397699
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
77407700

@@ -7772,10 +7732,6 @@ int main(int argc, char **argv) {
77727732
/* scratch tests */
77737733
run_scratch_tests();
77747734

7775-
/* randomness tests */
7776-
run_rand_bits();
7777-
run_rand_int();
7778-
77797735
/* integer arithmetic tests */
77807736
#ifdef SECP256K1_WIDEMUL_INT128
77817737
run_int128_tests();

0 commit comments

Comments
 (0)