Bitcoin ABC 0.32.10
P2P Digital Currency
pubkey.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2016 The Bitcoin Core developers
2// Copyright (c) 2017 The Zcash developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <pubkey.h>
7
8#include <secp256k1.h>
10#include <secp256k1_schnorr.h>
11
12namespace {
13
14struct Secp256k1SelfTester {
15 Secp256k1SelfTester() {
20 }
21} SECP256K1_SELFTESTER;
22
23} // namespace
24
37 const uint8_t *input, size_t inputlen) {
38 size_t rpos, rlen, spos, slen;
39 size_t pos = 0;
40 size_t lenbyte;
41 uint8_t tmpsig[64] = {0};
42 int overflow = 0;
43
44 /* Hack to initialize sig with a correctly-parsed but invalid signature. */
46 tmpsig);
47
48 /* Sequence tag byte */
49 if (pos == inputlen || input[pos] != 0x30) {
50 return 0;
51 }
52 pos++;
53
54 /* Sequence length bytes */
55 if (pos == inputlen) {
56 return 0;
57 }
58 lenbyte = input[pos++];
59 if (lenbyte & 0x80) {
60 lenbyte -= 0x80;
61 if (lenbyte > inputlen - pos) {
62 return 0;
63 }
64 pos += lenbyte;
65 }
66
67 /* Integer tag byte for R */
68 if (pos == inputlen || input[pos] != 0x02) {
69 return 0;
70 }
71 pos++;
72
73 /* Integer length for R */
74 if (pos == inputlen) {
75 return 0;
76 }
77 lenbyte = input[pos++];
78 if (lenbyte & 0x80) {
79 lenbyte -= 0x80;
80 if (lenbyte > inputlen - pos) {
81 return 0;
82 }
83 while (lenbyte > 0 && input[pos] == 0) {
84 pos++;
85 lenbyte--;
86 }
87 static_assert(sizeof(size_t) >= 4, "size_t too small");
88 if (lenbyte >= 4) {
89 return 0;
90 }
91 rlen = 0;
92 while (lenbyte > 0) {
93 rlen = (rlen << 8) + input[pos];
94 pos++;
95 lenbyte--;
96 }
97 } else {
98 rlen = lenbyte;
99 }
100 if (rlen > inputlen - pos) {
101 return 0;
102 }
103 rpos = pos;
104 pos += rlen;
105
106 /* Integer tag byte for S */
107 if (pos == inputlen || input[pos] != 0x02) {
108 return 0;
109 }
110 pos++;
111
112 /* Integer length for S */
113 if (pos == inputlen) {
114 return 0;
115 }
116 lenbyte = input[pos++];
117 if (lenbyte & 0x80) {
118 lenbyte -= 0x80;
119 if (lenbyte > inputlen - pos) {
120 return 0;
121 }
122 while (lenbyte > 0 && input[pos] == 0) {
123 pos++;
124 lenbyte--;
125 }
126 static_assert(sizeof(size_t) >= 4, "size_t too small");
127 if (lenbyte >= 4) {
128 return 0;
129 }
130 slen = 0;
131 while (lenbyte > 0) {
132 slen = (slen << 8) + input[pos];
133 pos++;
134 lenbyte--;
135 }
136 } else {
137 slen = lenbyte;
138 }
139 if (slen > inputlen - pos) {
140 return 0;
141 }
142 spos = pos;
143
144 /* Ignore leading zeroes in R */
145 while (rlen > 0 && input[rpos] == 0) {
146 rlen--;
147 rpos++;
148 }
149 /* Copy R value */
150 if (rlen > 32) {
151 overflow = 1;
152 } else {
153 memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
154 }
155
156 /* Ignore leading zeroes in S */
157 while (slen > 0 && input[spos] == 0) {
158 slen--;
159 spos++;
160 }
161 /* Copy S value */
162 if (slen > 32) {
163 overflow = 1;
164 } else {
165 memcpy(tmpsig + 64 - slen, input + spos, slen);
166 }
167
168 if (!overflow) {
171 }
172 if (overflow) {
173 /* Overwrite the result again with a correctly-parsed but invalid
174 signature if parsing failed. */
175 memset(tmpsig, 0, 64);
177 tmpsig);
178 }
179 return 1;
180}
181
183 const std::vector<uint8_t> &vchSig) const {
184 if (!IsValid()) {
185 return false;
186 }
187
188 secp256k1_pubkey pubkey;
191 size())) {
192 return false;
193 }
194 if (!ecdsa_signature_parse_der_lax(&sig, vchSig.data(), vchSig.size())) {
195 return false;
196 }
203 &pubkey);
204}
205
207 const uint256 &hash, const std::array<uint8_t, SCHNORR_SIZE> &sig) const {
208 if (!IsValid()) {
209 return false;
210 }
211
212 secp256k1_pubkey pubkey;
214 &(*this)[0], size())) {
215 return false;
216 }
217
219 hash.begin(), &pubkey);
220}
221
223 const std::vector<uint8_t> &vchSig) const {
224 if (vchSig.size() != SCHNORR_SIZE) {
225 return false;
226 }
227
228 std::array<uint8_t, SCHNORR_SIZE> sig;
229 std::copy(vchSig.begin(), vchSig.end(), sig.begin());
230
231 return VerifySchnorr(hash, sig);
232}
233
235 const std::vector<uint8_t> &vchSig) {
236 if (vchSig.size() != COMPACT_SIGNATURE_SIZE) {
237 return false;
238 }
239
240 int recid = (vchSig[0] - 27) & 3;
241 bool fComp = ((vchSig[0] - 27) & 4) != 0;
242 secp256k1_pubkey pubkey;
245 secp256k1_context_static, &sig, &vchSig[1], recid)) {
246 return false;
247 }
249 hash.begin())) {
250 return false;
251 }
252 uint8_t pub[SIZE];
253 size_t publen = SIZE;
255 secp256k1_context_static, pub, &publen, &pubkey,
257 Set(pub, pub + publen);
258 return true;
259}
260
262 if (!IsValid()) {
263 return false;
264 }
265 secp256k1_pubkey pubkey;
267 size());
268}
269
271 if (!IsValid()) {
272 return false;
273 }
274 secp256k1_pubkey pubkey;
276 size())) {
277 return false;
278 }
279 uint8_t pub[SIZE];
280 size_t publen = SIZE;
283 Set(pub, pub + publen);
284 return true;
285}
286
287bool CPubKey::Derive(CPubKey &pubkeyChild, ChainCode &ccChild,
288 unsigned int nChild, const ChainCode &cc) const {
289 assert(IsValid());
290 assert((nChild >> 31) == 0);
292 uint8_t out[64];
293 BIP32Hash(cc, nChild, *begin(), begin() + 1, out);
294 memcpy(ccChild.begin(), out + 32, 32);
295 secp256k1_pubkey pubkey;
297 size())) {
298 return false;
299 }
301 out)) {
302 return false;
303 }
304 uint8_t pub[COMPRESSED_SIZE];
305 size_t publen = COMPRESSED_SIZE;
307 &pubkey, SECP256K1_EC_COMPRESSED);
308 pubkeyChild.Set(pub, pub + publen);
309 return true;
310}
311
312void CExtPubKey::Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const {
313 code[0] = nDepth;
314 memcpy(code + 1, vchFingerprint, 4);
315 code[5] = (nChild >> 24) & 0xFF;
316 code[6] = (nChild >> 16) & 0xFF;
317 code[7] = (nChild >> 8) & 0xFF;
318 code[8] = (nChild >> 0) & 0xFF;
319 memcpy(code + 9, chaincode.begin(), 32);
321 memcpy(code + 41, pubkey.begin(), CPubKey::COMPRESSED_SIZE);
322}
323
324void CExtPubKey::Decode(const uint8_t code[BIP32_EXTKEY_SIZE]) {
325 nDepth = code[0];
326 memcpy(vchFingerprint, code + 1, 4);
327 nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
328 memcpy(chaincode.begin(), code + 9, 32);
329 pubkey.Set(code + 41, code + BIP32_EXTKEY_SIZE);
330}
331
332bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
333 out.nDepth = nDepth + 1;
334 CKeyID id = pubkey.GetID();
335 memcpy(out.vchFingerprint, &id, 4);
336 out.nChild = _nChild;
337 return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode);
338}
339
341 const boost::sliced_range<const std::vector<uint8_t>> &vchSig) {
343 if (!ecdsa_signature_parse_der_lax(&sig, &vchSig.front(), vchSig.size())) {
344 return false;
345 }
347 nullptr, &sig));
348}
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
An encapsulated public key.
Definition: pubkey.h:31
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:137
static constexpr unsigned int SCHNORR_SIZE
Definition: pubkey.h:38
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:37
uint8_t vch[SIZE]
see www.keylength.com script supports up to 75 for single byte push
Definition: pubkey.h:53
bool VerifySchnorr(const uint256 &hash, const std::array< uint8_t, SCHNORR_SIZE > &sig) const
Verify a Schnorr signature (=64 bytes).
Definition: pubkey.cpp:206
bool VerifyECDSA(const uint256 &hash, const std::vector< uint8_t > &vchSig) const
Verify a DER-serialized ECDSA signature (~72 bytes).
Definition: pubkey.cpp:182
bool IsValid() const
Definition: pubkey.h:147
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:270
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:36
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:261
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:98
bool RecoverCompact(const uint256 &hash, const std::vector< uint8_t > &vchSig)
Recover a public key from a compact ECDSA signature.
Definition: pubkey.cpp:234
const uint8_t * begin() const
Definition: pubkey.h:100
static bool CheckLowS(const boost::sliced_range< const std::vector< uint8_t > > &vchSig)
Check whether a DER-serialized ECDSA signature is normalized (lower-S).
Definition: pubkey.cpp:340
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:287
static constexpr unsigned int COMPACT_SIGNATURE_SIZE
Definition: pubkey.h:40
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:78
uint8_t * begin()
Definition: uint256.h:85
256-bit opaque blob.
Definition: uint256.h:129
void BIP32Hash(const ChainCode &chainCode, uint32_t nChild, uint8_t header, const uint8_t data[32], uint8_t output[64])
Definition: hash.cpp:72
SchnorrSig sig
Definition: processor.cpp:523
int ecdsa_signature_parse_der_lax(secp256k1_ecdsa_signature *sig, const uint8_t *input, size_t inputlen)
This function is taken from the libsecp256k1 distribution and implements DER parsing for ECDSA signat...
Definition: pubkey.cpp:36
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const unsigned char *input64) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse an ECDSA signature in compact (64 bytes) format.
Definition: secp256k1.c:371
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize a pubkey object into a serialized byte sequence.
Definition: secp256k1.c:282
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a variable-length public key into the pubkey object.
Definition: secp256k1.c:264
SECP256K1_API void secp256k1_selftest(void)
Perform basic self tests (to be used in conjunction with secp256k1_context_static)
Definition: secp256k1.c:88
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:213
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msghash32, const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Verify an ECDSA signature.
Definition: secp256k1.c:436
SECP256K1_API int secp256k1_ecdsa_signature_normalize(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3)
Convert a signature to a normalized lower-S form.
Definition: secp256k1.c:417
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Tweak a public key by adding tweak times the generator to it.
Definition: secp256k1.c:679
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:214
SECP256K1_API const secp256k1_context * secp256k1_context_static
A built-in constant secp256k1 context object with static storage duration, to be used in conjunction ...
Definition: secp256k1.c:76
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context *ctx, secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a compact ECDSA signature (64 bytes + recovery id).
Definition: main_impl.h:38
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *msghash32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Recover an ECDSA public key from a signature.
Definition: main_impl.h:138
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify(const secp256k1_context *ctx, const unsigned char *sig64, const unsigned char *msghash32, const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Verify a signature created by secp256k1_schnorr_sign.
Definition: main_impl.h:13
void Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:312
uint8_t nDepth
Definition: pubkey.h:194
ChainCode chaincode
Definition: pubkey.h:197
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:332
uint8_t vchFingerprint[4]
Definition: pubkey.h:195
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:324
CPubKey pubkey
Definition: pubkey.h:198
unsigned int nChild
Definition: pubkey.h:196
Opaque data structured that holds a parsed ECDSA signature, supporting pubkey recovery.
Opaque data structured that holds a parsed ECDSA signature.
Definition: secp256k1.h:87
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:74
assert(!tx.IsCoinBase())