From 92820d944b52d923dad57b7d5bae5fec48f28ddd Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Fri, 5 Aug 2022 21:05:09 +0000 Subject: [PATCH] rangeproof: add a test for all-zero blinding factors --- include/secp256k1_rangeproof.h | 3 +- src/modules/rangeproof/tests_impl.h | 53 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/include/secp256k1_rangeproof.h b/include/secp256k1_rangeproof.h index d4f35de7..d179b36f 100644 --- a/include/secp256k1_rangeproof.h +++ b/include/secp256k1_rangeproof.h @@ -227,7 +227,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_rewind( * proof: pointer to array to receive the proof, can be up to 5134 bytes. (cannot be NULL) * min_value: constructs a proof where the verifer can tell the minimum value is at least the specified amount. * commit: the commitment being proved. - * blind: 32-byte blinding factor used by commit. + * blind: 32-byte blinding factor used by commit. The blinding factor may be all-zeros as long as min_bits is set to 3 or greater. + * This is a side-effect of the underlying crypto, not a deliberate API choice, but it may be useful when balancing CT transactions. * nonce: 32-byte secret nonce used to initialize the proof (value can be reverse-engineered out of the proof if this secret is known.) * exp: Base-10 exponent. Digits below above will be made public, but the proof will be made smaller. Allowed range is -1 to 18. * (-1 is a special case that makes the value public. 0 is the most private.) diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index 47c5f3a7..67378cc4 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -547,6 +547,58 @@ static void test_rangeproof(void) { } } +static void test_rangeproof_null_blinder(void) { + unsigned char proof[5134]; + const unsigned char blind[32] = { 0 }; + const uint64_t v = 1111; + uint64_t minv, maxv; + secp256k1_pedersen_commitment commit; + size_t len; + + CHECK(secp256k1_pedersen_commit(ctx, &commit, blind, v, secp256k1_generator_h)); + + /* Try a 32-bit proof; should work */ + len = 5134; + CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, 1, &commit, blind, commit.data, 0, 32, v, NULL, 0, NULL, 0, secp256k1_generator_h)); + CHECK(secp256k1_rangeproof_verify(ctx, &minv, &maxv, &commit, proof, len, NULL, 0, secp256k1_generator_h)); + CHECK(minv == 1); + CHECK(maxv == 1ULL << 32); + + /* Try a 3-bit proof; should work */ + len = 5134; + CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, v - 1, &commit, blind, commit.data, 0, 3, v, NULL, 0, NULL, 0, secp256k1_generator_h)); + CHECK(secp256k1_rangeproof_verify(ctx, &minv, &maxv, &commit, proof, len, NULL, 0, secp256k1_generator_h)); + CHECK(minv == 1110); + CHECK(maxv == 1117); + + /* But a 2-bits will not because then it does not have any subcommitments (which rerandomize + * the blinding factors that get passed into the borromean logic ... passing 0s will fail) */ + len = 5134; + CHECK(!secp256k1_rangeproof_sign(ctx, proof, &len, v - 1, &commit, blind, commit.data, 0, 2, v, NULL, 0, NULL, 0, secp256k1_generator_h)); + + /* Rewinding with 3-bits works */ + { + uint64_t value_out; + unsigned char msg[128]; + unsigned char msg_out[128]; + unsigned char blind_out[32]; + size_t msg_len = sizeof(msg); + + len = 1000; + secp256k1_testrand256(msg); + secp256k1_testrand256(&msg[32]); + secp256k1_testrand256(&msg[64]); + secp256k1_testrand256(&msg[96]); + CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, v, &commit, blind, commit.data, 0, 3, v, msg, sizeof(msg), NULL, 0, secp256k1_generator_h)); + CHECK(secp256k1_rangeproof_rewind(ctx, blind_out, &value_out, msg_out, &msg_len, commit.data, &minv, &maxv, &commit, proof, len, NULL, 0, secp256k1_generator_h) != 0); + CHECK(memcmp(blind, blind_out, sizeof(blind)) == 0); + CHECK(memcmp(msg, msg_out, sizeof(msg)) == 0); + CHECK(value_out == v); + CHECK(minv == v); + CHECK(maxv == v + 7); + } +} + #define MAX_N_GENS 30 void test_multiple_generators(void) { const size_t n_inputs = (secp256k1_testrand32() % (MAX_N_GENS / 2)) + 1; @@ -705,6 +757,7 @@ void run_rangeproof_tests(void) { test_borromean(); } test_rangeproof(); + test_rangeproof_null_blinder(); test_multiple_generators(); }