PRCYCoin  2.0.0.7rc1
P2P Digital Currency
key.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2014 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "key.h"
6 
7 #include "crypto/hmac_sha512.h"
9 #include "eccryptoverify.h"
10 #include "pubkey.h"
11 #include "random.h"
12 
13 #include "ecwrapper.h"
14 #include <secp256k1.h>
15 
17 namespace
18 {
19 class CSecp256k1Init
20 {
21 public:
22  CSecp256k1Init()
23  {
25  }
26  ~CSecp256k1Init()
27  {
29  }
30 };
31 static CSecp256k1Init instance_of_csecp256k1;
32 
33 } // anon namespace
34 
35 bool CKey::Check(const unsigned char* vch)
36 {
37  return eccrypto::Check(vch);
38 }
39 
40 void CKey::MakeNewKey(bool fCompressedIn)
41 {
42  do {
43  GetStrongRandBytes(vch, sizeof(vch));
44  } while (!Check(vch));
45  fValid = true;
46  fCompressed = fCompressedIn;
47 }
48 
49 bool CKey::SetPrivKey(const CPrivKey& privkey, bool fCompressedIn)
50 {
51  if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
52  return false;
53  fCompressed = fCompressedIn;
54  fValid = true;
55  return true;
56 }
57 
59 {
60  void* key = &vch;
61  uint256* key_256 = (uint256*)key;
62 
63  return *key_256;
64 }
65 
67 {
68  assert(fValid);
69  CPrivKey privkey;
70  int privkeylen, ret;
71  privkey.resize(279);
72  privkeylen = 279;
73  ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
74  assert(ret);
75  privkey.resize(privkeylen);
76  return privkey;
77 }
78 
80 {
81  assert(fValid);
82  CPubKey result;
83  int clen = 65;
84  int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
85  assert((int)result.size() == clen);
86  assert(ret);
87  assert(result.IsValid());
88  return result;
89 }
90 
91 bool CKey::Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const
92 {
93  if (!fValid)
94  return false;
95  vchSig.resize(72);
96  RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
97  do {
98  uint256 nonce;
99  prng.Generate((unsigned char*)&nonce, 32);
100  nonce += test_case;
101  int nSigLen = 72;
102  int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce);
103  nonce = 0;
104  if (ret) {
105  vchSig.resize(nSigLen);
106  return true;
107  }
108  } while (true);
109 }
110 
111 bool CKey::VerifyPubKey(const CPubKey& pubkey) const
112 {
113  if (pubkey.IsCompressed() != fCompressed) {
114  return false;
115  }
116  unsigned char rnd[8];
117  std::string str = "Bitcoin key verification\n";
118  GetRandBytes(rnd, sizeof(rnd));
119  uint256 hash;
120  CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash);
121  std::vector<unsigned char> vchSig;
122  Sign(hash, vchSig);
123  return pubkey.Verify(hash, vchSig);
124 }
125 
126 bool CKey::SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const
127 {
128  if (!fValid)
129  return false;
130  vchSig.resize(65);
131  int rec = -1;
132  RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
133  do {
134  uint256 nonce;
135  prng.Generate((unsigned char*)&nonce, 32);
136  int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), (unsigned char*)&nonce, &rec);
137  nonce = 0;
138  if (ret)
139  break;
140  } while (true);
141  assert(rec != -1);
142  vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
143  return true;
144 }
145 
146 bool CKey::Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck = false)
147 {
148  if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
149  return false;
150  fCompressed = vchPubKey.IsCompressed();
151  fValid = true;
152 
153  if (fSkipCheck)
154  return true;
155 
156  return VerifyPubKey(vchPubKey);
157 }
158 
159 bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const
160 {
161  assert(IsValid());
162  assert(IsCompressed());
163  unsigned char out[64];
164  LockObject(out);
165  if ((nChild >> 31) == 0) {
166  CPubKey pubkey = GetPubKey();
167  assert(pubkey.begin() + 33 == pubkey.end());
168  BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin() + 1, out);
169  } else {
170  assert(begin() + 32 == end());
171  BIP32Hash(cc, nChild, 0, begin(), out);
172  }
173  memcpy(ccChild, out + 32, 32);
174  memcpy((unsigned char*)keyChild.begin(), begin(), 32);
175  bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
176  UnlockObject(out);
177  keyChild.fCompressed = true;
178  keyChild.fValid = ret;
179  return ret;
180 }
181 
182 bool CExtKey::Derive(CExtKey& out, unsigned int nChild) const
183 {
184  out.nDepth = nDepth + 1;
185  CKeyID id = key.GetPubKey().GetID();
186  memcpy(&out.vchFingerprint[0], &id, 4);
187  out.nChild = nChild;
188  return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode);
189 }
190 
191 void CExtKey::SetMaster(const unsigned char* seed, unsigned int nSeedLen)
192 {
193  static const unsigned char hashkey[] = {'p', 'r', 'c', 'y', 'c', 'o', 'i', 'n', ' ', 's', 'e', 'e', 'd'};
194  unsigned char out[64];
195  LockObject(out);
196  CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
197  key.Set(&out[0], &out[32], true);
198  memcpy(vchChainCode, &out[32], 32);
199  UnlockObject(out);
200  nDepth = 0;
201  nChild = 0;
202  memset(vchFingerprint, 0, sizeof(vchFingerprint));
203 }
204 
206 {
207  CExtPubKey ret;
208  ret.nDepth = nDepth;
209  memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4);
210  ret.nChild = nChild;
211  ret.pubkey = key.GetPubKey();
212  memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32);
213  return ret;
214 }
215 
216 void CExtKey::Encode(unsigned char code[74]) const
217 {
218  code[0] = nDepth;
219  memcpy(code + 1, vchFingerprint, 4);
220  code[5] = (nChild >> 24) & 0xFF;
221  code[6] = (nChild >> 16) & 0xFF;
222  code[7] = (nChild >> 8) & 0xFF;
223  code[8] = (nChild >> 0) & 0xFF;
224  memcpy(code + 9, vchChainCode, 32);
225  code[41] = 0;
226  assert(key.size() == 32);
227  memcpy(code + 42, key.begin(), 32);
228 }
229 
230 void CExtKey::Decode(const unsigned char code[74])
231 {
232  nDepth = code[0];
233  memcpy(vchFingerprint, code + 1, 4);
234  nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
235  memcpy(vchChainCode, code + 9, 32);
236  key.Set(code + 42, code + 74, true);
237 }
238 
240 {
241 #if !defined(USE_SECP256K1)
242  if (!CECKey::SanityCheck()) {
243  return false;
244  }
245 #endif
246  CKey key;
247  key.MakeNewKey(true);
248  CPubKey pubkey = key.GetPubKey();
249  return key.VerifyPubKey(pubkey);
250 }
CKey::IsCompressed
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:107
UnlockObject
void UnlockObject(const T &t)
Definition: allocators.h:174
secp256k1_start
void secp256k1_start(unsigned int flags)
Initialize the library.
Definition: secp256k1.c:21
CHash256::Finalize
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: hash.h:41
CKey::MakeNewKey
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:40
ecwrapper.h
CKey::SetPrivKey
bool SetPrivKey(const CPrivKey &vchPrivKey, bool fCompressed)
Initialize from a CPrivKey (serialized OpenSSL private key data).
Definition: key.cpp:49
CExtKey::Derive
bool Derive(CExtKey &out, unsigned int nChild) const
Definition: key.cpp:182
CKey::GetPrivKey
CPrivKey GetPrivKey() const
Convert the private key to a CPrivKey (serialized OpenSSL private key data).
Definition: key.cpp:66
CExtKey::vchFingerprint
unsigned char vchFingerprint[4]
Definition: key.h:163
CKey::Set
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:83
CKey::Derive
bool Derive(CKey &keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const
Derive BIP32 child key.
Definition: key.cpp:159
CPrivKey
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
secp256k1: const unsigned int PRIVATE_KEY_SIZE = 279; const unsigned int PUBLIC_KEY_SIZE = 65; const ...
Definition: key.h:20
ECC_InitSanityCheck
bool ECC_InitSanityCheck()
Check that required EC support is available at runtime.
Definition: key.cpp:239
CKey::fCompressed
bool fCompressed
Whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:47
memcpy
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:15
RFC6979_HMAC_SHA256::Generate
void Generate(unsigned char *output, size_t outputlen)
Generate a byte array.
Definition: rfc6979_hmac_sha256.cpp:31
SECP256K1_START_VERIFY
#define SECP256K1_START_VERIFY
Flags to pass to secp256k1_start.
Definition: secp256k1.h:45
eccrypto::Check
bool Check(const unsigned char *vch)
Definition: eccryptoverify.cpp:55
hmac_sha512.h
eccryptoverify.h
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
CExtPubKey::nDepth
unsigned char nDepth
Definition: pubkey.h:206
pubkey.h
rfc6979_hmac_sha256.h
CExtKey::nDepth
unsigned char nDepth
Definition: key.h:162
CKey::end
const unsigned char * end() const
Definition: key.h:101
CHMAC_SHA512::Write
CHMAC_SHA512 & Write(const unsigned char *data, size_t len)
Definition: hmac_sha512.h:24
CExtPubKey::nChild
unsigned int nChild
Definition: pubkey.h:208
CKey::vch
unsigned char vch[32]
The actual byte data.
Definition: key.h:50
CPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:95
CKey::begin
const unsigned char * begin() const
Definition: key.h:100
random.h
CKey::GetPrivKey_256
uint256 GetPrivKey_256()
Definition: key.cpp:58
secp256k1.h
GetRandBytes
void GetRandBytes(unsigned char *buf, int num)
Functions to gather random data via the OpenSSL PRNG.
Definition: random.cpp:273
CExtKey
Definition: key.h:161
secp256k1_ecdsa_sign_compact
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5)
Create a compact ECDSA signature (64 byte + recovery id).
Definition: secp256k1.c:108
CExtPubKey::vchFingerprint
unsigned char vchFingerprint[4]
Definition: pubkey.h:207
CHMAC_SHA512::Finalize
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: hmac_sha512.cpp:29
CPubKey::Verify
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Verify a DER signature (~72 bytes).
Definition: pubkey.cpp:15
secp256k1_ec_pubkey_create
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compute the public key for a secret key.
Definition: secp256k1.c:191
CExtKey::Decode
void Decode(const unsigned char code[74])
Definition: key.cpp:230
secp256k1_ecdsa_sign
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, unsigned char *sig, int *siglen, const unsigned char *seckey, const unsigned char *nonce) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6)
Create an ECDSA signature.
Definition: secp256k1.c:75
CPubKey::end
const unsigned char * end() const
Definition: pubkey.h:96
CExtPubKey::vchChainCode
unsigned char vchChainCode[32]
Definition: pubkey.h:209
CKey::SignCompact
bool SignCompact(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Create a compact signature (65 bytes), which allows reconstructing the used public key.
Definition: key.cpp:126
LockObject
void LockObject(const T &t)
Definition: allocators.h:168
CKey::IsValid
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:104
CExtKey::vchChainCode
unsigned char vchChainCode[32]
Definition: key.h:165
secp256k1_ec_privkey_import
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2)
Import a private key in DER format.
Definition: secp256k1.c:318
CPubKey::size
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:94
uint256
256-bit unsigned big integer.
Definition: uint256.h:38
CExtKey::nChild
unsigned int nChild
Definition: key.h:164
CKey::GetPubKey
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:79
CHash256::Write
CHash256 & Write(const unsigned char *data, size_t len)
Definition: hash.h:48
CPubKey::IsCompressed
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:168
BIP32Hash
void BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64])
Definition: hash.cpp:73
key.h
CPubKey
An encapsulated public key.
Definition: pubkey.h:37
CKey::size
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:99
CKey::Load
bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:146
SECP256K1_START_SIGN
#define SECP256K1_START_SIGN
Definition: secp256k1.h:46
CKey
An encapsulated private key.
Definition: key.h:39
CKey::VerifyPubKey
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:111
key
CKey key
Definition: bip38tooldialog.cpp:173
GetStrongRandBytes
void GetStrongRandBytes(unsigned char *out, int num)
Function to gather random data from multiple sources, failing whenever any of those source fail to pr...
Definition: random.cpp:316
CKey::Sign
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig, uint32_t test_case=0) const
Create a DER-serialized signature.
Definition: key.cpp:91
secp256k1_ec_privkey_tweak_add
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2)
Tweak a private key by adding tweak to it.
Definition: secp256k1.c:217
secp256k1_stop
void secp256k1_stop(void)
Free all memory associated with this library.
Definition: secp256k1.c:34
secp256k1_ec_privkey_export
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Export a private key in DER format.
Definition: secp256k1.c:306
CKey::fValid
bool fValid
Whether this private key is valid.
Definition: key.h:44
CHash256
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
Definition: hash.h:33
CPubKey::IsValid
bool IsValid() const
Definition: pubkey.h:159
CECKey::SanityCheck
static bool SanityCheck()
Definition: ecwrapper.cpp:282
CExtPubKey::pubkey
CPubKey pubkey
Definition: pubkey.h:210
RFC6979_HMAC_SHA256
The RFC 6979 PRNG using HMAC-SHA256.
Definition: rfc6979_hmac_sha256.h:14
CExtKey::Neuter
CExtPubKey Neuter() const
Definition: key.cpp:205
CExtKey::Encode
void Encode(unsigned char code[74]) const
Definition: key.cpp:216
CKey::Check
static bool Check(const unsigned char *vch)
Check whether the 32-byte array pointed to be vch is valid keydata.
Definition: key.cpp:35
CExtPubKey
Definition: pubkey.h:205
CExtKey::key
CKey key
Definition: key.h:166
CHMAC_SHA512
A hasher class for HMAC-SHA-512.
Definition: hmac_sha512.h:14
CExtKey::SetMaster
void SetMaster(const unsigned char *seed, unsigned int nSeedLen)
Definition: key.cpp:191
CPubKey::GetID
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:143