modules, tests: Port bitcoin-core/secp256k1#1777 and bitcoin-core/secp256k1#1824 to zkp-specific code
This commit is contained in:
@@ -138,7 +138,7 @@ static void secp256k1_surjectionproof_csprng_init(secp256k1_surjectionproof_cspr
|
||||
csprng->state_i = 0;
|
||||
}
|
||||
|
||||
static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_csprng *csprng, size_t rand_max) {
|
||||
static size_t secp256k1_surjectionproof_csprng_next(const secp256k1_hash_ctx *hash_ctx, secp256k1_surjectionproof_csprng *csprng, size_t rand_max) {
|
||||
/* The number of random bytes to read for each random sample */
|
||||
const size_t increment = rand_max > 256 ? 2 : 1;
|
||||
/* The maximum value expressable by the number of random bytes we read */
|
||||
@@ -151,8 +151,8 @@ static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_cs
|
||||
if (csprng->state_i + increment >= 32) {
|
||||
secp256k1_sha256 sha;
|
||||
secp256k1_sha256_initialize(&sha);
|
||||
secp256k1_sha256_write(&sha, csprng->state, 32);
|
||||
secp256k1_sha256_finalize(&sha, csprng->state);
|
||||
secp256k1_sha256_write(hash_ctx, &sha, csprng->state, 32);
|
||||
secp256k1_sha256_finalize(hash_ctx, &sha, csprng->state);
|
||||
secp256k1_sha256_clear(&sha);
|
||||
csprng->state_i = 0;
|
||||
}
|
||||
@@ -212,6 +212,7 @@ void secp256k1_surjectionproof_destroy(secp256k1_surjectionproof* proof) {
|
||||
}
|
||||
|
||||
int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1_surjectionproof* proof, size_t *input_index, const secp256k1_fixed_asset_tag* fixed_input_tags, const size_t n_input_tags, const size_t n_input_tags_to_use, const secp256k1_fixed_asset_tag* fixed_output_tag, const size_t n_max_iterations, const unsigned char *random_seed32) {
|
||||
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx);
|
||||
secp256k1_surjectionproof_csprng csprng;
|
||||
size_t n_iterations = 0;
|
||||
|
||||
@@ -239,7 +240,7 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1
|
||||
for (i = 0; i < n_input_tags_to_use; i++) {
|
||||
while (1) {
|
||||
size_t next_input_index;
|
||||
next_input_index = secp256k1_surjectionproof_csprng_next(&csprng, n_input_tags);
|
||||
next_input_index = secp256k1_surjectionproof_csprng_next(hash_ctx, &csprng, n_input_tags);
|
||||
if (secp256k1_memcmp_var(&fixed_input_tags[next_input_index], fixed_output_tag, sizeof(*fixed_output_tag)) == 0) {
|
||||
*input_index = next_input_index;
|
||||
has_output_tag = 1;
|
||||
@@ -270,6 +271,7 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1
|
||||
}
|
||||
|
||||
int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_surjectionproof* proof, const secp256k1_generator* ephemeral_input_tags, size_t n_ephemeral_input_tags, const secp256k1_generator* ephemeral_output_tag, size_t input_index, const unsigned char *input_blinding_key, const unsigned char *output_blinding_key) {
|
||||
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx);
|
||||
secp256k1_scalar blinding_key;
|
||||
secp256k1_scalar tmps;
|
||||
secp256k1_scalar nonce;
|
||||
@@ -334,8 +336,8 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
|
||||
/* Produce signature */
|
||||
rsizes[0] = (int) n_used_pubkeys;
|
||||
indices[0] = (int) ring_input_index;
|
||||
secp256k1_surjection_genmessage(msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag);
|
||||
if (secp256k1_surjection_genrand(borromean_s, n_used_pubkeys, &blinding_key) == 0) {
|
||||
secp256k1_surjection_genmessage(hash_ctx, msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag);
|
||||
if (secp256k1_surjection_genrand(hash_ctx, borromean_s, n_used_pubkeys, &blinding_key) == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Borromean sign will overwrite one of the s values we just generated, so use
|
||||
@@ -343,7 +345,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
|
||||
* homage to the rangeproof code which does this very cleverly to encode messages. */
|
||||
nonce = borromean_s[ring_input_index];
|
||||
secp256k1_scalar_clear(&borromean_s[ring_input_index]);
|
||||
if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
|
||||
if (secp256k1_borromean_sign(hash_ctx, &ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < n_used_pubkeys; i++) {
|
||||
@@ -356,6 +358,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
|
||||
static
|
||||
#endif
|
||||
int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256k1_surjectionproof* proof, const secp256k1_generator* ephemeral_input_tags, size_t n_ephemeral_input_tags, const secp256k1_generator* ephemeral_output_tag) {
|
||||
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx);
|
||||
size_t rsizes[1]; /* array needed for borromean sig API */
|
||||
size_t i;
|
||||
size_t n_total_pubkeys;
|
||||
@@ -394,8 +397,8 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
secp256k1_surjection_genmessage(msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag);
|
||||
return secp256k1_borromean_verify(NULL, &proof->data[0], borromean_s, ring_pubkeys, rsizes, 1, msg32, 32);
|
||||
secp256k1_surjection_genmessage(hash_ctx, msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag);
|
||||
return secp256k1_borromean_verify(hash_ctx, NULL, &proof->data[0], borromean_s, ring_pubkeys, rsizes, 1, msg32, 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "../../scalar.h"
|
||||
#include "../../hash.h"
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg32, const secp256k1_generator *ephemeral_input_tags, size_t n_input_tags, const secp256k1_generator *ephemeral_output_tag) {
|
||||
SECP256K1_INLINE static void secp256k1_surjection_genmessage(const secp256k1_hash_ctx *hash_ctx, unsigned char *msg32, const secp256k1_generator *ephemeral_input_tags, size_t n_input_tags, const secp256k1_generator *ephemeral_output_tag) {
|
||||
/* compute message */
|
||||
size_t i;
|
||||
unsigned char pk_ser[33];
|
||||
@@ -26,16 +26,16 @@ SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg3
|
||||
for (i = 0; i < n_input_tags; i++) {
|
||||
pk_ser[0] = 2 + (ephemeral_input_tags[i].data[63] & 1);
|
||||
memcpy(&pk_ser[1], &ephemeral_input_tags[i].data[0], 32);
|
||||
secp256k1_sha256_write(&sha256_en, pk_ser, pk_len);
|
||||
secp256k1_sha256_write(hash_ctx, &sha256_en, pk_ser, pk_len);
|
||||
}
|
||||
pk_ser[0] = 2 + (ephemeral_output_tag->data[63] & 1);
|
||||
memcpy(&pk_ser[1], &ephemeral_output_tag->data[0], 32);
|
||||
secp256k1_sha256_write(&sha256_en, pk_ser, pk_len);
|
||||
secp256k1_sha256_finalize(&sha256_en, msg32);
|
||||
secp256k1_sha256_write(hash_ctx, &sha256_en, pk_ser, pk_len);
|
||||
secp256k1_sha256_finalize(hash_ctx, &sha256_en, msg32);
|
||||
secp256k1_sha256_clear(&sha256_en);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) {
|
||||
SECP256K1_INLINE static int secp256k1_surjection_genrand(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) {
|
||||
size_t i;
|
||||
unsigned char sec_input[36];
|
||||
secp256k1_sha256 sha256_en;
|
||||
@@ -50,8 +50,8 @@ SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, si
|
||||
sec_input[3] = i >> 24;
|
||||
|
||||
secp256k1_sha256_initialize(&sha256_en);
|
||||
secp256k1_sha256_write(&sha256_en, sec_input, 36);
|
||||
secp256k1_sha256_finalize(&sha256_en, sec_input);
|
||||
secp256k1_sha256_write(hash_ctx, &sha256_en, sec_input, 36);
|
||||
secp256k1_sha256_finalize(hash_ctx, &sha256_en, sec_input);
|
||||
secp256k1_sha256_clear(&sha256_en);
|
||||
secp256k1_scalar_set_b32(&s[i], sec_input, &overflow);
|
||||
if (overflow == 1) {
|
||||
|
||||
@@ -26,7 +26,7 @@ static void test_surjectionproof_api(void) {
|
||||
size_t serialized_len;
|
||||
secp256k1_surjectionproof proof;
|
||||
secp256k1_surjectionproof* proof_on_heap;
|
||||
size_t n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]);
|
||||
size_t n_inputs = ARRAY_SIZE(fixed_input_tags);
|
||||
size_t input_index;
|
||||
size_t i;
|
||||
|
||||
@@ -146,7 +146,7 @@ static void test_input_selection(size_t n_inputs) {
|
||||
size_t try_count = n_inputs * 100;
|
||||
secp256k1_surjectionproof proof;
|
||||
secp256k1_fixed_asset_tag fixed_input_tags[1000];
|
||||
const size_t max_n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]) - 1;
|
||||
const size_t max_n_inputs = ARRAY_SIZE(fixed_input_tags) - 1;
|
||||
|
||||
CHECK(n_inputs < max_n_inputs);
|
||||
testrand256(seed);
|
||||
@@ -313,7 +313,7 @@ static void test_gen_verify(size_t n_inputs, size_t n_used) {
|
||||
secp256k1_fixed_asset_tag fixed_input_tags[1000];
|
||||
secp256k1_generator ephemeral_input_tags[1000];
|
||||
unsigned char *input_blinding_key[1000];
|
||||
const size_t max_n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]) - 1;
|
||||
const size_t max_n_inputs = ARRAY_SIZE(fixed_input_tags) - 1;
|
||||
size_t try_count = n_inputs * 100;
|
||||
size_t key_index;
|
||||
size_t input_index;
|
||||
@@ -395,6 +395,7 @@ static void test_gen_verify(size_t n_inputs, size_t n_used) {
|
||||
|
||||
/* check that a proof with empty n_used_inputs is invalid */
|
||||
static void test_no_used_inputs_verify(void) {
|
||||
const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX);
|
||||
secp256k1_surjectionproof proof;
|
||||
secp256k1_fixed_asset_tag fixed_input_tag;
|
||||
secp256k1_fixed_asset_tag fixed_output_tag;
|
||||
@@ -422,10 +423,10 @@ static void test_no_used_inputs_verify(void) {
|
||||
|
||||
/* create "borromean signature" which is just a hash of metadata (pubkeys, etc) in this case */
|
||||
secp256k1_generator_load(&output, &ephemeral_output_tag);
|
||||
secp256k1_surjection_genmessage(proof.data, ephemeral_input_tags, 1, &ephemeral_output_tag);
|
||||
secp256k1_surjection_genmessage(hash_ctx, proof.data, ephemeral_input_tags, 1, &ephemeral_output_tag);
|
||||
secp256k1_sha256_initialize(&sha256_e0);
|
||||
secp256k1_sha256_write(&sha256_e0, proof.data, 32);
|
||||
secp256k1_sha256_finalize(&sha256_e0, proof.data);
|
||||
secp256k1_sha256_write(hash_ctx, &sha256_e0, proof.data, 32);
|
||||
secp256k1_sha256_finalize(hash_ctx, &sha256_e0, proof.data);
|
||||
|
||||
result = secp256k1_surjectionproof_verify(CTX, &proof, ephemeral_input_tags, n_ephemeral_input_tags, &ephemeral_output_tag);
|
||||
CHECK(result == 0);
|
||||
|
||||
Reference in New Issue
Block a user