]>
Commit | Line | Data |
---|---|---|
f914f1a7 | 1 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
50fa0797 | 2 | // Copyright (c) 2017 The Zcash developers |
b4347f60 | 3 | // Distributed under the MIT software license, see the accompanying |
d2e74c55 CF |
4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | ||
6 | #include "pubkey.h" | |
7 | ||
3d02d0f6 PW |
8 | #include <secp256k1.h> |
9 | #include <secp256k1_recovery.h> | |
d2e74c55 | 10 | |
3d02d0f6 PW |
11 | namespace |
12 | { | |
13 | /* Global secp256k1_context object used for verification. */ | |
14 | secp256k1_context* secp256k1_context_verify = NULL; | |
15 | } | |
16 | ||
17 | /** This function is taken from the libsecp256k1 distribution and implements | |
18 | * DER parsing for ECDSA signatures, while supporting an arbitrary subset of | |
19 | * format violations. | |
20 | * | |
21 | * Supported violations include negative integers, excessive padding, garbage | |
22 | * at the end, and overly long length descriptors. This is safe to use in | |
23 | * Bitcoin because since the activation of BIP66, signatures are verified to be | |
24 | * strict DER before being passed to this module, and we know it supports all | |
25 | * violations present in the blockchain before that point. | |
26 | */ | |
27 | static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { | |
28 | size_t rpos, rlen, spos, slen; | |
29 | size_t pos = 0; | |
30 | size_t lenbyte; | |
31 | unsigned char tmpsig[64] = {0}; | |
32 | int overflow = 0; | |
33 | ||
34 | /* Hack to initialize sig with a correctly-parsed but invalid signature. */ | |
35 | secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); | |
36 | ||
37 | /* Sequence tag byte */ | |
38 | if (pos == inputlen || input[pos] != 0x30) { | |
39 | return 0; | |
40 | } | |
41 | pos++; | |
42 | ||
43 | /* Sequence length bytes */ | |
44 | if (pos == inputlen) { | |
45 | return 0; | |
46 | } | |
47 | lenbyte = input[pos++]; | |
48 | if (lenbyte & 0x80) { | |
49 | lenbyte -= 0x80; | |
50fa0797 | 50 | if (lenbyte > inputlen - pos) { |
3d02d0f6 PW |
51 | return 0; |
52 | } | |
53 | pos += lenbyte; | |
54 | } | |
55 | ||
56 | /* Integer tag byte for R */ | |
57 | if (pos == inputlen || input[pos] != 0x02) { | |
58 | return 0; | |
59 | } | |
60 | pos++; | |
61 | ||
62 | /* Integer length for R */ | |
63 | if (pos == inputlen) { | |
64 | return 0; | |
65 | } | |
66 | lenbyte = input[pos++]; | |
67 | if (lenbyte & 0x80) { | |
68 | lenbyte -= 0x80; | |
50fa0797 | 69 | if (lenbyte > inputlen - pos) { |
3d02d0f6 PW |
70 | return 0; |
71 | } | |
72 | while (lenbyte > 0 && input[pos] == 0) { | |
73 | pos++; | |
74 | lenbyte--; | |
75 | } | |
50fa0797 JG |
76 | static_assert(sizeof(size_t) >= 4, "size_t too small"); |
77 | if (lenbyte >= 4) { | |
3d02d0f6 PW |
78 | return 0; |
79 | } | |
80 | rlen = 0; | |
81 | while (lenbyte > 0) { | |
82 | rlen = (rlen << 8) + input[pos]; | |
83 | pos++; | |
84 | lenbyte--; | |
85 | } | |
86 | } else { | |
87 | rlen = lenbyte; | |
88 | } | |
89 | if (rlen > inputlen - pos) { | |
90 | return 0; | |
91 | } | |
92 | rpos = pos; | |
93 | pos += rlen; | |
94 | ||
95 | /* Integer tag byte for S */ | |
96 | if (pos == inputlen || input[pos] != 0x02) { | |
97 | return 0; | |
98 | } | |
99 | pos++; | |
100 | ||
101 | /* Integer length for S */ | |
102 | if (pos == inputlen) { | |
103 | return 0; | |
104 | } | |
105 | lenbyte = input[pos++]; | |
106 | if (lenbyte & 0x80) { | |
107 | lenbyte -= 0x80; | |
50fa0797 | 108 | if (lenbyte > inputlen - pos) { |
3d02d0f6 PW |
109 | return 0; |
110 | } | |
111 | while (lenbyte > 0 && input[pos] == 0) { | |
112 | pos++; | |
113 | lenbyte--; | |
114 | } | |
50fa0797 JG |
115 | static_assert(sizeof(size_t) >= 4, "size_t too small"); |
116 | if (lenbyte >= 4) { | |
3d02d0f6 PW |
117 | return 0; |
118 | } | |
119 | slen = 0; | |
120 | while (lenbyte > 0) { | |
121 | slen = (slen << 8) + input[pos]; | |
122 | pos++; | |
123 | lenbyte--; | |
124 | } | |
125 | } else { | |
126 | slen = lenbyte; | |
127 | } | |
128 | if (slen > inputlen - pos) { | |
129 | return 0; | |
130 | } | |
131 | spos = pos; | |
132 | pos += slen; | |
133 | ||
134 | /* Ignore leading zeroes in R */ | |
135 | while (rlen > 0 && input[rpos] == 0) { | |
136 | rlen--; | |
137 | rpos++; | |
138 | } | |
139 | /* Copy R value */ | |
140 | if (rlen > 32) { | |
141 | overflow = 1; | |
142 | } else { | |
143 | memcpy(tmpsig + 32 - rlen, input + rpos, rlen); | |
144 | } | |
145 | ||
146 | /* Ignore leading zeroes in S */ | |
147 | while (slen > 0 && input[spos] == 0) { | |
148 | slen--; | |
149 | spos++; | |
150 | } | |
151 | /* Copy S value */ | |
152 | if (slen > 32) { | |
153 | overflow = 1; | |
154 | } else { | |
155 | memcpy(tmpsig + 64 - slen, input + spos, slen); | |
156 | } | |
157 | ||
158 | if (!overflow) { | |
159 | overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); | |
160 | } | |
161 | if (overflow) { | |
162 | /* Overwrite the result again with a correctly-parsed but invalid | |
163 | signature if parsing failed. */ | |
164 | memset(tmpsig, 0, 64); | |
165 | secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); | |
166 | } | |
167 | return 1; | |
168 | } | |
d2e74c55 CF |
169 | |
170 | bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const { | |
171 | if (!IsValid()) | |
172 | return false; | |
3d02d0f6 PW |
173 | secp256k1_pubkey pubkey; |
174 | secp256k1_ecdsa_signature sig; | |
175 | if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) { | |
d2e74c55 | 176 | return false; |
3d02d0f6 PW |
177 | } |
178 | if (vchSig.size() == 0) { | |
d2e74c55 | 179 | return false; |
3d02d0f6 PW |
180 | } |
181 | if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) { | |
182 | return false; | |
183 | } | |
184 | /* libsecp256k1's ECDSA verification requires lower-S signatures, which have | |
185 | * not historically been enforced in Bitcoin, so normalize them first. */ | |
186 | secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig); | |
187 | return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey); | |
d2e74c55 CF |
188 | } |
189 | ||
190 | bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) { | |
191 | if (vchSig.size() != 65) | |
192 | return false; | |
193 | int recid = (vchSig[0] - 27) & 3; | |
194 | bool fComp = ((vchSig[0] - 27) & 4) != 0; | |
3d02d0f6 PW |
195 | secp256k1_pubkey pubkey; |
196 | secp256k1_ecdsa_recoverable_signature sig; | |
197 | if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) { | |
d2e74c55 | 198 | return false; |
3d02d0f6 PW |
199 | } |
200 | if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) { | |
201 | return false; | |
202 | } | |
203 | unsigned char pub[65]; | |
204 | size_t publen = 65; | |
205 | secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); | |
206 | Set(pub, pub + publen); | |
d2e74c55 CF |
207 | return true; |
208 | } | |
209 | ||
210 | bool CPubKey::IsFullyValid() const { | |
211 | if (!IsValid()) | |
212 | return false; | |
3d02d0f6 PW |
213 | secp256k1_pubkey pubkey; |
214 | return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size()); | |
d2e74c55 CF |
215 | } |
216 | ||
217 | bool CPubKey::Decompress() { | |
218 | if (!IsValid()) | |
219 | return false; | |
3d02d0f6 PW |
220 | secp256k1_pubkey pubkey; |
221 | if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) { | |
d2e74c55 | 222 | return false; |
3d02d0f6 PW |
223 | } |
224 | unsigned char pub[65]; | |
225 | size_t publen = 65; | |
226 | secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED); | |
227 | Set(pub, pub + publen); | |
d2e74c55 CF |
228 | return true; |
229 | } | |
230 | ||
a5748996 | 231 | bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const { |
d2e74c55 CF |
232 | assert(IsValid()); |
233 | assert((nChild >> 31) == 0); | |
50fa0797 | 234 | assert(size() == 33); |
d2e74c55 CF |
235 | unsigned char out[64]; |
236 | BIP32Hash(cc, nChild, *begin(), begin()+1, out); | |
a5748996 | 237 | memcpy(ccChild.begin(), out+32, 32); |
3d02d0f6 PW |
238 | secp256k1_pubkey pubkey; |
239 | if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) { | |
240 | return false; | |
241 | } | |
242 | if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) { | |
243 | return false; | |
244 | } | |
245 | unsigned char pub[33]; | |
246 | size_t publen = 33; | |
247 | secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); | |
248 | pubkeyChild.Set(pub, pub + publen); | |
249 | return true; | |
d2e74c55 CF |
250 | } |
251 | ||
252 | void CExtPubKey::Encode(unsigned char code[74]) const { | |
253 | code[0] = nDepth; | |
254 | memcpy(code+1, vchFingerprint, 4); | |
255 | code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; | |
256 | code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; | |
a5748996 | 257 | memcpy(code+9, chaincode.begin(), 32); |
d2e74c55 CF |
258 | assert(pubkey.size() == 33); |
259 | memcpy(code+41, pubkey.begin(), 33); | |
260 | } | |
261 | ||
262 | void CExtPubKey::Decode(const unsigned char code[74]) { | |
263 | nDepth = code[0]; | |
264 | memcpy(vchFingerprint, code+1, 4); | |
265 | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | |
a5748996 | 266 | memcpy(chaincode.begin(), code+9, 32); |
d2e74c55 CF |
267 | pubkey.Set(code+41, code+74); |
268 | } | |
269 | ||
270 | bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { | |
271 | out.nDepth = nDepth + 1; | |
272 | CKeyID id = pubkey.GetID(); | |
273 | memcpy(&out.vchFingerprint[0], &id, 4); | |
274 | out.nChild = nChild; | |
a5748996 | 275 | return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode); |
d2e74c55 | 276 | } |
3d02d0f6 PW |
277 | |
278 | /* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) { | |
279 | secp256k1_ecdsa_signature sig; | |
280 | if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) { | |
281 | return false; | |
282 | } | |
283 | return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig)); | |
284 | } | |
285 | ||
286 | /* static */ int ECCVerifyHandle::refcount = 0; | |
287 | ||
288 | ECCVerifyHandle::ECCVerifyHandle() | |
289 | { | |
290 | if (refcount == 0) { | |
291 | assert(secp256k1_context_verify == NULL); | |
292 | secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); | |
293 | assert(secp256k1_context_verify != NULL); | |
294 | } | |
295 | refcount++; | |
296 | } | |
297 | ||
298 | ECCVerifyHandle::~ECCVerifyHandle() | |
299 | { | |
300 | refcount--; | |
301 | if (refcount == 0) { | |
302 | assert(secp256k1_context_verify != NULL); | |
303 | secp256k1_context_destroy(secp256k1_context_verify); | |
304 | secp256k1_context_verify = NULL; | |
305 | } | |
306 | } |