]>
Commit | Line | Data |
---|---|---|
f914f1a7 | 1 | // Copyright (c) 2009-2014 The Bitcoin Core 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 | ||
36fa4a78 | 7 | #include "crypto/hmac_sha512.h" |
a53fd414 | 8 | #include "crypto/rfc6979_hmac_sha256.h" |
900078ae | 9 | #include "eccryptoverify.h" |
d2e74c55 | 10 | #include "pubkey.h" |
001a53d7 | 11 | #include "random.h" |
977cdade | 12 | |
fda3fed1 | 13 | #include <secp256k1.h> |
50f71cd5 | 14 | #include "ecwrapper.h" |
dfa23b94 | 15 | |
2b173d3b | 16 | //! anonymous namespace |
dfa23b94 PW |
17 | namespace { |
18 | ||
fda3fed1 PW |
19 | class CSecp256k1Init { |
20 | public: | |
21 | CSecp256k1Init() { | |
dffb8f81 | 22 | secp256k1_start(SECP256K1_START_SIGN); |
fda3fed1 PW |
23 | } |
24 | ~CSecp256k1Init() { | |
25 | secp256k1_stop(); | |
26 | } | |
27 | }; | |
28 | static CSecp256k1Init instance_of_csecp256k1; | |
29 | ||
e10dcf27 | 30 | } // anon namespace |
dfa23b94 PW |
31 | |
32 | bool CKey::Check(const unsigned char *vch) { | |
900078ae | 33 | return eccrypto::Check(vch); |
096e06db GA |
34 | } |
35 | ||
dfa23b94 PW |
36 | void CKey::MakeNewKey(bool fCompressedIn) { |
37 | do { | |
001a53d7 | 38 | GetRandBytes(vch, sizeof(vch)); |
dfa23b94 PW |
39 | } while (!Check(vch)); |
40 | fValid = true; | |
41 | fCompressed = fCompressedIn; | |
096e06db GA |
42 | } |
43 | ||
dfa23b94 | 44 | bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { |
dffb8f81 | 45 | if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) |
dfa23b94 | 46 | return false; |
dfa23b94 PW |
47 | fCompressed = fCompressedIn; |
48 | fValid = true; | |
49 | return true; | |
096e06db GA |
50 | } |
51 | ||
dfa23b94 PW |
52 | CPrivKey CKey::GetPrivKey() const { |
53 | assert(fValid); | |
fda3fed1 | 54 | CPrivKey privkey; |
e405aa48 | 55 | int privkeylen, ret; |
fda3fed1 | 56 | privkey.resize(279); |
e405aa48 | 57 | privkeylen = 279; |
dffb8f81 | 58 | ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); |
fda3fed1 PW |
59 | assert(ret); |
60 | privkey.resize(privkeylen); | |
dfa23b94 | 61 | return privkey; |
096e06db GA |
62 | } |
63 | ||
dfa23b94 PW |
64 | CPubKey CKey::GetPubKey() const { |
65 | assert(fValid); | |
bdaec6ab | 66 | CPubKey result; |
fda3fed1 | 67 | int clen = 65; |
dffb8f81 | 68 | int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed); |
bdaec6ab | 69 | assert((int)result.size() == clen); |
fda3fed1 | 70 | assert(ret); |
bdaec6ab CF |
71 | assert(result.IsValid()); |
72 | return result; | |
096e06db GA |
73 | } |
74 | ||
a53fd414 | 75 | bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const { |
dfa23b94 | 76 | if (!fValid) |
096e06db | 77 | return false; |
fda3fed1 | 78 | vchSig.resize(72); |
a53fd414 | 79 | RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32); |
fda3fed1 | 80 | do { |
a53fd414 PW |
81 | uint256 nonce; |
82 | prng.Generate((unsigned char*)&nonce, 32); | |
83 | nonce += test_case; | |
84 | int nSigLen = 72; | |
830ee48b | 85 | int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce); |
a53fd414 | 86 | nonce = 0; |
4cdaa95a PW |
87 | if (ret) { |
88 | vchSig.resize(nSigLen); | |
a53fd414 | 89 | return true; |
4cdaa95a | 90 | } |
fda3fed1 | 91 | } while(true); |
096e06db GA |
92 | } |
93 | ||
d0c41a73 PW |
94 | bool CKey::VerifyPubKey(const CPubKey& pubkey) const { |
95 | if (pubkey.IsCompressed() != fCompressed) { | |
96 | return false; | |
97 | } | |
98 | unsigned char rnd[8]; | |
99 | std::string str = "Bitcoin key verification\n"; | |
100 | GetRandBytes(rnd, sizeof(rnd)); | |
101 | uint256 hash; | |
102 | CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash); | |
103 | std::vector<unsigned char> vchSig; | |
104 | Sign(hash, vchSig); | |
105 | return pubkey.Verify(hash, vchSig); | |
106 | } | |
107 | ||
dfa23b94 PW |
108 | bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const { |
109 | if (!fValid) | |
096e06db | 110 | return false; |
dfa23b94 PW |
111 | vchSig.resize(65); |
112 | int rec = -1; | |
a53fd414 | 113 | RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32); |
fda3fed1 | 114 | do { |
a53fd414 PW |
115 | uint256 nonce; |
116 | prng.Generate((unsigned char*)&nonce, 32); | |
830ee48b | 117 | int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, &vchSig[1], begin(), (unsigned char*)&nonce, &rec); |
a53fd414 PW |
118 | nonce = 0; |
119 | if (ret) | |
fda3fed1 PW |
120 | break; |
121 | } while(true); | |
dfa23b94 PW |
122 | assert(rec != -1); |
123 | vchSig[0] = 27 + rec + (fCompressed ? 4 : 0); | |
124 | return true; | |
125 | } | |
096e06db | 126 | |
6e51b3bd | 127 | bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { |
dffb8f81 | 128 | if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) |
6e51b3bd | 129 | return false; |
6e51b3bd | 130 | fCompressed = vchPubKey.IsCompressed(); |
131 | fValid = true; | |
fda3fed1 | 132 | |
a42eef6f | 133 | if (fSkipCheck) |
134 | return true; | |
fda3fed1 | 135 | |
d0c41a73 | 136 | return VerifyPubKey(vchPubKey); |
6e51b3bd | 137 | } |
138 | ||
eb2c9990 PW |
139 | bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { |
140 | assert(IsValid()); | |
141 | assert(IsCompressed()); | |
142 | unsigned char out[64]; | |
143 | LockObject(out); | |
144 | if ((nChild >> 31) == 0) { | |
145 | CPubKey pubkey = GetPubKey(); | |
146 | assert(pubkey.begin() + 33 == pubkey.end()); | |
147 | BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out); | |
148 | } else { | |
149 | assert(begin() + 32 == end()); | |
150 | BIP32Hash(cc, nChild, 0, begin(), out); | |
151 | } | |
152 | memcpy(ccChild, out+32, 32); | |
fda3fed1 | 153 | memcpy((unsigned char*)keyChild.begin(), begin(), 32); |
dffb8f81 | 154 | bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out); |
eb2c9990 PW |
155 | UnlockObject(out); |
156 | keyChild.fCompressed = true; | |
157 | keyChild.fValid = ret; | |
158 | return ret; | |
159 | } | |
160 | ||
eb2c9990 PW |
161 | bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const { |
162 | out.nDepth = nDepth + 1; | |
163 | CKeyID id = key.GetPubKey().GetID(); | |
164 | memcpy(&out.vchFingerprint[0], &id, 4); | |
165 | out.nChild = nChild; | |
166 | return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode); | |
167 | } | |
168 | ||
169 | void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { | |
977cdade | 170 | static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; |
eb2c9990 PW |
171 | unsigned char out[64]; |
172 | LockObject(out); | |
977cdade | 173 | CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out); |
eb2c9990 PW |
174 | key.Set(&out[0], &out[32], true); |
175 | memcpy(vchChainCode, &out[32], 32); | |
176 | UnlockObject(out); | |
177 | nDepth = 0; | |
178 | nChild = 0; | |
179 | memset(vchFingerprint, 0, sizeof(vchFingerprint)); | |
180 | } | |
181 | ||
182 | CExtPubKey CExtKey::Neuter() const { | |
183 | CExtPubKey ret; | |
184 | ret.nDepth = nDepth; | |
185 | memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4); | |
186 | ret.nChild = nChild; | |
187 | ret.pubkey = key.GetPubKey(); | |
188 | memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32); | |
189 | return ret; | |
190 | } | |
191 | ||
192 | void CExtKey::Encode(unsigned char code[74]) const { | |
193 | code[0] = nDepth; | |
194 | memcpy(code+1, vchFingerprint, 4); | |
195 | code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; | |
196 | code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; | |
197 | memcpy(code+9, vchChainCode, 32); | |
198 | code[41] = 0; | |
199 | assert(key.size() == 32); | |
200 | memcpy(code+42, key.begin(), 32); | |
201 | } | |
202 | ||
203 | void CExtKey::Decode(const unsigned char code[74]) { | |
204 | nDepth = code[0]; | |
205 | memcpy(vchFingerprint, code+1, 4); | |
206 | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | |
207 | memcpy(vchChainCode, code+9, 32); | |
208 | key.Set(code+42, code+74, true); | |
209 | } | |
210 | ||
4a09e1df | 211 | bool ECC_InitSanityCheck() { |
f321d6bf PW |
212 | #if !defined(USE_SECP256K1) |
213 | if (!CECKey::SanityCheck()) { | |
214 | return false; | |
215 | } | |
216 | #endif | |
217 | CKey key; | |
218 | key.MakeNewKey(true); | |
219 | CPubKey pubkey = key.GetPubKey(); | |
220 | return key.VerifyPubKey(pubkey); | |
4a09e1df | 221 | } |