genesis 1
genesis 2
genesis 3
genesis 4
genesis 5 #ifndef BITCOIN_KEY_H
genesis 6 #define BITCOIN_KEY_H
genesis 7
genesis 8 #include <stdexcept>
genesis 9 #include <vector>
genesis 10
genesis 11 #include <openssl/ec.h>
genesis 12 #include <openssl/ecdsa.h>
genesis 13 #include <openssl/obj_mac.h>
genesis 14
genesis 15 #include "serialize.h"
genesis 16 #include "uint256.h"
genesis 17 #include "base58.h"
genesis 18
genesis 19
genesis 20
genesis 21
genesis 22
genesis 23
genesis 24
genesis 25
genesis 26
genesis 27
genesis 28
genesis 29
genesis 30
genesis 31
genesis 32
genesis 33
genesis 34
genesis 35
genesis 36
genesis 37
genesis 38
genesis 39
genesis 40
genesis 41
genesis 42
genesis 43 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
genesis 44 {
genesis 45 int ok = 0;
genesis 46 BN_CTX *ctx = NULL;
genesis 47 EC_POINT *pub_key = NULL;
genesis 48
genesis 49 if (!eckey) return 0;
genesis 50
genesis 51 const EC_GROUP *group = EC_KEY_get0_group(eckey);
genesis 52
genesis 53 if ((ctx = BN_CTX_new()) == NULL)
genesis 54 goto err;
genesis 55
genesis 56 pub_key = EC_POINT_new(group);
genesis 57
genesis 58 if (pub_key == NULL)
genesis 59 goto err;
genesis 60
genesis 61 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
genesis 62 goto err;
genesis 63
genesis 64 EC_KEY_set_private_key(eckey,priv_key);
genesis 65 EC_KEY_set_public_key(eckey,pub_key);
genesis 66
genesis 67 ok = 1;
genesis 68
genesis 69 err:
genesis 70
genesis 71 if (pub_key)
genesis 72 EC_POINT_free(pub_key);
genesis 73 if (ctx != NULL)
genesis 74 BN_CTX_free(ctx);
genesis 75
genesis 76 return(ok);
genesis 77 }
genesis 78
genesis 79
genesis 80
genesis 81
genesis 82 int static inline ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
genesis 83 {
genesis 84 if (!eckey) return 0;
genesis 85
genesis 86 int ret = 0;
genesis 87 BN_CTX *ctx = NULL;
genesis 88
genesis 89 BIGNUM *x = NULL;
genesis 90 BIGNUM *e = NULL;
genesis 91 BIGNUM *order = NULL;
genesis 92 BIGNUM *sor = NULL;
genesis 93 BIGNUM *eor = NULL;
genesis 94 BIGNUM *field = NULL;
genesis 95 EC_POINT *R = NULL;
genesis 96 EC_POINT *O = NULL;
genesis 97 EC_POINT *Q = NULL;
genesis 98 BIGNUM *rr = NULL;
genesis 99 BIGNUM *zero = NULL;
genesis 100 int n = 0;
genesis 101 int i = recid / 2;
genesis 102
genesis 103 const EC_GROUP *group = EC_KEY_get0_group(eckey);
genesis 104 if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
genesis 105 BN_CTX_start(ctx);
genesis 106 order = BN_CTX_get(ctx);
genesis 107 if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
genesis 108 x = BN_CTX_get(ctx);
genesis 109 if (!BN_copy(x, order)) { ret=-1; goto err; }
genesis 110 if (!BN_mul_word(x, i)) { ret=-1; goto err; }
genesis 111 if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
genesis 112 field = BN_CTX_get(ctx);
genesis 113 if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
genesis 114 if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
genesis 115 if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
genesis 116 if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
genesis 117 if (check)
genesis 118 {
genesis 119 if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
genesis 120 if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
genesis 121 if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
genesis 122 }
genesis 123 if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
genesis 124 n = EC_GROUP_get_degree(group);
genesis 125 e = BN_CTX_get(ctx);
genesis 126 if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
genesis 127 if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
genesis 128 zero = BN_CTX_get(ctx);
genesis 129 if (!BN_zero(zero)) { ret=-1; goto err; }
genesis 130 if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
genesis 131 rr = BN_CTX_get(ctx);
genesis 132 if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
genesis 133 sor = BN_CTX_get(ctx);
genesis 134 if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
genesis 135 eor = BN_CTX_get(ctx);
genesis 136 if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
genesis 137 if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
genesis 138 if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
genesis 139
genesis 140 ret = 1;
genesis 141
genesis 142 err:
genesis 143 if (ctx) {
genesis 144 BN_CTX_end(ctx);
genesis 145 BN_CTX_free(ctx);
genesis 146 }
genesis 147 if (R != NULL) EC_POINT_free(R);
genesis 148 if (O != NULL) EC_POINT_free(O);
genesis 149 if (Q != NULL) EC_POINT_free(Q);
genesis 150 return ret;
genesis 151 }
genesis 152
genesis 153 class key_error : public std::runtime_error
genesis 154 {
genesis 155 public:
genesis 156 explicit key_error(const std::string& str) : std::runtime_error(str) {}
genesis 157 };
genesis 158
genesis 159
genesis 160
genesis 161
genesis 162 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
genesis 163
genesis 164 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
genesis 165
genesis 166 class CKey
genesis 167 {
genesis 168 protected:
genesis 169 EC_KEY* pkey;
genesis 170 bool fSet;
genesis 171
genesis 172 public:
genesis 173 CKey()
genesis 174 {
genesis 175 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 176 if (pkey == NULL)
genesis 177 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
genesis 178 fSet = false;
genesis 179 }
genesis 180
genesis 181 CKey(const CKey& b)
genesis 182 {
genesis 183 pkey = EC_KEY_dup(b.pkey);
genesis 184 if (pkey == NULL)
genesis 185 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
genesis 186 fSet = b.fSet;
genesis 187 }
genesis 188
genesis 189 CKey& operator=(const CKey& b)
genesis 190 {
genesis 191 if (!EC_KEY_copy(pkey, b.pkey))
genesis 192 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
genesis 193 fSet = b.fSet;
genesis 194 return (*this);
genesis 195 }
genesis 196
genesis 197 ~CKey()
genesis 198 {
genesis 199 EC_KEY_free(pkey);
genesis 200 }
genesis 201
genesis 202 bool IsNull() const
genesis 203 {
genesis 204 return !fSet;
genesis 205 }
genesis 206
genesis 207 void MakeNewKey()
genesis 208 {
genesis 209 if (!EC_KEY_generate_key(pkey))
genesis 210 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
genesis 211 fSet = true;
genesis 212 }
genesis 213
genesis 214 bool SetPrivKey(const CPrivKey& vchPrivKey)
genesis 215 {
genesis 216 const unsigned char* pbegin = &vchPrivKey[0];
genesis 217 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
genesis 218 return false;
genesis 219 fSet = true;
genesis 220 return true;
genesis 221 }
genesis 222
genesis 223 bool SetSecret(const CSecret& vchSecret)
genesis 224 {
genesis 225 EC_KEY_free(pkey);
genesis 226 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 227 if (pkey == NULL)
genesis 228 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
genesis 229 if (vchSecret.size() != 32)
genesis 230 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
genesis 231 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
genesis 232 if (bn == NULL)
genesis 233 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
genesis 234 if (!EC_KEY_regenerate_key(pkey,bn))
genesis 235 {
genesis 236 BN_clear_free(bn);
genesis 237 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
genesis 238 }
genesis 239 BN_clear_free(bn);
genesis 240 fSet = true;
genesis 241 return true;
genesis 242 }
genesis 243
genesis 244 CSecret GetSecret() const
genesis 245 {
genesis 246 CSecret vchRet;
genesis 247 vchRet.resize(32);
genesis 248 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
genesis 249 int nBytes = BN_num_bytes(bn);
genesis 250 if (bn == NULL)
genesis 251 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
genesis 252 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
genesis 253 if (n != nBytes)
genesis 254 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
genesis 255 return vchRet;
genesis 256 }
genesis 257
genesis 258 CPrivKey GetPrivKey() const
genesis 259 {
genesis 260 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
genesis 261 if (!nSize)
genesis 262 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
genesis 263 CPrivKey vchPrivKey(nSize, 0);
genesis 264 unsigned char* pbegin = &vchPrivKey[0];
genesis 265 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
genesis 266 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
genesis 267 return vchPrivKey;
genesis 268 }
genesis 269
genesis 270 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
genesis 271 {
genesis 272 const unsigned char* pbegin = &vchPubKey[0];
genesis 273 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
genesis 274 return false;
genesis 275 fSet = true;
genesis 276 return true;
genesis 277 }
genesis 278
genesis 279 std::vector<unsigned char> GetPubKey() const
genesis 280 {
genesis 281 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
genesis 282 if (!nSize)
genesis 283 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
genesis 284 std::vector<unsigned char> vchPubKey(nSize, 0);
genesis 285 unsigned char* pbegin = &vchPubKey[0];
genesis 286 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
genesis 287 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
genesis 288 return vchPubKey;
genesis 289 }
genesis 290
genesis 291 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
genesis 292 {
genesis 293 vchSig.clear();
mod6_der_high_low_s 294 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char *) &hash, sizeof(hash), pkey);
mod6_der_high_low_s 295
mod6_der_high_low_s 296 if (sig == NULL)
mod6_der_high_low_s 297 {
mod6_der_high_low_s 298 printf("ERROR, ECDSA_sign failed in key.h:Sign()\n");
genesis 299 return false;
mod6_der_high_low_s 300 }
mod6_der_high_low_s 301
mod6_der_high_low_s 302 BN_CTX *ctx = BN_CTX_new();
mod6_der_high_low_s 303 BN_CTX_start(ctx);
mod6_der_high_low_s 304 const EC_GROUP *group = EC_KEY_get0_group(pkey);
mod6_der_high_low_s 305 BIGNUM *order = BN_CTX_get(ctx);
mod6_der_high_low_s 306 BIGNUM *halforder = BN_CTX_get(ctx);
mod6_der_high_low_s 307 EC_GROUP_get_order(group, order, ctx);
mod6_der_high_low_s 308 BN_rshift1(halforder, order);
mod6_der_high_low_s 309
mod6_der_high_low_s 310 if (fHighS && (BN_cmp(sig->s, halforder) < 0))
mod6_der_high_low_s 311 {
mod6_der_high_low_s 312
mod6_der_high_low_s 313 BN_sub(sig->s, order, sig->s);
mod6_der_high_low_s 314 }
mod6_der_high_low_s 315
mod6_der_high_low_s 316 if (fLowS && (BN_cmp(sig->s, halforder) > 0))
mod6_der_high_low_s 317 {
mod6_der_high_low_s 318
mod6_der_high_low_s 319 BN_sub(sig->s, order, sig->s);
mod6_der_high_low_s 320 }
mod6_der_high_low_s 321
mod6_der_high_low_s 322 BN_CTX_end(ctx);
mod6_der_high_low_s 323 BN_CTX_free(ctx);
mod6_der_high_low_s 324 unsigned int nSize = ECDSA_size(pkey);
mod6_der_high_low_s 325 vchSig.resize(nSize);
mod6_der_high_low_s 326 unsigned char *pos = &vchSig[0];
mod6_der_high_low_s 327 nSize = i2d_ECDSA_SIG(sig, &pos);
mod6_der_high_low_s 328
mod6_der_high_low_s 329
mod6_der_high_low_s 330
mod6_der_high_low_s 331
mod6_der_high_low_s 332 ECDSA_SIG_free(sig);
mod6_der_high_low_s 333 vchSig.resize(nSize);
genesis 334 return true;
genesis 335 }
genesis 336
genesis 337
genesis 338
genesis 339
genesis 340
genesis 341 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
genesis 342 {
genesis 343 bool fOk = false;
genesis 344 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
genesis 345 if (sig==NULL)
genesis 346 return false;
genesis 347 vchSig.clear();
genesis 348 vchSig.resize(65,0);
genesis 349 int nBitsR = BN_num_bits(sig->r);
genesis 350 int nBitsS = BN_num_bits(sig->s);
genesis 351 if (nBitsR <= 256 && nBitsS <= 256)
genesis 352 {
genesis 353 int nRecId = -1;
genesis 354 for (int i=0; i<4; i++)
genesis 355 {
genesis 356 CKey keyRec;
genesis 357 keyRec.fSet = true;
genesis 358 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
genesis 359 if (keyRec.GetPubKey() == this->GetPubKey())
genesis 360 {
genesis 361 nRecId = i;
genesis 362 break;
genesis 363 }
genesis 364 }
genesis 365
genesis 366 if (nRecId == -1)
genesis 367 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
genesis 368
genesis 369 vchSig[0] = nRecId+27;
genesis 370 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
genesis 371 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
genesis 372 fOk = true;
genesis 373 }
genesis 374 ECDSA_SIG_free(sig);
genesis 375 return fOk;
genesis 376 }
genesis 377
genesis 378
genesis 379
genesis 380
genesis 381
genesis 382 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 383 {
genesis 384 if (vchSig.size() != 65)
genesis 385 return false;
genesis 386 if (vchSig[0]<27 || vchSig[0]>=31)
genesis 387 return false;
genesis 388 ECDSA_SIG *sig = ECDSA_SIG_new();
genesis 389 BN_bin2bn(&vchSig[1],32,sig->r);
genesis 390 BN_bin2bn(&vchSig[33],32,sig->s);
genesis 391
genesis 392 EC_KEY_free(pkey);
genesis 393 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 394 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
genesis 395 {
genesis 396 fSet = true;
genesis 397 ECDSA_SIG_free(sig);
genesis 398 return true;
genesis 399 }
genesis 400 return false;
genesis 401 }
genesis 402
genesis 403 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 404 {
genesis 405
genesis 406 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
genesis 407 return false;
genesis 408 return true;
genesis 409 }
genesis 410
genesis 411
genesis 412 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 413 {
genesis 414 CKey key;
genesis 415 if (!key.SetCompactSignature(hash, vchSig))
genesis 416 return false;
genesis 417 if (GetPubKey() != key.GetPubKey())
genesis 418 return false;
genesis 419 return true;
genesis 420 }
genesis 421
genesis 422
genesis 423 CBitcoinAddress GetAddress() const
genesis 424 {
genesis 425 return CBitcoinAddress(GetPubKey());
genesis 426 }
genesis 427
genesis 428 bool IsValid()
genesis 429 {
genesis 430 if (!fSet)
genesis 431 return false;
genesis 432
genesis 433 CSecret secret = GetSecret();
genesis 434 CKey key2;
genesis 435 key2.SetSecret(secret);
genesis 436 return GetPubKey() == key2.GetPubKey();
genesis 437 }
genesis 438 };
genesis 439
genesis 440 #endif