Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
key.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2012 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <openssl/ecdsa.h>
6 #include <openssl/rand.h>
7 #include <openssl/obj_mac.h>
8 
9 #include "key.h"
10 
11 
12 // anonymous namespace with local implementation code (OpenSSL interaction)
13 namespace {
14 
15 // Generate a private key from just the secret parameter
16 int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
17 {
18  int ok = 0;
19  BN_CTX *ctx = NULL;
20  EC_POINT *pub_key = NULL;
21 
22  if (!eckey) return 0;
23 
24  const EC_GROUP *group = EC_KEY_get0_group(eckey);
25 
26  if ((ctx = BN_CTX_new()) == NULL)
27  goto err;
28 
29  pub_key = EC_POINT_new(group);
30 
31  if (pub_key == NULL)
32  goto err;
33 
34  if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
35  goto err;
36 
37  EC_KEY_set_private_key(eckey,priv_key);
38  EC_KEY_set_public_key(eckey,pub_key);
39 
40  ok = 1;
41 
42 err:
43 
44  if (pub_key)
45  EC_POINT_free(pub_key);
46  if (ctx != NULL)
47  BN_CTX_free(ctx);
48 
49  return(ok);
50 }
51 
52 // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
53 // recid selects which key is recovered
54 // if check is non-zero, additional checks are performed
55 int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
56 {
57  if (!eckey) return 0;
58 
59  int ret = 0;
60  BN_CTX *ctx = NULL;
61 
62  BIGNUM *x = NULL;
63  BIGNUM *e = NULL;
64  BIGNUM *order = NULL;
65  BIGNUM *sor = NULL;
66  BIGNUM *eor = NULL;
67  BIGNUM *field = NULL;
68  EC_POINT *R = NULL;
69  EC_POINT *O = NULL;
70  EC_POINT *Q = NULL;
71  BIGNUM *rr = NULL;
72  BIGNUM *zero = NULL;
73  int n = 0;
74  int i = recid / 2;
75 
76  const EC_GROUP *group = EC_KEY_get0_group(eckey);
77  if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
78  BN_CTX_start(ctx);
79  order = BN_CTX_get(ctx);
80  if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
81  x = BN_CTX_get(ctx);
82  if (!BN_copy(x, order)) { ret=-1; goto err; }
83  if (!BN_mul_word(x, i)) { ret=-1; goto err; }
84  if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
85  field = BN_CTX_get(ctx);
86  if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
87  if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
88  if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
89  if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
90  if (check)
91  {
92  if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
93  if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
94  if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
95  }
96  if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
97  n = EC_GROUP_get_degree(group);
98  e = BN_CTX_get(ctx);
99  if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
100  if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
101  zero = BN_CTX_get(ctx);
102  if (!BN_zero(zero)) { ret=-1; goto err; }
103  if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
104  rr = BN_CTX_get(ctx);
105  if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
106  sor = BN_CTX_get(ctx);
107  if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
108  eor = BN_CTX_get(ctx);
109  if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
110  if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
111  if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
112 
113  ret = 1;
114 
115 err:
116  if (ctx) {
117  BN_CTX_end(ctx);
118  BN_CTX_free(ctx);
119  }
120  if (R != NULL) EC_POINT_free(R);
121  if (O != NULL) EC_POINT_free(O);
122  if (Q != NULL) EC_POINT_free(Q);
123  return ret;
124 }
125 
126 // RAII Wrapper around OpenSSL's EC_KEY
127 class CECKey {
128 private:
129  EC_KEY *pkey;
130 
131 public:
132  CECKey() {
133  pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
134  assert(pkey != NULL);
135  }
136 
137  ~CECKey() {
138  EC_KEY_free(pkey);
139  }
140 
141  void GetSecretBytes(unsigned char vch[32]) const {
142  const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
143  assert(bn);
144  int nBytes = BN_num_bytes(bn);
145  int n=BN_bn2bin(bn,&vch[32 - nBytes]);
146  assert(n == nBytes);
147  memset(vch, 0, 32 - nBytes);
148  }
149 
150  void SetSecretBytes(const unsigned char vch[32]) {
151  BIGNUM bn;
152  BN_init(&bn);
153  assert(BN_bin2bn(vch, 32, &bn));
154  assert(EC_KEY_regenerate_key(pkey, &bn));
155  BN_clear_free(&bn);
156  }
157 
158  void GetPrivKey(CPrivKey &privkey, bool fCompressed) {
159  EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
160  int nSize = i2d_ECPrivateKey(pkey, NULL);
161  assert(nSize);
162  privkey.resize(nSize);
163  unsigned char* pbegin = &privkey[0];
164  int nSize2 = i2d_ECPrivateKey(pkey, &pbegin);
165  assert(nSize == nSize2);
166  }
167 
168  bool SetPrivKey(const CPrivKey &privkey) {
169  const unsigned char* pbegin = &privkey[0];
170  if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
171  // d2i_ECPrivateKey returns true if parsing succeeds.
172  // This doesn't necessarily mean the key is valid.
173  if (EC_KEY_check_key(pkey))
174  return true;
175  }
176  return false;
177  }
178 
179  void GetPubKey(CPubKey &pubkey, bool fCompressed) {
180  EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
181  int nSize = i2o_ECPublicKey(pkey, NULL);
182  assert(nSize);
183  assert(nSize <= 65);
184  unsigned char c[65];
185  unsigned char *pbegin = c;
186  int nSize2 = i2o_ECPublicKey(pkey, &pbegin);
187  assert(nSize == nSize2);
188  pubkey.Set(&c[0], &c[nSize]);
189  }
190 
191  bool SetPubKey(const CPubKey &pubkey) {
192  const unsigned char* pbegin = pubkey.begin();
193  return o2i_ECPublicKey(&pkey, &pbegin, pubkey.size());
194  }
195 
196  bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) {
197  unsigned int nSize = ECDSA_size(pkey);
198  vchSig.resize(nSize); // Make sure it is big enough
199  assert(ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey));
200  vchSig.resize(nSize); // Shrink to fit actual size
201  return true;
202  }
203 
204  bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
205  // -1 = error, 0 = bad sig, 1 = good
206  if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
207  return false;
208  return true;
209  }
210 
211  bool SignCompact(const uint256 &hash, unsigned char *p64, int &rec) {
212  bool fOk = false;
213  ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
214  if (sig==NULL)
215  return false;
216  memset(p64, 0, 64);
217  int nBitsR = BN_num_bits(sig->r);
218  int nBitsS = BN_num_bits(sig->s);
219  if (nBitsR <= 256 && nBitsS <= 256) {
220  CPubKey pubkey;
221  GetPubKey(pubkey, true);
222  for (int i=0; i<4; i++) {
223  CECKey keyRec;
224  if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1) {
225  CPubKey pubkeyRec;
226  keyRec.GetPubKey(pubkeyRec, true);
227  if (pubkeyRec == pubkey) {
228  rec = i;
229  fOk = true;
230  break;
231  }
232  }
233  }
234  assert(fOk);
235  BN_bn2bin(sig->r,&p64[32-(nBitsR+7)/8]);
236  BN_bn2bin(sig->s,&p64[64-(nBitsS+7)/8]);
237  }
238  ECDSA_SIG_free(sig);
239  return fOk;
240  }
241 
242  // reconstruct public key from a compact signature
243  // This is only slightly more CPU intensive than just verifying it.
244  // If this function succeeds, the recovered public key is guaranteed to be valid
245  // (the signature is a valid signature of the given data for that key)
246  bool Recover(const uint256 &hash, const unsigned char *p64, int rec)
247  {
248  if (rec<0 || rec>=3)
249  return false;
250  ECDSA_SIG *sig = ECDSA_SIG_new();
251  BN_bin2bn(&p64[0], 32, sig->r);
252  BN_bin2bn(&p64[32], 32, sig->s);
253  bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1;
254  ECDSA_SIG_free(sig);
255  return ret;
256  }
257 };
258 
259 }; // end of anonymous namespace
260 
261 bool CKey::Check(const unsigned char *vch) {
262  // Do not convert to OpenSSL's data structures for range-checking keys,
263  // it's easy enough to do directly.
264  static const unsigned char vchMax[32] = {
265  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
266  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
267  0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
268  0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
269  };
270  bool fIsZero = true;
271  for (int i=0; i<32 && fIsZero; i++)
272  if (vch[i] != 0)
273  fIsZero = false;
274  if (fIsZero)
275  return false;
276  for (int i=0; i<32; i++) {
277  if (vch[i] < vchMax[i])
278  return true;
279  if (vch[i] > vchMax[i])
280  return false;
281  }
282  return true;
283 }
284 
285 void CKey::MakeNewKey(bool fCompressedIn) {
286  do {
287  RAND_bytes(vch, sizeof(vch));
288  } while (!Check(vch));
289  fValid = true;
290  fCompressed = fCompressedIn;
291 }
292 
293 bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
294  CECKey key;
295  if (!key.SetPrivKey(privkey))
296  return false;
297  key.GetSecretBytes(vch);
298  fCompressed = fCompressedIn;
299  fValid = true;
300  return true;
301 }
302 
304  assert(fValid);
305  CECKey key;
306  key.SetSecretBytes(vch);
307  CPrivKey privkey;
308  key.GetPrivKey(privkey, fCompressed);
309  return privkey;
310 }
311 
313  assert(fValid);
314  CECKey key;
315  key.SetSecretBytes(vch);
316  CPubKey pubkey;
317  key.GetPubKey(pubkey, fCompressed);
318  return pubkey;
319 }
320 
321 bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
322  if (!fValid)
323  return false;
324  CECKey key;
325  key.SetSecretBytes(vch);
326  return key.Sign(hash, vchSig);
327 }
328 
329 bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
330  if (!fValid)
331  return false;
332  CECKey key;
333  key.SetSecretBytes(vch);
334  vchSig.resize(65);
335  int rec = -1;
336  if (!key.SignCompact(hash, &vchSig[1], rec))
337  return false;
338  assert(rec != -1);
339  vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
340  return true;
341 }
342 
343 bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
344  if (!IsValid())
345  return false;
346  CECKey key;
347  if (!key.SetPubKey(*this))
348  return false;
349  if (!key.Verify(hash, vchSig))
350  return false;
351  return true;
352 }
353 
354 bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
355  if (vchSig.size() != 65)
356  return false;
357  CECKey key;
358  if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4))
359  return false;
360  key.GetPubKey(*this, (vchSig[0] - 27) & 4);
361  return true;
362 }
363 
364 bool CPubKey::VerifyCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
365  if (!IsValid())
366  return false;
367  if (vchSig.size() != 65)
368  return false;
369  CECKey key;
370  if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4))
371  return false;
372  CPubKey pubkeyRec;
373  key.GetPubKey(pubkeyRec, IsCompressed());
374  if (*this != pubkeyRec)
375  return false;
376  return true;
377 }
378 
379 bool CPubKey::IsFullyValid() const {
380  if (!IsValid())
381  return false;
382  CECKey key;
383  if (!key.SetPubKey(*this))
384  return false;
385  return true;
386 }
387 
389  if (!IsValid())
390  return false;
391  CECKey key;
392  if (!key.SetPubKey(*this))
393  return false;
394  key.GetPubKey(*this, false);
395  return true;
396 }
bool VerifyCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Definition: key.cpp:364
unsigned int size() const
Definition: key.h:88
void Set(const T pbegin, const T pend)
Definition: key.h:68
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Definition: key.cpp:321
bool fValid
Definition: key.h:176
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
Definition: key.h:169
CPubKey GetPubKey() const
Definition: key.cpp:312
CPrivKey GetPrivKey() const
Definition: key.cpp:303
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Definition: key.cpp:354
An encapsulated public key.
Definition: key.h:40
void MakeNewKey(bool fCompressed)
Definition: key.cpp:285
const unsigned char * begin() const
Definition: key.h:89
bool IsCompressed() const
Definition: key.h:147
256-bit unsigned integer
Definition: uint256.h:537
bool SetPrivKey(const CPrivKey &vchPrivKey, bool fCompressed)
Definition: key.cpp:293
bool SignCompact(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Definition: key.cpp:329
bool IsFullyValid() const
Definition: key.cpp:379
bool IsValid() const
Definition: key.h:139
static bool Check(const unsigned char *vch)
Definition: key.cpp:261
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Definition: key.cpp:343
unsigned int size() const
Definition: uint256.h:368
uint32_t hash
Definition: cache.cc:34
bool Decompress()
Definition: key.cpp:388