]> Git Repo - VerusCoin.git/blame - src/key.cpp
Update comments in key to be doxygen compatible
[VerusCoin.git] / src / key.cpp
CommitLineData
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
17namespace {
18
fda3fed1
PW
19#ifdef USE_SECP256K1
20#include <secp256k1.h>
21class CSecp256k1Init {
22public:
23 CSecp256k1Init() {
24 secp256k1_start();
25 }
26 ~CSecp256k1Init() {
27 secp256k1_stop();
28 }
29};
30static CSecp256k1Init instance_of_csecp256k1;
31
fda3fed1
PW
32#endif
33
6fd7ef2b
PW
34int 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
60const 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
68const 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 75const unsigned char vchZero[1] = {0};
6fd7ef2b 76
e10dcf27 77} // anon namespace
dfa23b94
PW
78
79bool 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
84bool 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
89void 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 97bool 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
112CPrivKey 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
134CPubKey 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 153bool 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
174bool 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 197bool 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
219bool 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 235bool 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
256bool 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
270bool 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
289void 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
301bool 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
327bool 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
348bool 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
356void 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
369CExtPubKey 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
379void 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
390void 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
398void 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
408void 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
416bool 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
424bool ECC_InitSanityCheck() {
fda3fed1
PW
425#ifdef USE_SECP256K1
426 return true;
427#else
50f71cd5 428 return CECKey::SanityCheck();
fda3fed1 429#endif
4a09e1df 430}
This page took 0.207764 seconds and 4 git commands to generate.