1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "pubkey.h"
#include "crypto/sha2.h"
#include "eccryptoverify.h"
#ifdef USE_SECP256K1
#include <secp256k1.h>
#else
#include "ecwrapper.h"
#endif
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1)
return false;
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
if (!key.Verify(hash, vchSig))
return false;
#endif
return true;
}
bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
if (vchSig.size() != 65)
return false;
int recid = (vchSig[0] - 27) & 3;
bool fComp = ((vchSig[0] - 27) & 4) != 0;
#ifdef USE_SECP256K1
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid))
return false;
assert((int)size() == pubkeylen);
#else
CECKey key;
if (!key.Recover(hash, &vchSig[1], recid))
return false;
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, fComp);
Set(pubkey.begin(), pubkey.end());
#endif
return true;
}
bool CPubKey::IsFullyValid() const {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
if (!secp256k1_ecdsa_pubkey_verify(begin(), size()))
return false;
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
#endif
return true;
}
bool CPubKey::Decompress() {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
int clen = size();
int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen);
assert(ret);
assert(clen == (int)size());
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, false);
Set(pubkey.begin(), pubkey.end());
#endif
return true;
}
bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
assert(IsValid());
assert((nChild >> 31) == 0);
assert(begin() + 33 == end());
unsigned char out[64];
BIP32Hash(cc, nChild, *begin(), begin()+1, out);
memcpy(ccChild, out+32, 32);
#ifdef USE_SECP256K1
pubkeyChild = *this;
bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out);
#else
CECKey key;
bool ret = key.SetPubKey(begin(), size());
ret &= key.TweakPublic(out);
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, true);
pubkeyChild.Set(pubkey.begin(), pubkey.end());
#endif
return ret;
}
void CExtPubKey::Encode(unsigned char code[74]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
memcpy(code+9, vchChainCode, 32);
assert(pubkey.size() == 33);
memcpy(code+41, pubkey.begin(), 33);
}
void CExtPubKey::Decode(const unsigned char code[74]) {
nDepth = code[0];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(vchChainCode, code+9, 32);
pubkey.Set(code+41, code+74);
}
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
out.nDepth = nDepth + 1;
CKeyID id = pubkey.GetID();
memcpy(&out.vchFingerprint[0], &id, 4);
out.nChild = nChild;
return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
}
|