Skip to content

Commit 4a243da

Browse files
committed
Move secp256k1_ec_privkey_import/export to contrib.
These functions are intended for compatibility with legacy software, and are not normally needed in new secp256k1 applications. They also do not obeying any particular standard (and likely cannot without without undermining their compatibility), and so are a better fit for contrib.
1 parent 1b3efc1 commit 4a243da

File tree

6 files changed

+215
-186
lines changed

6 files changed

+215
-186
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ noinst_HEADERS += src/field.h
4141
noinst_HEADERS += src/field_impl.h
4242
noinst_HEADERS += src/bench.h
4343
noinst_HEADERS += contrib/lax_der_parsing.h
44+
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
4445

4546
pkgconfigdir = $(libdir)/pkgconfig
4647
pkgconfig_DATA = libsecp256k1.pc
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/**********************************************************************
2+
* Copyright (c) 2014, 2015 Pieter Wuille *
3+
* Distributed under the MIT software license, see the accompanying *
4+
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5+
**********************************************************************/
6+
7+
/* This file contains code snippets that parse DER private keys with
8+
* various errors and violations. This is not a part of the library
9+
* itself, because the allowed violations are chosen arbitrarily and
10+
* do not follow or establish any standard.
11+
*
12+
* It also contains code to serialize private keys in a compatible
13+
* manner.
14+
*
15+
* These functions are meant for compatibility with applications
16+
* that require BER encoded keys. When working with secp256k1-specific
17+
* code, the simple 32-byte private keys normally used by the
18+
* library are sufficient.
19+
*/
20+
21+
#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_
22+
#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_
23+
24+
#include <string.h>
25+
#include <secp256k1.h>
26+
27+
/** Export a private key in DER format.
28+
*
29+
* Returns: 1 if the private key was valid.
30+
* Args: ctx: pointer to a context object, initialized for signing (cannot
31+
* be NULL)
32+
* Out: privkey: pointer to an array for storing the private key in BER.
33+
* Should have space for 279 bytes, and cannot be NULL.
34+
* privkeylen: Pointer to an int where the length of the private key in
35+
* privkey will be stored.
36+
* In: seckey: pointer to a 32-byte secret key to export.
37+
* flags: SECP256K1_EC_COMPRESSED if the key should be exported in
38+
* compressed format.
39+
*
40+
* This function is purely meant for compatibility with applications that
41+
* require BER encoded keys. When working with secp256k1-specific code, the
42+
* simple 32-byte private keys are sufficient.
43+
*
44+
* Note that this function does not guarantee correct DER output. It is
45+
* guaranteed to be parsable by secp256k1_ec_privkey_import.
46+
*/
47+
static SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export_der(
48+
const secp256k1_context* ctx,
49+
unsigned char *privkey,
50+
size_t *privkeylen,
51+
const unsigned char *seckey,
52+
unsigned int flags
53+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
54+
55+
/** Import a private key in DER format.
56+
* Returns: 1 if a private key was extracted.
57+
* Args: ctx: pointer to a context object (cannot be NULL).
58+
* Out: seckey: pointer to a 32-byte array for storing the private key.
59+
* (cannot be NULL).
60+
* In: privkey: pointer to a private key in DER format (cannot be NULL).
61+
* privkeylen: length of the DER private key pointed to be privkey.
62+
*
63+
* This function will accept more than just strict DER, and even allow some BER
64+
* violations. The public key stored inside the DER-encoded private key is not
65+
* verified for correctness, nor are the curve parameters. Use this function
66+
* only if you know in advance it is supposed to contain a secp256k1 private
67+
* key.
68+
*/
69+
static SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import_der(
70+
const secp256k1_context* ctx,
71+
unsigned char *seckey,
72+
const unsigned char *privkey,
73+
size_t privkeylen
74+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
75+
76+
static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen) {
77+
unsigned char c[32] = {0};
78+
const unsigned char *end = privkey + privkeylen;
79+
int lenb = 0;
80+
int len = 0;
81+
int overflow = 0;
82+
/* sequence header */
83+
if (end < privkey+1 || *privkey != 0x30) {
84+
return 0;
85+
}
86+
privkey++;
87+
/* sequence length constructor */
88+
if (end < privkey+1 || !(*privkey & 0x80)) {
89+
return 0;
90+
}
91+
lenb = *privkey & ~0x80; privkey++;
92+
if (lenb < 1 || lenb > 2) {
93+
return 0;
94+
}
95+
if (end < privkey+lenb) {
96+
return 0;
97+
}
98+
/* sequence length */
99+
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
100+
privkey += lenb;
101+
if (end < privkey+len) {
102+
return 0;
103+
}
104+
/* sequence element 0: version number (=1) */
105+
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) {
106+
return 0;
107+
}
108+
privkey += 3;
109+
/* sequence element 1: octet string, up to 32 bytes */
110+
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) {
111+
return 0;
112+
}
113+
memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);
114+
secp256k1_scalar_set_b32(key, c, &overflow);
115+
memset(c, 0, 32);
116+
return !overflow;
117+
}
118+
119+
static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags) {
120+
secp256k1_gej rp;
121+
secp256k1_ge r;
122+
size_t pubkeylen = 0;
123+
secp256k1_ecmult_gen(ctx, &rp, key);
124+
secp256k1_ge_set_gej(&r, &rp);
125+
if (flags & SECP256K1_EC_COMPRESSED) {
126+
static const unsigned char begin[] = {
127+
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20
128+
};
129+
static const unsigned char middle[] = {
130+
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
131+
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
132+
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
133+
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
134+
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
135+
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
136+
0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
137+
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
138+
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00
139+
};
140+
unsigned char *ptr = privkey;
141+
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
142+
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
143+
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
144+
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {
145+
return 0;
146+
}
147+
ptr += pubkeylen;
148+
*privkeylen = ptr - privkey;
149+
} else {
150+
static const unsigned char begin[] = {
151+
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20
152+
};
153+
static const unsigned char middle[] = {
154+
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
155+
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
156+
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
157+
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
158+
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
159+
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
160+
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11,
161+
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,
162+
0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
163+
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
164+
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00
165+
};
166+
unsigned char *ptr = privkey;
167+
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
168+
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
169+
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
170+
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {
171+
return 0;
172+
}
173+
ptr += pubkeylen;
174+
*privkeylen = ptr - privkey;
175+
}
176+
return 1;
177+
}
178+
179+
static int secp256k1_ec_privkey_export_der(const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, unsigned int flags) {
180+
secp256k1_scalar key;
181+
int ret = 0;
182+
VERIFY_CHECK(ctx != NULL);
183+
ARG_CHECK(seckey != NULL);
184+
ARG_CHECK(privkey != NULL);
185+
ARG_CHECK(privkeylen != NULL);
186+
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
187+
188+
secp256k1_scalar_set_b32(&key, seckey, NULL);
189+
ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, flags);
190+
secp256k1_scalar_clear(&key);
191+
return ret;
192+
}
193+
194+
static int secp256k1_ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen) {
195+
secp256k1_scalar key;
196+
int ret = 0;
197+
ARG_CHECK(seckey != NULL);
198+
ARG_CHECK(privkey != NULL);
199+
(void)ctx;
200+
201+
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
202+
if (ret) {
203+
secp256k1_scalar_get_b32(seckey, &key);
204+
}
205+
secp256k1_scalar_clear(&key);
206+
return ret;
207+
}
208+
209+
#endif

