Skip to content

Commit 24ae07c

Browse files
committed
Introduce secp256k1_pubkey_t type
1 parent 1b68366 commit 24ae07c

File tree

6 files changed

+202
-246
lines changed

6 files changed

+202
-246
lines changed

include/secp256k1.h

Lines changed: 59 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -74,25 +74,67 @@ void secp256k1_context_destroy(
7474
secp256k1_context_t* ctx
7575
) SECP256K1_ARG_NONNULL(1);
7676

77+
/** Data type to hold a parsed public key.
78+
This data type should be considered opaque to the user, and only created
79+
through API functions.
80+
*/
81+
typedef struct {
82+
unsigned char data[64];
83+
} secp256k1_pubkey_t;
84+
85+
/** Parse a variable-length public key into the pubkey object.
86+
* Returns: 1 if the public key was fully valid.
87+
* 0 if the public key could not be parsed or is invalid.
88+
* In: ctx: a secp256k1 context object.
89+
* input: pointer to a serialized public key
90+
* inputlen: length of the array pointed to by input
91+
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
92+
* parsed version of input. If not, its value is undefined.
93+
* This function supports parsing compressed (33 bytes, header byte 0x02 or
94+
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header
95+
* byte 0x06 or 0x07) format public keys.
96+
*/
97+
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
98+
const secp256k1_context_t* ctx,
99+
secp256k1_pubkey_t* pubkey,
100+
const unsigned char *input,
101+
int inputlen
102+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
103+
104+
/** Serialize a pubkey object into a serialized byte sequence.
105+
* Returns: 1 always.
106+
* In: ctx: a secp256k1 context object.
107+
* pubkey: a pointer to a secp256k1_pubkey_t containing an initialized
108+
* public key.
109+
* compressed: whether to serialize in compressed format.
110+
* Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if
111+
* compressed==1) byte array to place the serialized key in.
112+
* outputlen: a pointer to an integer which will contain the serialized
113+
* size.
114+
*/
115+
int secp256k1_ec_pubkey_serialize(
116+
const secp256k1_context_t* ctx,
117+
unsigned char *output,
118+
int *outputlen,
119+
const secp256k1_pubkey_t* pubkey,
120+
int compressed
121+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
122+
77123
/** Verify an ECDSA signature.
78124
* Returns: 1: correct signature
79-
* 0: incorrect signature
80-
* -1: invalid public key
81-
* -2: invalid signature
125+
* 0: incorrect or unparseable signature
82126
* In: ctx: a secp256k1 context object, initialized for verification.
83127
* msg32: the 32-byte message hash being verified (cannot be NULL)
84128
* sig: the signature being verified (cannot be NULL)
85129
* siglen: the length of the signature
86130
* pubkey: the public key to verify with (cannot be NULL)
87-
* pubkeylen: the length of pubkey
88131
*/
89132
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
90133
const secp256k1_context_t* ctx,
91134
const unsigned char *msg32,
92135
const unsigned char *sig,
93136
int siglen,
94-
const unsigned char *pubkey,
95-
int pubkeylen
137+
const secp256k1_pubkey_t *pubkey
96138
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
97139

98140
/** A pointer to a function to deterministically generate a nonce.
@@ -124,7 +166,6 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979;
124166
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
125167
extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
126168

127-
128169
/** Create an ECDSA signature.
129170
* Returns: 1: signature created
130171
* 0: the nonce generation function failed, the private key was invalid, or there is not
@@ -202,20 +243,16 @@ int secp256k1_ecdsa_sign_compact(
202243
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
203244
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
204245
* sig64: signature as 64 byte array (cannot be NULL)
205-
* compressed: whether to recover a compressed or uncompressed pubkey
206246
* recid: the recovery id (0-3, as returned by ecdsa_sign_compact)
207-
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL)
208-
* pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL)
247+
* Out: pubkey: pointer to the recoved public key (cannot be NULL)
209248
*/
210249
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
211250
const secp256k1_context_t* ctx,
212251
const unsigned char *msg32,
213252
const unsigned char *sig64,
214-
unsigned char *pubkey,
215-
int *pubkeylen,
216-
int compressed,
253+
secp256k1_pubkey_t *pubkey,
217254
int recid
218-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
255+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
219256

220257
/** Verify an ECDSA secret key.
221258
* Returns: 1: secret key is valid
@@ -228,24 +265,11 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
228265
const unsigned char *seckey
229266
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
230267

231-
/** Just validate a public key.
232-
* Returns: 1: public key is valid
233-
* 0: public key is invalid
234-
* In: ctx: pointer to a context object (cannot be NULL)
235-
* pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
236-
* pubkeylen: length of pubkey
237-
*/
238-
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(
239-
const secp256k1_context_t* ctx,
240-
const unsigned char *pubkey,
241-
int pubkeylen
242-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
243-
244268
/** Compute the public key for a secret key.
245269
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
246270
* compressed: whether the computed public key should be compressed
247271
* seckey: pointer to a 32-byte private key (cannot be NULL)
248-
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
272+
* Out: pubkey: pointer to the created public key (cannot be NULL)
249273
* area to store the public key (cannot be NULL)
250274
* pubkeylen: pointer to int that will be updated to contains the pubkey's
251275
* length (cannot be NULL)
@@ -254,45 +278,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(
254278
*/
255279
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
256280
const secp256k1_context_t* ctx,
257-
unsigned char *pubkey,
258-
int *pubkeylen,
259-
const unsigned char *seckey,
260-
int compressed
261-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
262-
263-
/** Compress a public key.
264-
* In: ctx: pointer to a context object (cannot be NULL)
265-
* pubkeyin: pointer to a 33-byte or 65-byte public key (cannot be NULL)
266-
* Out: pubkeyout: pointer to a 33-byte array to put the compressed public key (cannot be NULL)
267-
* May alias pubkeyin.
268-
* pubkeylen: pointer to the size of the public key pointed to by pubkeyin (cannot be NULL)
269-
* It will be updated to reflect the size of the public key in pubkeyout.
270-
* Returns: 0: pubkeyin was invalid
271-
* 1: pubkeyin was valid, and pubkeyout is its compressed version
272-
*/
273-
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_compress(
274-
const secp256k1_context_t* ctx,
275-
const unsigned char *pubkeyin,
276-
unsigned char *pubkeyout,
277-
int *pubkeylen
278-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
279-
280-
/** Decompress a public key.
281-
* In: ctx: pointer to a context object (cannot be NULL)
282-
* pubkeyin: pointer to a 33-byte or 65-byte public key (cannot be NULL)
283-
* Out: pubkeyout: pointer to a 65-byte array to put the decompressed public key (cannot be NULL)
284-
* May alias pubkeyin.
285-
* pubkeylen: pointer to the size of the public key pointed to by pubkeyin (cannot be NULL)
286-
* It will be updated to reflect the size of the public key in pubkeyout.
287-
* Returns: 0: pubkeyin was invalid
288-
* 1: pubkeyin was valid, and pubkeyout is its decompressed version
289-
*/
290-
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress(
291-
const secp256k1_context_t* ctx,
292-
const unsigned char *pubkeyin,
293-
unsigned char *pubkeyout,
294-
int *pubkeylen
295-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
281+
secp256k1_pubkey_t *pubkey,
282+
const unsigned char *seckey
283+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
296284

297285
/** Export a private key in DER format.
298286
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
@@ -325,10 +313,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
325313
*/
326314
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
327315
const secp256k1_context_t* ctx,
328-
unsigned char *pubkey,
329-
int pubkeylen,
316+
secp256k1_pubkey_t *pubkey,
330317
const unsigned char *tweak
331-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
318+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
332319

333320
/** Tweak a private key by multiplying it with tweak. */
334321
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
@@ -342,10 +329,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
342329
*/
343330
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
344331
const secp256k1_context_t* ctx,
345-
unsigned char *pubkey,
346-
int pubkeylen,
332+
secp256k1_pubkey_t *pubkey,
347333
const unsigned char *tweak
348-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
334+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
349335

350336
/** Updates the context randomization.
351337
* Returns: 1: randomization successfully updated

src/bench_recover.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ typedef struct {
1717
void bench_recover(void* arg) {
1818
int i;
1919
bench_recover_t *data = (bench_recover_t*)arg;
20-
unsigned char pubkey[33];
20+
secp256k1_pubkey_t pubkey;
21+
unsigned char pubkeyc[33];
2122

2223
for (i = 0; i < 20000; i++) {
2324
int j;
2425
int pubkeylen = 33;
25-
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
26+
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, &pubkey, 1));
27+
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, i % 2));
2628
for (j = 0; j < 32; j++) {
2729
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
2830
data->msg[j] = data->sig[j]; /* Move former R to message. */
29-
data->sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
31+
data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
3032
}
3133
}
3234
}

src/bench_verify.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ static void benchmark_verify(void* arg) {
2626
benchmark_verify_t* data = (benchmark_verify_t*)arg;
2727

2828
for (i = 0; i < 20000; i++) {
29+
secp256k1_pubkey_t pubkey;
2930
data->sig[data->siglen - 1] ^= (i & 0xFF);
3031
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
3132
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
32-
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
33+
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
34+
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, &pubkey) == (i == 0));
3335
data->sig[data->siglen - 1] ^= (i & 0xFF);
3436
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
3537
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
@@ -38,6 +40,7 @@ static void benchmark_verify(void* arg) {
3840

3941
int main(void) {
4042
int i;
43+
secp256k1_pubkey_t pubkey;
4144
benchmark_verify_t data;
4245

4346
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
@@ -46,8 +49,8 @@ int main(void) {
4649
for (i = 0; i < 32; i++) data.key[i] = 33 + i;
4750
data.siglen = 72;
4851
secp256k1_ecdsa_sign(data.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
49-
data.pubkeylen = 33;
50-
CHECK(secp256k1_ec_pubkey_create(data.ctx, data.pubkey, &data.pubkeylen, data.key, 1));
52+
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
53+
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, 1) == 1);
5154

5255
run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
5356

src/eckey.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "ecmult_gen.h"
1414

1515
static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
16-
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);
1716

1817
static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen);
1918
static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);

0 commit comments

Comments
 (0)