Merge pull request #30 from apoelstra/2018-09-audit-set-xquad

check the value of `ge_set_xquad` everywhere in -zkp modules
This commit is contained in:
Andrew Poelstra 2018-10-04 16:35:38 +00:00 committed by GitHub
commit b2dca3ae19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 135 additions and 36 deletions

View File

@ -13,15 +13,12 @@ extern "C" {
* *
* The exact representation of data inside is implementation defined and not * The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is * 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. * 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 or transmission, use * If you need to convert to a format suitable for storage, transmission, or
* the secp256k1_generator_serialize_*. * comparison, use secp256k1_generator_serialize and secp256k1_generator_parse.
*
* Furthermore, it is guaranteed to identical points will have identical
* representation, so they can be memcmp'ed.
*/ */
typedef struct { typedef struct {
unsigned char data[33]; unsigned char data[64];
} secp256k1_generator; } secp256k1_generator;
/** Parse a 33-byte generator byte sequence into a generator object. /** Parse a 33-byte generator byte sequence into a generator object.

View File

@ -14,15 +14,13 @@ extern "C" {
* *
* The exact representation of data inside is implementation defined and not * The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is * 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. * 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 or transmission, use * If you need to convert to a format suitable for storage, transmission, or
* secp256k1_pedersen_commitment_serialize and secp256k1_pedersen_commitment_parse. * comparison, 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.
*/ */
typedef struct { typedef struct {
unsigned char data[33]; unsigned char data[64];
} secp256k1_pedersen_commitment; } secp256k1_pedersen_commitment;
/** /**

View File

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

View File

@ -16,13 +16,14 @@
/** Alternative generator for secp256k1. /** Alternative generator for secp256k1.
* This is the sha256 of 'g' after DER encoding (without compression), * This is the sha256 of 'g' after DER encoding (without compression),
* which happens to be a point on the curve. * 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: G2 = EllipticCurve ([F (0), F (7)]).lift_x(F(int(hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')).hexdigest(),16)))
* sage: '%x %x' % (11 - G2.xy()[1].is_square(), G2.xy()[0]) * sage: '%x %x' % G2.xy()
*/ */
static const secp256k1_generator secp256k1_generator_h_internal = {{ 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, 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; 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) { 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); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(commit != NULL); ARG_CHECK(commit != NULL);
ARG_CHECK(input != NULL); ARG_CHECK(input != NULL);
(void) ctx; (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; 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; return 1;
} }
int secp256k1_pedersen_commitment_serialize(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pedersen_commitment* commit) { int secp256k1_pedersen_commitment_serialize(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pedersen_commitment* commit) {
secp256k1_ge ge;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(output != NULL); ARG_CHECK(output != NULL);
ARG_CHECK(commit != NULL); ARG_CHECK(commit != NULL);
memcpy(output, commit->data, sizeof(commit->data));
secp256k1_pedersen_commitment_load(&ge, commit);
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; 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++) { for(i = 0; i < rings - 1; i++) {
secp256k1_fe fe; secp256k1_fe fe;
secp256k1_fe_set_b32(&fe, &proof[offset]); if (!secp256k1_fe_set_b32(&fe, &proof[offset]) ||
secp256k1_ge_set_xquad(&c, &fe); !secp256k1_ge_set_xquad(&c, &fe)) {
return 0;
}
if (signs[i]) { if (signs[i]) {
secp256k1_ge_neg(&c, &c); secp256k1_ge_neg(&c, &c);
} }

View File

@ -607,9 +607,75 @@ 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 run_rangeproof_tests(void) { void run_rangeproof_tests(void) {
int i; int i;
test_api(); test_api();
test_rangeproof_fixed_vectors();
for (i = 0; i < 10*count; i++) { for (i = 0; i < 10*count; i++) {
test_pedersen(); test_pedersen();
} }