include/secp256k1.h

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -478,55 +478,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
478478
const unsigned char *seckey
479479
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
480480

481-
/** Export a private key in BER format.
482-
*
483-
* Returns: 1 if the private key was valid.
484-
* Args: ctx: pointer to a context object, initialized for signing (cannot
485-
* be NULL)
486-
* Out: privkey: pointer to an array for storing the private key in BER.
487-
* Should have space for 279 bytes, and cannot be NULL.
488-
* privkeylen: Pointer to an int where the length of the private key in
489-
* privkey will be stored.
490-
* In: seckey: pointer to a 32-byte secret key to export.
491-
* flags: SECP256K1_EC_COMPRESSED if the key should be exported in
492-
* compressed format.
493-
*
494-
* This function is purely meant for compatibility with applications that
495-
* require BER encoded keys. When working with secp256k1-specific code, the
496-
* simple 32-byte private keys are sufficient.
497-
*
498-
* Note that this function does not guarantee correct DER output. It is
499-
* guaranteed to be parsable by secp256k1_ec_privkey_import.
500-
*/
501-
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(
502-
const secp256k1_context* ctx,
503-
unsigned char *privkey,
504-
size_t *privkeylen,
505-
const unsigned char *seckey,
506-
unsigned int flags
507-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
508-
509-
/** Import a private key in DER format.
510-
* Returns: 1 if a private key was extracted.
511-
* Args: ctx: pointer to a context object (cannot be NULL).
512-
* Out: seckey: pointer to a 32-byte array for storing the private key.
513-
* (cannot be NULL).
514-
* In: privkey: pointer to a private key in DER format (cannot be NULL).
515-
* privkeylen: length of the DER private key pointed to be privkey.
516-
*
517-
* This function will accept more than just strict DER, and even allow some BER
518-
* violations. The public key stored inside the DER-encoded private key is not
519-
* verified for correctness, nor are the curve parameters. Use this function
520-
* only if you know in advance it is supposed to contain a secp256k1 private
521-
* key.
522-
*/
523-
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(
524-
const secp256k1_context* ctx,
525-
unsigned char *seckey,
526-
const unsigned char *privkey,
527-
size_t privkeylen
528-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
529-
530481
/** Tweak a private key by adding tweak to it.
531482
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
532483
* uniformly random 32-byte arrays, or if the resulting private key

src/eckey_impl.h

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -51,109 +51,6 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p
5151
return 1;
5252
}
5353

54-
static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen) {
55-
unsigned char c[32] = {0};
56-
const unsigned char *end = privkey + privkeylen;
57-
int lenb = 0;
58-
int len = 0;
59-
int overflow = 0;
60-
/* sequence header */
61-
if (end < privkey+1 || *privkey != 0x30) {
62-
return 0;
63-
}
64-
privkey++;
65-
/* sequence length constructor */
66-
if (end < privkey+1 || !(*privkey & 0x80)) {
67-
return 0;
68-
}
69-
lenb = *privkey & ~0x80; privkey++;
70-
if (lenb < 1 || lenb > 2) {
71-
return 0;
72-
}
73-
if (end < privkey+lenb) {
74-
return 0;
75-
}
76-
/* sequence length */
77-
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
78-
privkey += lenb;
79-
if (end < privkey+len) {
80-
return 0;
81-
}
82-
/* sequence element 0: version number (=1) */
83-
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) {
84-
return 0;
85-
}
86-
privkey += 3;
87-
/* sequence element 1: octet string, up to 32 bytes */
88-
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) {
89-
return 0;
90-
}
91-
memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);
92-
secp256k1_scalar_set_b32(key, c, &overflow);
93-
memset(c, 0, 32);
94-
return !overflow;
95-
}
96-
97-
static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags) {
98-
secp256k1_gej rp;
99-
secp256k1_ge r;
100-
size_t pubkeylen = 0;
101-
secp256k1_ecmult_gen(ctx, &rp, key);
102-
secp256k1_ge_set_gej(&r, &rp);
103-
if (flags & SECP256K1_EC_COMPRESSED) {
104-
static const unsigned char begin[] = {
105-
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20
106-
};
107-
static const unsigned char middle[] = {
108-
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
109-
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
110-
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
111-
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
112-
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
113-
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
114-
0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
115-
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
116-
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00
117-
};
118-
unsigned char *ptr = privkey;
119-
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
120-
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
121-
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
122-
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {
123-
return 0;
124-
}
125-
ptr += pubkeylen;
126-
*privkeylen = ptr - privkey;
127-
} else {
128-
static const unsigned char begin[] = {
129-
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20
130-
};
131-
static const unsigned char middle[] = {
132-
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
133-
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
134-
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
135-
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
136-
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
137-
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
138-
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11,
139-
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,
140-
0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
141-
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
142-
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00
143-
};
144-
unsigned char *ptr = privkey;
145-
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
146-
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
147-
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
148-
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {
149-
return 0;
150-
}
151-
ptr += pubkeylen;
152-
*privkeylen = ptr - privkey;
153-
}
154-
return 1;
155-
}
156-
15754
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
15855
secp256k1_scalar_add(key, key, tweak);
15956
if (secp256k1_scalar_is_zero(key)) {

0 commit comments

Comments
 (0)