Skip to content

Commit 0f84518

Browse files
committed
Add algolen argument to nonce function
This commit is based on code changes proposed in bitcoin-core/secp256k1#844. Responds to comment: BlockstreamResearch#117 (comment)
1 parent 1f43cd1 commit 0f84518

File tree

4 files changed

+66
-57
lines changed

4 files changed

+66
-57
lines changed

include/secp256k1_ecdsa_adaptor.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ extern "C" {
2828
* In: msg32: the 32-byte message hash being verified
2929
* key32: pointer to a 32-byte secret key
3030
* pk33: the 33-byte serialized pubkey corresponding to key32
31-
* algo16: pointer to a 16-byte array describing the signature
32-
* algorithm
31+
* algo: pointer to an array describing the signature algorithm
32+
* algolen: the length of the algo array
3333
* data: arbitrary data pointer that is passed through
3434
*
3535
* Except for test cases, this function should compute some cryptographic hash of
@@ -40,13 +40,14 @@ typedef int (*secp256k1_nonce_function_hardened_ecdsa_adaptor)(
4040
const unsigned char *msg32,
4141
const unsigned char *key32,
4242
const unsigned char *pk33,
43-
const unsigned char *algo16,
43+
const unsigned char *algo,
44+
size_t algolen,
4445
void *data
4546
);
4647

4748
/** A modified BIP-340 nonce generation function. If a data pointer is passed, it is
4849
* assumed to be a pointer to 32 bytes of auxiliary random data as defined in BIP-340.
49-
* The hash will be tagged with algo16 after removing all terminating null bytes.
50+
* The hash will be tagged with algo after removing all terminating null bytes.
5051
*/
5152
SECP256K1_API extern const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_ecdsa_adaptor;
5253

@@ -90,7 +91,7 @@ SECP256K1_API int secp256k1_ecdsa_adaptor_encrypt(
9091
* In: adaptor_sig162: pointer to 162-byte signature to verify
9192
* pubkey: pointer to the public key corresponding to the secret key
9293
* used for signing
93-
* msg32: pointer to the 32-byte message hash
94+
* msg32: pointer to the 32-byte message hash being verified
9495
* enckey: pointer to the adaptor encryption public key
9596
*/
9697
SECP256K1_API int secp256k1_ecdsa_adaptor_verify(

src/modules/ecdsa_adaptor/dleq_impl.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) {
1717
sha->bytes = 64;
1818
}
1919

20-
/* algo16 argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */
21-
static const unsigned char dleq_algo16[16] = "DLEQ\0\0\0\0\0\0\0\0\0\0\0\0";
20+
/* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */
21+
static const unsigned char dleq_algo[4] = "DLEQ";
2222

2323
static int secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) {
2424
unsigned char buf[33];
@@ -32,7 +32,7 @@ static int secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) {
3232
return 1;
3333
}
3434

35-
static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *algo16, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) {
35+
static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *algo, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) {
3636
secp256k1_sha256 sha;
3737
unsigned char buf[32];
3838
unsigned char key[32];
@@ -57,7 +57,7 @@ static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *algo16
5757
return 0;
5858
}
5959

60-
if (!noncefp(nonce, buf, key, pk, algo16, ndata)) {
60+
if (!noncefp(nonce, buf, key, pk, algo, sizeof(algo), ndata)) {
6161
return 0;
6262
}
6363
secp256k1_scalar_set_b32(k, nonce, NULL);
@@ -97,12 +97,12 @@ static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_c
9797

9898
/* Generates a proof that the discrete logarithm of P1 to the secp256k1 base G is the
9999
* same as the discrete logarithm of P2 to the base Y */
100-
static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const unsigned char *algo16, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) {
100+
static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const unsigned char *algo, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) {
101101
secp256k1_ge r1, r2;
102102
secp256k1_scalar k = { 0 };
103103
int ret = 1;
104104

105-
ret &= secp256k1_dleq_nonce(&k, algo16, sk, gen2, p1, p2, noncefp, ndata);
105+
ret &= secp256k1_dleq_nonce(&k, algo, sk, gen2, p1, p2, noncefp, ndata);
106106
/* R1 = k*G, R2 = k*Y */
107107
secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, &r1, &r2, &k, gen2);
108108
/* We declassify the non-secret values r1 and r2 to allow using them as

src/modules/ecdsa_adaptor/main_impl.h

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,16 @@ static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(secp256k1_s
9797
sha->bytes = 64;
9898
}
9999

100-
/* algo16 argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */
101-
static const unsigned char ecdsa_adaptor_algo16[16] = "ECDSAadaptor/non";
100+
/* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */
101+
static const unsigned char ecdsa_adaptor_algo[16] = "ECDSAadaptor/non";
102102

