]>
Commit | Line | Data |
---|---|---|
001a53d7 | 1 | // Copyright (c) 2009-2014 The Bitcoin developers |
ffd8edda | 2 | // Distributed under the MIT software license, see the accompanying |
3a25a2b9 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
93db3fce | 4 | |
51ed9ec9 BD |
5 | #include "key.h" |
6 | ||
13b5dfef | 7 | #include "crypto/sha2.h" |
001a53d7 | 8 | #include "random.h" |
977cdade | 9 | |
fda3fed1 PW |
10 | #ifdef USE_SECP256K1 |
11 | #include <secp256k1.h> | |
12 | #else | |
50f71cd5 | 13 | #include "ecwrapper.h" |
fda3fed1 | 14 | #endif |
dfa23b94 | 15 | |
ffd8edda | 16 | //! anonymous namespace with local implementation code (OpenSSL interaction) |
dfa23b94 PW |
17 | namespace { |
18 | ||
fda3fed1 PW |
19 | #ifdef USE_SECP256K1 |
20 | #include <secp256k1.h> | |
21 | class CSecp256k1Init { | |
22 | public: | |
23 | CSecp256k1Init() { | |
24 | secp256k1_start(); | |
25 | } | |
26 | ~CSecp256k1Init() { | |
27 | secp256k1_stop(); | |
28 | } | |
29 | }; | |
30 | static CSecp256k1Init instance_of_csecp256k1; | |
31 | ||
fda3fed1 PW |
32 | #endif |
33 | ||
6fd7ef2b PW |
34 | int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { |
35 | while (c1len > c2len) { | |
36 | if (*c1) | |
37 | return 1; | |
38 | c1++; | |
39 | c1len--; | |
40 | } | |
41 | while (c2len > c1len) { | |
42 | if (*c2) | |
43 | return -1; | |
44 | c2++; | |
45 | c2len--; | |
46 | } | |
47 | while (c1len > 0) { | |
48 | if (*c1 > *c2) | |
49 | return 1; | |
50 | if (*c2 > *c1) | |
51 | return -1; | |
52 | c1++; | |
53 | c2++; | |
54 | c1len--; | |
55 | } | |
56 | return 0; | |
57 | } | |
58 | ||
ffd8edda | 59 | /** Order of secp256k1's generator minus 1. */ |
6fd7ef2b PW |
60 | const unsigned char vchMaxModOrder[32] = { |
61 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
62 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, | |
63 | 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, | |
64 | 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 | |
65 | }; | |
66 | ||
ffd8edda | 67 | /** Half of the order of secp256k1's generator minus 1. */ |
6fd7ef2b PW |
68 | const unsigned char vchMaxModHalfOrder[32] = { |
69 | 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
70 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
71 | 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D, | |
72 | 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 | |
73 | }; | |
74 | ||
c0f5d4ab | 75 | const unsigned char vchZero[1] = {0}; |
6fd7ef2b | 76 | |
e10dcf27 | 77 | } // anon namespace |
dfa23b94 PW |
78 | |
79 | bool CKey::Check(const unsigned char *vch) { | |
6fd7ef2b PW |
80 | return CompareBigEndian(vch, 32, vchZero, 0) > 0 && |
81 | CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0; | |
82 | } | |
83 | ||
84 | bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) { | |
85 | return CompareBigEndian(vch, len, vchZero, 0) > 0 && | |
86 | CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0; | |
096e06db GA |
87 | } |
88 | ||
dfa23b94 PW |
89 | void CKey::MakeNewKey(bool fCompressedIn) { |
90 | do { | |
001a53d7 | 91 | GetRandBytes(vch, sizeof(vch)); |
dfa23b94 PW |
92 | } while (!Check(vch)); |
93 | fValid = true; | |
94 | fCompressed = fCompressedIn; | |
096e06db GA |
95 | } |
96 | ||
dfa23b94 | 97 | bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { |
fda3fed1 PW |
98 | #ifdef USE_SECP256K1 |
99 | if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) | |
100 | return false; | |
101 | #else | |
dfa23b94 | 102 | CECKey key; |
e405aa48 | 103 | if (!key.SetPrivKey(&privkey[0], privkey.size())) |
dfa23b94 PW |
104 | return false; |
105 | key.GetSecretBytes(vch); | |
fda3fed1 | 106 | #endif |
dfa23b94 PW |
107 | fCompressed = fCompressedIn; |
108 | fValid = true; | |
109 | return true; | |
096e06db GA |
110 | } |
111 | ||
dfa23b94 PW |
112 | CPrivKey CKey::GetPrivKey() const { |
113 | assert(fValid); | |
fda3fed1 | 114 | CPrivKey privkey; |
e405aa48 | 115 | int privkeylen, ret; |
fda3fed1 PW |
116 | #ifdef USE_SECP256K1 |
117 | privkey.resize(279); | |
e405aa48 CF |
118 | privkeylen = 279; |
119 | ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); | |
fda3fed1 PW |
120 | assert(ret); |
121 | privkey.resize(privkeylen); | |
122 | #else | |
dfa23b94 PW |
123 | CECKey key; |
124 | key.SetSecretBytes(vch); | |
e405aa48 CF |
125 | privkeylen = key.GetPrivKeySize(fCompressed); |
126 | assert(privkeylen); | |
127 | privkey.resize(privkeylen); | |
128 | ret = key.GetPrivKey(&privkey[0], fCompressed); | |
129 | assert(ret == (int)privkey.size()); | |
fda3fed1 | 130 | #endif |
dfa23b94 | 131 | return privkey; |
096e06db GA |
132 | } |
133 | ||
dfa23b94 PW |
134 | CPubKey CKey::GetPubKey() const { |
135 | assert(fValid); | |
bdaec6ab | 136 | CPubKey result; |
fda3fed1 PW |
137 | #ifdef USE_SECP256K1 |
138 | int clen = 65; | |
bdaec6ab CF |
139 | int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed); |
140 | assert((int)result.size() == clen); | |
fda3fed1 | 141 | assert(ret); |
fda3fed1 | 142 | #else |
bdaec6ab | 143 | std::vector<unsigned char> pubkey; |
dfa23b94 PW |
144 | CECKey key; |
145 | key.SetSecretBytes(vch); | |
dfa23b94 | 146 | key.GetPubKey(pubkey, fCompressed); |
bdaec6ab | 147 | result.Set(pubkey.begin(), pubkey.end()); |
fda3fed1 | 148 | #endif |
bdaec6ab CF |
149 | assert(result.IsValid()); |
150 | return result; | |
096e06db GA |
151 | } |
152 | ||
8138cbea | 153 | bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool lowS) const { |
dfa23b94 | 154 | if (!fValid) |
096e06db | 155 | return false; |
fda3fed1 PW |
156 | #ifdef USE_SECP256K1 |
157 | vchSig.resize(72); | |
158 | int nSigLen = 72; | |
159 | CKey nonce; | |
160 | do { | |
161 | nonce.MakeNewKey(true); | |
162 | if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin())) | |
163 | break; | |
164 | } while(true); | |
165 | vchSig.resize(nSigLen); | |
166 | return true; | |
167 | #else | |
dfa23b94 PW |
168 | CECKey key; |
169 | key.SetSecretBytes(vch); | |
8138cbea | 170 | return key.Sign(hash, vchSig, lowS); |
fda3fed1 | 171 | #endif |
096e06db GA |
172 | } |
173 | ||
dfa23b94 PW |
174 | bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const { |
175 | if (!fValid) | |
096e06db | 176 | return false; |
dfa23b94 PW |
177 | vchSig.resize(65); |
178 | int rec = -1; | |
fda3fed1 PW |
179 | #ifdef USE_SECP256K1 |
180 | CKey nonce; | |
181 | do { | |
182 | nonce.MakeNewKey(true); | |
183 | if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec)) | |
184 | break; | |
185 | } while(true); | |
186 | #else | |
187 | CECKey key; | |
188 | key.SetSecretBytes(vch); | |
dfa23b94 PW |
189 | if (!key.SignCompact(hash, &vchSig[1], rec)) |
190 | return false; | |
fda3fed1 | 191 | #endif |
dfa23b94 PW |
192 | assert(rec != -1); |
193 | vchSig[0] = 27 + rec + (fCompressed ? 4 : 0); | |
194 | return true; | |
195 | } | |
096e06db | 196 | |
6e51b3bd | 197 | bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { |
fda3fed1 PW |
198 | #ifdef USE_SECP256K1 |
199 | if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) | |
200 | return false; | |
201 | #else | |
6e51b3bd | 202 | CECKey key; |
e405aa48 | 203 | if (!key.SetPrivKey(&privkey[0], privkey.size(), fSkipCheck)) |
6e51b3bd | 204 | return false; |
6e51b3bd | 205 | key.GetSecretBytes(vch); |
fda3fed1 | 206 | #endif |
6e51b3bd | 207 | fCompressed = vchPubKey.IsCompressed(); |
208 | fValid = true; | |
fda3fed1 | 209 | |
a42eef6f | 210 | if (fSkipCheck) |
211 | return true; | |
fda3fed1 | 212 | |
a42eef6f | 213 | if (GetPubKey() != vchPubKey) |
214 | return false; | |
fda3fed1 | 215 | |
6e51b3bd | 216 | return true; |
217 | } | |
218 | ||
dfa23b94 PW |
219 | bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const { |
220 | if (!IsValid()) | |
221 | return false; | |
fda3fed1 PW |
222 | #ifdef USE_SECP256K1 |
223 | if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1) | |
224 | return false; | |
225 | #else | |
dfa23b94 | 226 | CECKey key; |
bdaec6ab | 227 | if (!key.SetPubKey(begin(), size())) |
dfa23b94 PW |
228 | return false; |
229 | if (!key.Verify(hash, vchSig)) | |
230 | return false; | |
fda3fed1 | 231 | #endif |
dfa23b94 | 232 | return true; |
096e06db GA |
233 | } |
234 | ||
dfa23b94 | 235 | bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) { |
096e06db GA |
236 | if (vchSig.size() != 65) |
237 | return false; | |
fda3fed1 | 238 | int recid = (vchSig[0] - 27) & 3; |
8d657a65 | 239 | bool fComp = ((vchSig[0] - 27) & 4) != 0; |
fda3fed1 PW |
240 | #ifdef USE_SECP256K1 |
241 | int pubkeylen = 65; | |
242 | if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid)) | |
243 | return false; | |
244 | assert((int)size() == pubkeylen); | |
245 | #else | |
dfa23b94 | 246 | CECKey key; |
fda3fed1 | 247 | if (!key.Recover(hash, &vchSig[1], recid)) |
096e06db | 248 | return false; |
bdaec6ab CF |
249 | std::vector<unsigned char> pubkey; |
250 | key.GetPubKey(pubkey, fComp); | |
251 | Set(pubkey.begin(), pubkey.end()); | |
fda3fed1 | 252 | #endif |
dfa23b94 | 253 | return true; |
096e06db GA |
254 | } |
255 | ||
dfa23b94 PW |
256 | bool CPubKey::IsFullyValid() const { |
257 | if (!IsValid()) | |
096e06db | 258 | return false; |
fda3fed1 PW |
259 | #ifdef USE_SECP256K1 |
260 | if (!secp256k1_ecdsa_pubkey_verify(begin(), size())) | |
261 | return false; | |
262 | #else | |
dfa23b94 | 263 | CECKey key; |
bdaec6ab | 264 | if (!key.SetPubKey(begin(), size())) |
096e06db | 265 | return false; |
fda3fed1 | 266 | #endif |
096e06db GA |
267 | return true; |
268 | } | |
269 | ||
dfa23b94 PW |
270 | bool CPubKey::Decompress() { |
271 | if (!IsValid()) | |
096e06db | 272 | return false; |
fda3fed1 PW |
273 | #ifdef USE_SECP256K1 |
274 | int clen = size(); | |
275 | int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen); | |
276 | assert(ret); | |
277 | assert(clen == (int)size()); | |
278 | #else | |
dfa23b94 | 279 | CECKey key; |
bdaec6ab | 280 | if (!key.SetPubKey(begin(), size())) |
eed1785f | 281 | return false; |
bdaec6ab CF |
282 | std::vector<unsigned char> pubkey; |
283 | key.GetPubKey(pubkey, false); | |
284 | Set(pubkey.begin(), pubkey.end()); | |
fda3fed1 | 285 | #endif |
dfa23b94 | 286 | return true; |
096e06db | 287 | } |
eb2c9990 PW |
288 | |
289 | void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]) { | |
290 | unsigned char num[4]; | |
291 | num[0] = (nChild >> 24) & 0xFF; | |
292 | num[1] = (nChild >> 16) & 0xFF; | |
293 | num[2] = (nChild >> 8) & 0xFF; | |
294 | num[3] = (nChild >> 0) & 0xFF; | |
977cdade PW |
295 | CHMAC_SHA512(chainCode, 32).Write(&header, 1) |
296 | .Write(data, 32) | |
297 | .Write(num, 4) | |
298 | .Finalize(output); | |
eb2c9990 PW |
299 | } |
300 | ||
301 | bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { | |
302 | assert(IsValid()); | |
303 | assert(IsCompressed()); | |
304 | unsigned char out[64]; | |
305 | LockObject(out); | |
306 | if ((nChild >> 31) == 0) { | |
307 | CPubKey pubkey = GetPubKey(); | |
308 | assert(pubkey.begin() + 33 == pubkey.end()); | |
309 | BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out); | |
310 | } else { | |
311 | assert(begin() + 32 == end()); | |
312 | BIP32Hash(cc, nChild, 0, begin(), out); | |
313 | } | |
314 | memcpy(ccChild, out+32, 32); | |
fda3fed1 PW |
315 | #ifdef USE_SECP256K1 |
316 | memcpy((unsigned char*)keyChild.begin(), begin(), 32); | |
317 | bool ret = secp256k1_ecdsa_privkey_tweak_add((unsigned char*)keyChild.begin(), out); | |
318 | #else | |
eb2c9990 | 319 | bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out); |
fda3fed1 | 320 | #endif |
eb2c9990 PW |
321 | UnlockObject(out); |
322 | keyChild.fCompressed = true; | |
323 | keyChild.fValid = ret; | |
324 | return ret; | |
325 | } | |
326 | ||
327 | bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { | |
328 | assert(IsValid()); | |
329 | assert((nChild >> 31) == 0); | |
330 | assert(begin() + 33 == end()); | |
331 | unsigned char out[64]; | |
332 | BIP32Hash(cc, nChild, *begin(), begin()+1, out); | |
333 | memcpy(ccChild, out+32, 32); | |
fda3fed1 PW |
334 | #ifdef USE_SECP256K1 |
335 | pubkeyChild = *this; | |
336 | bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out); | |
337 | #else | |
eb2c9990 | 338 | CECKey key; |
bdaec6ab | 339 | bool ret = key.SetPubKey(begin(), size()); |
eb2c9990 | 340 | ret &= key.TweakPublic(out); |
bdaec6ab CF |
341 | std::vector<unsigned char> pubkey; |
342 | key.GetPubKey(pubkey, true); | |
343 | pubkeyChild.Set(pubkey.begin(), pubkey.end()); | |
fda3fed1 | 344 | #endif |
eb2c9990 PW |
345 | return ret; |
346 | } | |
347 | ||
348 | bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const { | |
349 | out.nDepth = nDepth + 1; | |
350 | CKeyID id = key.GetPubKey().GetID(); | |
351 | memcpy(&out.vchFingerprint[0], &id, 4); | |
352 | out.nChild = nChild; | |
353 | return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode); | |
354 | } | |
355 | ||
356 | void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { | |
977cdade | 357 | static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; |
eb2c9990 PW |
358 | unsigned char out[64]; |
359 | LockObject(out); | |
977cdade | 360 | CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out); |
eb2c9990 PW |
361 | key.Set(&out[0], &out[32], true); |
362 | memcpy(vchChainCode, &out[32], 32); | |
363 | UnlockObject(out); | |
364 | nDepth = 0; | |
365 | nChild = 0; | |
366 | memset(vchFingerprint, 0, sizeof(vchFingerprint)); | |
367 | } | |
368 | ||
369 | CExtPubKey CExtKey::Neuter() const { | |
370 | CExtPubKey ret; | |
371 | ret.nDepth = nDepth; | |
372 | memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4); | |
373 | ret.nChild = nChild; | |
374 | ret.pubkey = key.GetPubKey(); | |
375 | memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32); | |
376 | return ret; | |
377 | } | |
378 | ||
379 | void CExtKey::Encode(unsigned char code[74]) const { | |
380 | code[0] = nDepth; | |
381 | memcpy(code+1, vchFingerprint, 4); | |
382 | code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; | |
383 | code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; | |
384 | memcpy(code+9, vchChainCode, 32); | |
385 | code[41] = 0; | |
386 | assert(key.size() == 32); | |
387 | memcpy(code+42, key.begin(), 32); | |
388 | } | |
389 | ||
390 | void CExtKey::Decode(const unsigned char code[74]) { | |
391 | nDepth = code[0]; | |
392 | memcpy(vchFingerprint, code+1, 4); | |
393 | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | |
394 | memcpy(vchChainCode, code+9, 32); | |
395 | key.Set(code+42, code+74, true); | |
396 | } | |
397 | ||
398 | void CExtPubKey::Encode(unsigned char code[74]) const { | |
399 | code[0] = nDepth; | |
400 | memcpy(code+1, vchFingerprint, 4); | |
401 | code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; | |
402 | code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; | |
403 | memcpy(code+9, vchChainCode, 32); | |
404 | assert(pubkey.size() == 33); | |
405 | memcpy(code+41, pubkey.begin(), 33); | |
406 | } | |
407 | ||
408 | void CExtPubKey::Decode(const unsigned char code[74]) { | |
409 | nDepth = code[0]; | |
410 | memcpy(vchFingerprint, code+1, 4); | |
411 | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | |
412 | memcpy(vchChainCode, code+9, 32); | |
413 | pubkey.Set(code+41, code+74); | |
414 | } | |
415 | ||
416 | bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { | |
417 | out.nDepth = nDepth + 1; | |
418 | CKeyID id = pubkey.GetID(); | |
419 | memcpy(&out.vchFingerprint[0], &id, 4); | |
420 | out.nChild = nChild; | |
421 | return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode); | |
422 | } | |
4a09e1df AP |
423 | |
424 | bool ECC_InitSanityCheck() { | |
fda3fed1 PW |
425 | #ifdef USE_SECP256K1 |
426 | return true; | |
427 | #else | |
50f71cd5 | 428 | return CECKey::SanityCheck(); |
fda3fed1 | 429 | #endif |
4a09e1df | 430 | } |