update secp256k1-zkp 2318f18a909dffa1f962e681db7ff62cdc0f8e1c

This commit is contained in:
Gregory Sanders 2018-10-08 10:29:29 +09:00
parent 138d55a1b7
commit f3a424f0d0
7 changed files with 182 additions and 40 deletions

View file

@ -13,15 +13,12 @@ extern "C" {
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 33 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage or transmission, use
* the secp256k1_generator_serialize_*.
*
* Furthermore, it is guaranteed to identical points will have identical
* representation, so they can be memcmp'ed.
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use secp256k1_generator_serialize and secp256k1_generator_parse.
*/
typedef struct {
unsigned char data[33];
unsigned char data[64];
} secp256k1_generator;
/** Parse a 33-byte generator byte sequence into a generator object.
@ -58,9 +55,9 @@ SECP256K1_API int secp256k1_generator_serialize(
* Out: gen: a generator object
* In: seed32: a 32-byte seed
*
* If succesful, a valid generator will be placed in gen. The produced
* If successful a valid generator will be placed in gen. The produced
* generators are distributed uniformly over the curve, and will not have a
* known dicrete logarithm with respect to any other generator produced,
* known discrete logarithm with respect to any other generator produced,
* or to the base generator G.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_generator_generate(

View file

@ -14,21 +14,19 @@ extern "C" {
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 33 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage or transmission, use
* secp256k1_pedersen_commitment_serialize and secp256k1_pedersen_commitment_parse.
*
* Furthermore, it is guaranteed to identical signatures will have identical
* representation, so they can be memcmp'ed.
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use secp256k1_pedersen_commitment_serialize and
* secp256k1_pedersen_commitment_parse.
*/
typedef struct {
unsigned char data[33];
unsigned char data[64];
} secp256k1_pedersen_commitment;
/**
* Static constant generator 'h' maintained for historical reasons.
*/
extern const secp256k1_generator *secp256k1_generator_h;
SECP256K1_API extern const secp256k1_generator *secp256k1_generator_h;
/** Parse a 33-byte commitment into a commitment object.
*

View file

@ -15,36 +15,55 @@
#include "scalar.h"
static void secp256k1_generator_load(secp256k1_ge* ge, const secp256k1_generator* gen) {
secp256k1_fe fe;
secp256k1_fe_set_b32(&fe, &gen->data[1]);
secp256k1_ge_set_xquad(ge, &fe);
if (gen->data[0] & 1) {
secp256k1_ge_neg(ge, ge);
}
int succeed;
succeed = secp256k1_fe_set_b32(&ge->x, &gen->data[0]);
VERIFY_CHECK(succeed != 0);
succeed = secp256k1_fe_set_b32(&ge->y, &gen->data[32]);
VERIFY_CHECK(succeed != 0);
ge->infinity = 0;
(void) succeed;
}
static void secp256k1_generator_save(secp256k1_generator* commit, secp256k1_ge* ge) {
secp256k1_fe_normalize(&ge->x);
secp256k1_fe_get_b32(&commit->data[1], &ge->x);
commit->data[0] = 11 ^ secp256k1_fe_is_quad_var(&ge->y);
static void secp256k1_generator_save(secp256k1_generator *gen, secp256k1_ge* ge) {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x);
secp256k1_fe_normalize_var(&ge->y);
secp256k1_fe_get_b32(&gen->data[0], &ge->x);
secp256k1_fe_get_b32(&gen->data[32], &ge->y);
}
int secp256k1_generator_parse(const secp256k1_context* ctx, secp256k1_generator* gen, const unsigned char *input) {
secp256k1_fe x;
secp256k1_ge ge;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(gen != NULL);
ARG_CHECK(input != NULL);
if ((input[0] & 0xFE) != 10) {
if ((input[0] & 0xFE) != 10 ||
!secp256k1_fe_set_b32(&x, &input[1]) ||
!secp256k1_ge_set_xquad(&ge, &x)) {
return 0;
}
memcpy(gen->data, input, sizeof(gen->data));
if (input[0] & 1) {
secp256k1_ge_neg(&ge, &ge);
}
secp256k1_generator_save(gen, &ge);
return 1;
}
int secp256k1_generator_serialize(const secp256k1_context* ctx, unsigned char *output, const secp256k1_generator* gen) {
secp256k1_ge ge;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(output != NULL);
ARG_CHECK(gen != NULL);
memcpy(output, gen->data, sizeof(gen->data));
secp256k1_generator_load(&ge, gen);
output[0] = 11 ^ secp256k1_fe_is_quad_var(&ge.y);
secp256k1_fe_normalize_var(&ge.x);
secp256k1_fe_get_b32(&output[1], &ge.x);
return 1;
}

View file

@ -190,8 +190,28 @@ void test_generator_generate(void) {
}
}
void test_generator_fixed_vector(void) {
const unsigned char two_g[33] = {
0x0b,
0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8,
0x5c, 0x77, 0x8e, 0x4b, 0x8c, 0xef, 0x3c, 0xa7, 0xab, 0xac, 0x09, 0xb9, 0x5c, 0x70, 0x9e, 0xe5
};
unsigned char result[33];
secp256k1_generator parse;
CHECK(secp256k1_generator_parse(ctx, &parse, two_g));
CHECK(secp256k1_generator_serialize(ctx, result, &parse));
CHECK(memcmp(two_g, result, 33) == 0);
result[0] = 0x0a;
CHECK(secp256k1_generator_parse(ctx, &parse, result));
result[0] = 0x08;
CHECK(!secp256k1_generator_parse(ctx, &parse, result));
}
void run_generator_tests(void) {
test_shallue_van_de_woestijne();
test_generator_fixed_vector();
test_generator_api();
test_generator_generate();
}

View file

@ -16,13 +16,14 @@
/** Alternative generator for secp256k1.
* This is the sha256 of 'g' after DER encoding (without compression),
* which happens to be a point on the curve.
* sage: G2 = EllipticCurve ([F (0), F (7)]).lift_x(int(hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')).hexdigest(),16))
* sage: '%x %x' % (11 - G2.xy()[1].is_square(), G2.xy()[0])
* sage: G2 = EllipticCurve ([F (0), F (7)]).lift_x(F(int(hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')).hexdigest(),16)))
* sage: '%x %x' % G2.xy()
*/
static const secp256k1_generator secp256k1_generator_h_internal = {{
0x11,
0x50, 0x92, 0x9b, 0x74, 0xc1, 0xa0, 0x49, 0x54, 0xb7, 0x8b, 0x4b, 0x60, 0x35, 0xe9, 0x7a, 0x5e,
0x07, 0x8a, 0x5a, 0x0f, 0x28, 0xec, 0x96, 0xd5, 0x47, 0xbf, 0xee, 0x9a, 0xce, 0x80, 0x3a, 0xc0
0x07, 0x8a, 0x5a, 0x0f, 0x28, 0xec, 0x96, 0xd5, 0x47, 0xbf, 0xee, 0x9a, 0xce, 0x80, 0x3a, 0xc0,
0x31, 0xd3, 0xc6, 0x86, 0x39, 0x73, 0x92, 0x6e, 0x04, 0x9e, 0x63, 0x7c, 0xb1, 0xb5, 0xf4, 0x0a,
0x36, 0xda, 0xc2, 0x8a, 0xf1, 0x76, 0x69, 0x68, 0xc3, 0x0c, 0x23, 0x13, 0xf3, 0xa3, 0x89, 0x04
}};
const secp256k1_generator *secp256k1_generator_h = &secp256k1_generator_h_internal;
@ -43,22 +44,38 @@ static void secp256k1_pedersen_commitment_save(secp256k1_pedersen_commitment* co
}
int secp256k1_pedersen_commitment_parse(const secp256k1_context* ctx, secp256k1_pedersen_commitment* commit, const unsigned char *input) {
secp256k1_fe x;
secp256k1_ge ge;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(commit != NULL);
ARG_CHECK(input != NULL);
(void) ctx;
if ((input[0] & 0xFE) != 8) {
if ((input[0] & 0xFE) != 8 ||
!secp256k1_fe_set_b32(&x, &input[1]) ||
!secp256k1_ge_set_xquad(&ge, &x)) {
return 0;
}
memcpy(commit->data, input, sizeof(commit->data));
if (input[0] & 1) {
secp256k1_ge_neg(&ge, &ge);
}
secp256k1_pedersen_commitment_save(commit, &ge);
return 1;
}
int secp256k1_pedersen_commitment_serialize(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pedersen_commitment* commit) {
secp256k1_ge ge;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(output != NULL);
ARG_CHECK(commit != NULL);
memcpy(output, commit->data, sizeof(commit->data));
secp256k1_pedersen_commitment_load(&ge, commit);
output[0] = 9 ^ secp256k1_fe_is_quad_var(&ge.y);
secp256k1_fe_normalize_var(&ge.x);
secp256k1_fe_get_b32(&output[1], &ge.x);
return 1;
}

View file

@ -609,8 +609,10 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
}
for(i = 0; i < rings - 1; i++) {
secp256k1_fe fe;
secp256k1_fe_set_b32(&fe, &proof[offset]);
secp256k1_ge_set_xquad(&c, &fe);
if (!secp256k1_fe_set_b32(&fe, &proof[offset]) ||
!secp256k1_ge_set_xquad(&c, &fe)) {
return 0;
}
if (signs[i]) {
secp256k1_ge_neg(&c, &c);
}

View file

@ -385,7 +385,7 @@ static void test_rangeproof(void) {
const uint64_t testvs[11] = {0, 1, 5, 11, 65535, 65537, INT32_MAX, UINT32_MAX, INT64_MAX - 1, INT64_MAX, UINT64_MAX};
secp256k1_pedersen_commitment commit;
secp256k1_pedersen_commitment commit2;
unsigned char proof[5134];
unsigned char proof[5134 + 1]; /* One additional byte to test if trailing bytes are rejected */
unsigned char blind[32];
unsigned char blindout[32];
unsigned char message[4096];
@ -485,6 +485,9 @@ static void test_rangeproof(void) {
len = 5134;
CHECK(secp256k1_rangeproof_sign(ctx, proof, &len, 0, &commit, blind, commit.data, 0, 3, v, NULL, 0, NULL, 0, secp256k1_generator_h));
CHECK(len <= 5134);
/* Test if trailing bytes are rejected. */
proof[len] = v;
CHECK(!secp256k1_rangeproof_verify(ctx, &minv, &maxv, &commit, proof, len + 1, NULL, 0, secp256k1_generator_h));
for (i = 0; i < len*8; i++) {
proof[i >> 3] ^= 1 << (i & 7);
CHECK(!secp256k1_rangeproof_verify(ctx, &minv, &maxv, &commit, proof, len, NULL, 0, secp256k1_generator_h));
@ -604,9 +607,95 @@ void test_multiple_generators(void) {
}
}
void test_rangeproof_fixed_vectors(void) {
const unsigned char vector_1[] = {
0x62, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x02, 0x2a, 0x5c, 0x42, 0x0e, 0x1d,
0x51, 0xe1, 0xb7, 0xf3, 0x69, 0x04, 0xb5, 0xbb, 0x9b, 0x41, 0x66, 0x14, 0xf3, 0x64, 0x42, 0x26,
0xe3, 0xa7, 0x6a, 0x06, 0xbb, 0xa8, 0x5a, 0x49, 0x6f, 0x19, 0x76, 0xfb, 0xe5, 0x75, 0x77, 0x88,
0xab, 0xa9, 0x66, 0x44, 0x80, 0xea, 0x29, 0x95, 0x7f, 0xdf, 0x72, 0x4a, 0xaf, 0x02, 0xbe, 0xdd,
0x5d, 0x15, 0xd8, 0xae, 0xff, 0x74, 0xc9, 0x8c, 0x1a, 0x67, 0x0e, 0xb2, 0x57, 0x22, 0x99, 0xc3,
0x21, 0x46, 0x6f, 0x15, 0x58, 0x0e, 0xdb, 0xe6, 0x6e, 0xc4, 0x0d, 0xfe, 0x6f, 0x04, 0x6b, 0x0d,
0x18, 0x3d, 0x78, 0x40, 0x98, 0x56, 0x4e, 0xe4, 0x4a, 0x74, 0x90, 0xa7, 0xac, 0x9c, 0x16, 0xe0,
0x3e, 0x81, 0xaf, 0x0f, 0xe3, 0x4f, 0x34, 0x99, 0x52, 0xf7, 0xa7, 0xf6, 0xd3, 0x83, 0xa0, 0x17,
0x4b, 0x2d, 0xa7, 0xd4, 0xfd, 0xf7, 0x84, 0x45, 0xc4, 0x11, 0x71, 0x3d, 0x4a, 0x22, 0x34, 0x09,
0x9c, 0xa7, 0xe5, 0xc8, 0xba, 0x04, 0xbf, 0xfd, 0x25, 0x11, 0x7d, 0xa4, 0x43, 0x45, 0xc7, 0x62,
0x9e, 0x7b, 0x80, 0xf6, 0x09, 0xbb, 0x1b, 0x2e, 0xf3, 0xcd, 0x23, 0xe0, 0xed, 0x81, 0x43, 0x42,
0xbe, 0xc4, 0x9f, 0x58, 0x8a, 0x0d, 0x66, 0x79, 0x09, 0x70, 0x11, 0x68, 0x3d, 0x87, 0x38, 0x1c,
0x3c, 0x85, 0x52, 0x5b, 0x62, 0xf7, 0x3e, 0x7e, 0x87, 0xa2, 0x99, 0x24, 0xd0, 0x7d, 0x18, 0x63,
0x56, 0x48, 0xa4, 0x3a, 0xfe, 0x65, 0xfa, 0xa4, 0xd0, 0x67, 0xaa, 0x98, 0x65, 0x4d, 0xe4, 0x22,
0x75, 0x45, 0x52, 0xe8, 0x41, 0xc7, 0xed, 0x38, 0xeb, 0xf5, 0x02, 0x90, 0xc9, 0x45, 0xa3, 0xb0,
0x4d, 0x03, 0xd7, 0xab, 0x43, 0xe4, 0x21, 0xfc, 0x83, 0xd6, 0x12, 0x1d, 0x76, 0xb1, 0x3c, 0x67,
0x63, 0x1f, 0x52, 0x9d, 0xc3, 0x23, 0x5c, 0x4e, 0xa6, 0x8d, 0x01, 0x4a, 0xba, 0x9a, 0xf4, 0x16,
0x5b, 0x67, 0xc8, 0xe1, 0xd2, 0x42, 0x6d, 0xdf, 0xcd, 0x08, 0x6a, 0x73, 0x41, 0x6a, 0xc2, 0x84,
0xc6, 0x31, 0xbe, 0x57, 0xcb, 0x0e, 0xde, 0xbf, 0x71, 0xd5, 0x8a, 0xf7, 0x24, 0xb2, 0xa7, 0x89,
0x96, 0x62, 0x4f, 0xd9, 0xf7, 0xc3, 0xde, 0x4c, 0xab, 0x13, 0x72, 0xb4, 0xb3, 0x35, 0x04, 0x82,
0xa8, 0x75, 0x1d, 0xde, 0x46, 0xa8, 0x0d, 0xb8, 0x23, 0x44, 0x00, 0x44, 0xfa, 0x53, 0x6c, 0x2d,
0xce, 0xd3, 0xa6, 0x80, 0xa1, 0x20, 0xca, 0xd1, 0x63, 0xbb, 0xbe, 0x39, 0x5f, 0x9d, 0x27, 0x69,
0xb3, 0x33, 0x1f, 0xdb, 0xda, 0x67, 0x05, 0x37, 0xbe, 0x65, 0xe9, 0x7e, 0xa9, 0xc3, 0xff, 0x37,
0x8a, 0xb4, 0x2d, 0xfe, 0xf2, 0x16, 0x85, 0xc7, 0x0f, 0xd9, 0xbe, 0x14, 0xd1, 0x80, 0x14, 0x9f,
0x58, 0x56, 0x98, 0x41, 0xf6, 0x26, 0xf7, 0xa2, 0x71, 0x66, 0xb4, 0x7a, 0x9c, 0x12, 0x73, 0xd3,
0xdf, 0x77, 0x2b, 0x49, 0xe5, 0xca, 0x50, 0x57, 0x44, 0x6e, 0x3f, 0x58, 0x56, 0xbc, 0x21, 0x70,
0x4f, 0xc6, 0xaa, 0x12, 0xff, 0x7c, 0xa7, 0x3d, 0xed, 0x46, 0xc1, 0x40, 0xe6, 0x58, 0x09, 0x2a,
0xda, 0xb3, 0x76, 0xab, 0x44, 0xb5, 0x4e, 0xb3, 0x12, 0xe0, 0x26, 0x8a, 0x52, 0xac, 0x49, 0x1d,
0xe7, 0x06, 0x53, 0x3a, 0x01, 0x35, 0x21, 0x2e, 0x86, 0x48, 0xc5, 0x75, 0xc1, 0xa2, 0x7d, 0x22,
0x53, 0xf6, 0x3f, 0x41, 0xc5, 0xb3, 0x08, 0x7d, 0xa3, 0x67, 0xc0, 0xbb, 0xb6, 0x8d, 0xf0, 0xd3,
0x01, 0x72, 0xd3, 0x63, 0x82, 0x01, 0x1a, 0xe7, 0x1d, 0x22, 0xfa, 0x95, 0x33, 0xf6, 0xf2, 0xde,
0xa2, 0x53, 0x86, 0x55, 0x5a, 0xb4, 0x2e, 0x75, 0x75, 0xc6, 0xd5, 0x93, 0x9c, 0x57, 0xa9, 0x1f,
0xb9, 0x3e, 0xe8, 0x1c, 0xbf, 0xac, 0x1c, 0x54, 0x6f, 0xf5, 0xab, 0x41, 0xee, 0xb3, 0x0e, 0xd0,
0x76, 0xc4, 0x1a, 0x45, 0xcd, 0xf1, 0xd6, 0xcc, 0xb0, 0x83, 0x70, 0x73, 0xbc, 0x88, 0x74, 0xa0,
0x5b, 0xe7, 0x98, 0x10, 0x36, 0xbf, 0xec, 0x23, 0x1c, 0xc2, 0xb5, 0xba, 0x4b, 0x9d, 0x7f, 0x8c,
0x8a, 0xe2, 0xda, 0x18, 0xdd, 0xab, 0x27, 0x8a, 0x15, 0xeb, 0xb0, 0xd4, 0x3a, 0x8b, 0x77, 0x00,
0xc7, 0xbb, 0xcc, 0xfa, 0xba, 0xa4, 0x6a, 0x17, 0x5c, 0xf8, 0x51, 0x5d, 0x8d, 0x16, 0xcd, 0xa7,
0x0e, 0x71, 0x97, 0x98, 0x78, 0x5a, 0x41, 0xb3, 0xf0, 0x1f, 0x87, 0x2d, 0x65, 0xcd, 0x29, 0x49,
0xd2, 0x87, 0x2c, 0x91, 0xa9, 0x5f, 0xcc, 0xa9, 0xd8, 0xbb, 0x53, 0x18, 0xe7, 0xd6, 0xec, 0x65,
0xa6, 0x45, 0xf6, 0xce, 0xcf, 0x48, 0xf6, 0x1e, 0x3d, 0xd2, 0xcf, 0xcb, 0x3a, 0xcd, 0xbb, 0x92,
0x29, 0x24, 0x16, 0x7f, 0x8a, 0xa8, 0x5c, 0x0c, 0x45, 0x71, 0x33
};
const unsigned char commit_1[] = {
0x08,
0xf5, 0x1e, 0x0d, 0xc5, 0x86, 0x78, 0x51, 0xa9, 0x00, 0x00, 0xef, 0x4d, 0xe2, 0x94, 0x60, 0x89,
0x83, 0x04, 0xb4, 0x0e, 0x90, 0x10, 0x05, 0x1c, 0x7f, 0xd7, 0x33, 0x92, 0x1f, 0xe7, 0x74, 0x59
};
size_t min_value_1;
size_t max_value_1;
secp256k1_pedersen_commitment pc;
CHECK(secp256k1_pedersen_commitment_parse(ctx, &pc, commit_1));
CHECK(secp256k1_rangeproof_verify(
ctx,
&min_value_1, &max_value_1,
&pc,
vector_1, sizeof(vector_1),
NULL, 0,
secp256k1_generator_h
));
}
void test_pedersen_commitment_fixed_vector(void) {
const unsigned char two_g[33] = {
0x09,
0xc6, 0x04, 0x7f, 0x94, 0x41, 0xed, 0x7d, 0x6d, 0x30, 0x45, 0x40, 0x6e, 0x95, 0xc0, 0x7c, 0xd8,
0x5c, 0x77, 0x8e, 0x4b, 0x8c, 0xef, 0x3c, 0xa7, 0xab, 0xac, 0x09, 0xb9, 0x5c, 0x70, 0x9e, 0xe5
};
unsigned char result[33];
secp256k1_pedersen_commitment parse;
CHECK(secp256k1_pedersen_commitment_parse(ctx, &parse, two_g));
CHECK(secp256k1_pedersen_commitment_serialize(ctx, result, &parse));
CHECK(memcmp(two_g, result, 33) == 0);
result[0] = 0x08;
CHECK(secp256k1_pedersen_commitment_parse(ctx, &parse, result));
result[0] = 0x0c;
CHECK(!secp256k1_pedersen_commitment_parse(ctx, &parse, result));
}
void run_rangeproof_tests(void) {
int i;
test_api();
test_rangeproof_fixed_vectors();
test_pedersen_commitment_fixed_vector();
for (i = 0; i < 10*count; i++) {
test_pedersen();
}