103103
/* Modified BIP-340 nonce function */
104-
static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo16, void *data) {
104+
static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo, size_t algolen, void *data) {
105105
secp256k1_sha256 sha;
106106
unsigned char masked_key[32];
107107
int i;
108108

109-
if (algo16 == NULL) {
109+
if (algo == NULL) {
110110
return 0;
111111
}
112112

@@ -119,20 +119,17 @@ static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned c
119119
}
120120
}
121121

122-
/* Tag the hash with algo16 which is important to avoid nonce reuse across
122+
/* Tag the hash with algo which is important to avoid nonce reuse across
123123
* algorithims. An optimized tagging implementation is used if the default
124124
* tag is provided. */
125-
if (secp256k1_memcmp_var(algo16, ecdsa_adaptor_algo16, 16) == 0) {
125+
if (algolen == sizeof(ecdsa_adaptor_algo)
126+
&& secp256k1_memcmp_var(algo, ecdsa_adaptor_algo, algolen) == 0) {
126127
secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged(&sha);
127-
} else if (secp256k1_memcmp_var(algo16, dleq_algo16, 16) == 0) {
128+
} else if (algolen == sizeof(dleq_algo)
129+
&& secp256k1_memcmp_var(algo, dleq_algo, algolen) == 0) {
128130
secp256k1_nonce_function_dleq_sha256_tagged(&sha);
129131
} else {
130-
int algo16_len = 16;
131-
/* Remove terminating null bytes */
132-
while (algo16_len > 0 && !algo16[algo16_len - 1]) {
133-
algo16_len--;
134-
}
135-
secp256k1_sha256_initialize_tagged(&sha, algo16, algo16_len);
132+
secp256k1_sha256_initialize_tagged(&sha, algo, algolen);
136133
}
137134

138135
/* Hash (masked-)key||pk||msg using the tagged hash as per BIP-340 */
@@ -179,7 +176,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char
179176

180177
ret &= secp256k1_pubkey_load(ctx, &enckey_ge, enckey);
181178
ret &= secp256k1_eckey_pubkey_serialize(&enckey_ge, buf33, &size, 1);
182-
ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo16, ndata);
179+
ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata);
183180
secp256k1_scalar_set_b32(&k, nonce32, NULL);
184181
ret &= !secp256k1_scalar_is_zero(&k);
185182
secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret);
@@ -196,7 +193,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char
196193
secp256k1_declassify(ctx, &r, sizeof(r));
197194

198195
/* dleq_proof = DLEQ_prove(k, (R', Y, R)) */
199-
ret &= secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, dleq_algo16, &k, &enckey_ge, &rp, &r, noncefp, ndata);
196+
ret &= secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, dleq_algo, &k, &enckey_ge, &rp, &r, noncefp, ndata);
200197

201198
ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey32);
202199
secp256k1_scalar_cmov(&sk, &secp256k1_scalar_one, !ret);

src/modules/ecdsa_adaptor/tests_impl.h

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -616,34 +616,37 @@ void test_ecdsa_adaptor_spec_vectors(void) {
616616
}
617617

618618
/* Nonce function that returns constant 0 */
619-
static int ecdsa_adaptor_nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *encryption_key33, const unsigned char *algo16, void *data) {
619+
static int ecdsa_adaptor_nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *encryption_key33, const unsigned char *algo, size_t algolen, void *data) {
620620
(void) msg32;
621621
(void) key32;
622622
(void) encryption_key33;
623-
(void) algo16;
623+
(void) algo;
624+
(void) algolen;
624625
(void) data;
625626
(void) nonce32;
626627
return 0;
627628
}
628629

629630
/* Nonce function that sets nonce to 0 */
630-
static int ecdsa_adaptor_nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *encryption_key33, const unsigned char *algo16, void *data) {
631+
static int ecdsa_adaptor_nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *encryption_key33, const unsigned char *algo, size_t algolen, void *data) {
631632
(void) msg32;
632633
(void) key32;
633634
(void) encryption_key33;
634-
(void) algo16;
635+
(void) algo;
636+
(void) algolen;
635637
(void) data;
636638

637639
memset(nonce32, 0, 32);
638640
return 1;
639641
}
640642

