Skip to content

Commit 59113ab

Browse files
jonasnickbenma
authored andcommitted
f serialize s2c_opening as 33 bytes instead of 34
1 parent 0b74a94 commit 59113ab

File tree

3 files changed

+54
-25
lines changed

3 files changed

+54
-25
lines changed

include/secp256k1.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -477,27 +477,27 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
477477
* Args: ctx: a secp256k1 context object.
478478
* Out: opening: pointer to an opening object. If 1 is returned, it is set to a
479479
* parsed version of input. If not, its value is undefined.
480-
* In: input34: pointer to 34-byte array with a serialized opening
480+
* In: input33: pointer to 33-byte array with a serialized opening
481481
*
482482
*/
483483
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_s2c_opening_parse(
484484
const secp256k1_context* ctx,
485485
secp256k1_s2c_opening* opening,
486-
const unsigned char *input34
486+
const unsigned char *input33
487487
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
488488

489489
/** Serialize a sign-to-contract opening into a byte sequence.
490490
*
491491
* Returns: 1 if the opening was successfully serialized.
492492
* 0 if the opening was not initializaed.
493493
* Args: ctx: a secp256k1 context object.
494-
* Out: output34: pointer to a 34-byte array to place the serialized opening
494+
* Out: output33: pointer to a 33-byte array to place the serialized opening
495495
* in.
496496
* In: opening: a pointer to an initialized `secp256k1_s2c_opening`.
497497
*/
498498
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_s2c_opening_serialize(
499499
const secp256k1_context* ctx,
500-
unsigned char *output34,
500+
unsigned char *output33,
501501
const secp256k1_s2c_opening* opening
502502
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
503503

src/secp256k1.c

+29-8
Original file line numberDiff line numberDiff line change
@@ -840,26 +840,47 @@ static int secp256k1_s2c_commit_is_init(const secp256k1_s2c_opening *opening) {
840840
return opening->magic == s2c_opening_magic;
841841
}
842842

843-
int secp256k1_s2c_opening_parse(const secp256k1_context* ctx, secp256k1_s2c_opening* opening, const unsigned char *input34) {
843+
/* s2c_opening is serialized as 33 bytes containing the compressed original pubnonce. In addition to
844+
* holding the EVEN or ODD tag, the first byte has the third bit set to 1 if the nonce was negated.
845+
* The remaining bits in the first byte are 0. */
846+
int secp256k1_s2c_opening_parse(const secp256k1_context* ctx, secp256k1_s2c_opening* opening, const unsigned char *input33) {
847+
unsigned char pk_ser[33];
844848
VERIFY_CHECK(ctx != NULL);
845849
ARG_CHECK(opening != NULL);
846-
ARG_CHECK(input34 != NULL);
850+
ARG_CHECK(input33 != NULL);
847851

848852
secp256k1_s2c_opening_init(opening);
849-
opening->nonce_is_negated = input34[0];
850-
return secp256k1_ec_pubkey_parse(ctx, &opening->original_pubnonce, &input34[1], 33);
853+
/* Return 0 if unknown bits are set */
854+
if ((input33[0] & ~0x06) != 0) {
855+
return 0;
856+
}
857+
/* Read nonce_is_negated bit */
858+
opening->nonce_is_negated = input33[0] & (1 << 2);
859+
memcpy(pk_ser, input33, sizeof(pk_ser));
860+
/* Unset nonce_is_negated bit to allow parsing the public key */
861+
pk_ser[0] &= ~(1 << 2);
862+
return secp256k1_ec_pubkey_parse(ctx, &opening->original_pubnonce, &pk_ser[0], 33);
851863
}
852864

853-
int secp256k1_s2c_opening_serialize(const secp256k1_context* ctx, unsigned char *output34, const secp256k1_s2c_opening* opening) {
865+
int secp256k1_s2c_opening_serialize(const secp256k1_context* ctx, unsigned char *output33, const secp256k1_s2c_opening* opening) {
854866
size_t outputlen = 33;
855867

856868
VERIFY_CHECK(ctx != NULL);
857-
ARG_CHECK(output34 != NULL);
869+
ARG_CHECK(output33 != NULL);
858870
ARG_CHECK(opening != NULL);
859871
ARG_CHECK(secp256k1_s2c_commit_is_init(opening));
860872

861-
output34[0] = opening->nonce_is_negated;
862-
return secp256k1_ec_pubkey_serialize(ctx, &output34[1], &outputlen, &opening->original_pubnonce, SECP256K1_EC_COMPRESSED);
873+
if (!secp256k1_ec_pubkey_serialize(ctx, &output33[0], &outputlen, &opening->original_pubnonce, SECP256K1_EC_COMPRESSED)) {
874+
return 0;
875+
}
876+
/* Verify that ec_pubkey_serialize only sets the first two bits of the
877+
* first byte, otherwise this function doesn't make any sense */
878+
VERIFY_CHECK(output33[0] == 0x02 || output33[0] == 0x03);
879+
if (opening->nonce_is_negated) {
880+
/* Set nonce_is_negated bit */
881+
output33[0] |= (1 << 2);
882+
}
883+
return 1;
863884
}
864885

865886
#ifdef ENABLE_MODULE_ECDH

src/tests.c

+21-13
Original file line numberDiff line numberDiff line change
@@ -4183,13 +4183,13 @@ void run_eckey_edge_case_test(void) {
41834183
secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
41844184
}
41854185

4186-
41874186
void run_s2c_opening_test(void) {
41884187
int i = 0;
4189-
unsigned char output[34];
4190-
unsigned char input[34] = {
4191-
0x01,
4192-
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4188+
unsigned char output[33];
4189+
/* First byte 0x06 means that nonce_is_negated and EVEN tag for the
4190+
* following compressed pubkey (which is valid). */
4191+
unsigned char input[33] = {
4192+
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41934193
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41944194
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41954195
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -4210,12 +4210,20 @@ void run_s2c_opening_test(void) {
42104210
/* First parsing, then serializing works */
42114211
CHECK(secp256k1_s2c_opening_parse(ctx, &opening, input) == 1);
42124212
CHECK(secp256k1_s2c_opening_serialize(ctx, output, &opening) == 1);
4213+
CHECK(secp256k1_s2c_opening_parse(ctx, &opening, input) == 1);
42134214

42144215
{
42154216
/* Invalid pubkey makes parsing fail */
4216-
unsigned char input_tmp[34];
4217+
unsigned char input_tmp[33];
42174218
memcpy(input_tmp, input, sizeof(input_tmp));
4218-
input_tmp[33] = 0;
4219+
/* Pubkey oddness tag is invalid */
4220+
input_tmp[0] = 0;
4221+
CHECK(secp256k1_s2c_opening_parse(ctx, &opening, input_tmp) == 0);
4222+
/* nonce_is_negated bit is set but pubkey oddness tag is invalid */
4223+
input_tmp[0] = 5;
4224+
CHECK(secp256k1_s2c_opening_parse(ctx, &opening, input_tmp) == 0);
4225+
/* Unknown bit is set */
4226+
input_tmp[0] = 8;
42194227
CHECK(secp256k1_s2c_opening_parse(ctx, &opening, input_tmp) == 0);
42204228
}
42214229

@@ -4225,13 +4233,13 @@ void run_s2c_opening_test(void) {
42254233
* points' x-coordinates are uniformly random */
42264234
if (secp256k1_s2c_opening_parse(ctx, &opening, input) == 1) {
42274235
CHECK(secp256k1_s2c_opening_serialize(ctx, output, &opening) == 1);
4228-
CHECK(memcmp(output, input, 34) == 0);
4236+
CHECK(memcmp(output, input, sizeof(output)) == 0);
42294237
}
4230-
secp256k1_rand256(input);
4231-
/* nonce_is_negated */
4232-
input[0] = input[0] & 1;
4233-
/* oddness */
4234-
input[1] = (input[1] % 2) + 2;
4238+
secp256k1_rand256(&input[1]);
4239+
/* Set pubkey oddness tag to first bit of input[1] */
4240+
input[0] = (input[1] & 1) + 2;
4241+
/* Set nonce_is_negated bit to input[1]'s 3rd bit */
4242+
input[0] |= (input[1] & (1 << 2));
42354243
i++;
42364244
} while(i < count);
42374245
}

0 commit comments

Comments
 (0)