641643
/* Nonce function that sets nonce to 0xFF...0xFF */
642-
static int ecdsa_adaptor_nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *encryption_key33, const unsigned char *algo16, void *data) {
644+
static int ecdsa_adaptor_nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *encryption_key33, const unsigned char *algo, size_t algolen, void *data) {
643645
(void) msg32;
644646
(void) key32;
645647
(void) encryption_key33;
646-
(void) algo16;
648+
(void) algo;
649+
(void) algolen;
647650
(void) data;
648651

649652
memset(nonce32, 0xFF, 32);
@@ -653,11 +656,11 @@ static int ecdsa_adaptor_nonce_function_overflowing(unsigned char *nonce32, cons
653656
/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many
654657
* bytes) changes the hash function
655658
*/
656-
void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
659+
void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t algolen) {
657660
unsigned char nonces[2][32];
658-
CHECK(nonce_function_ecdsa_adaptor(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1);
661+
CHECK(nonce_function_ecdsa_adaptor(nonces[0], args[0], args[1], args[2], args[3], algolen, args[4]) == 1);
659662
secp256k1_testrand_flip(args[n_flip], n_bytes);
660-
CHECK(nonce_function_ecdsa_adaptor(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1);
663+
CHECK(nonce_function_ecdsa_adaptor(nonces[1], args[0], args[1], args[2], args[3], algolen, args[4]) == 1);
661664
CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0);
662665
}
663666

@@ -675,7 +678,8 @@ void ecdsa_adaptor_test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_
675678
void run_nonce_function_ecdsa_adaptor_tests(void) {
676679
unsigned char tag[16] = "ECDSAadaptor/non";
677680
unsigned char aux_tag[16] = "ECDSAadaptor/aux";
678-
unsigned char algo16[16] = "ECDSAadaptor/non";
681+
unsigned char algo[16] = "ECDSAadaptor/non";
682+
size_t algolen = sizeof(algo);
679683
unsigned char dleq_tag[4] = "DLEQ";
680684
secp256k1_sha256 sha;
681685
secp256k1_sha256 sha_optimized;
@@ -717,33 +721,40 @@ void run_nonce_function_ecdsa_adaptor_tests(void) {
717721
args[0] = msg;
718722
args[1] = key;
719723
args[2] = pk;
720-
args[3] = algo16;
724+
args[3] = algo;
721725
args[4] = aux_rand;
722726
for (i = 0; i < count; i++) {
723-
nonce_function_ecdsa_adaptor_bitflip(args, 0, 32);
724-
nonce_function_ecdsa_adaptor_bitflip(args, 1, 32);
725-
nonce_function_ecdsa_adaptor_bitflip(args, 2, 32);
726-
/* Flip algo16 special case "ECDSAadaptor/non" */
727-
nonce_function_ecdsa_adaptor_bitflip(args, 3, 16);
728-
/* Flip algo16 again */
729-
nonce_function_ecdsa_adaptor_bitflip(args, 3, 16);
730-
nonce_function_ecdsa_adaptor_bitflip(args, 4, 32);
727+
nonce_function_ecdsa_adaptor_bitflip(args, 0, 32, algolen);
728+
nonce_function_ecdsa_adaptor_bitflip(args, 1, 32, algolen);
729+
nonce_function_ecdsa_adaptor_bitflip(args, 2, 32, algolen);
730+
/* Flip algo special case "ECDSAadaptor/non" */
731+
nonce_function_ecdsa_adaptor_bitflip(args, 3, 16, algolen);
732+
/* Flip algo again */
733+
nonce_function_ecdsa_adaptor_bitflip(args, 3, 16, algolen);
734+
nonce_function_ecdsa_adaptor_bitflip(args, 4, 32, algolen);
731735
}
732736

733-
/* NULL algo16 is disallowed */
734-
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, NULL, NULL) == 0);
735-
/* Empty algo16 is fine */
736-
memset(algo16, 0x00, 16);
737-
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo16, NULL) == 1);
738-
/* algo16 with terminating null bytes is fine */
739-
algo16[1] = 65;
740-
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo16, NULL) == 1);
741-
/* Other algo16 is fine */
742-
memset(algo16, 0xFF, 16);
743-
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo16, NULL) == 1);
737+
/* NULL algo is disallowed */
738+
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, NULL, 0, NULL) == 0);
739+
/* Empty algo is fine */
740+
memset(algo, 0x00, algolen);
741+
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo, algolen, NULL) == 1);
742+
/* Other algo is fine */
743+
memset(algo, 0xFF, algolen);
744+
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo, algolen, NULL) == 1);
745+
746+
/* Different algolen gives different nonce */
747+
for (i = 0; i < count; i++) {
748+
unsigned char nonce2[32];
749+
uint32_t offset = secp256k1_testrand_int(algolen - 1);
750+
size_t algolen_tmp = (algolen + offset) % algolen;
751+
752+
CHECK(nonce_function_ecdsa_adaptor(nonce2, msg, key, pk, algo, algolen_tmp, NULL) == 1);
753+
CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0);
754+
}
744755

745756
/* NULL aux_rand argument is allowed. */
746-
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo16, NULL) == 1);
757+
CHECK(nonce_function_ecdsa_adaptor(nonce, msg, key, pk, algo, algolen, NULL) == 1);
747758
}
748759

749760
void test_ecdsa_adaptor_api(void) {

0 commit comments

Comments
 (0)