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();
genesis 294 unsigned char pchSig[10000];
genesis 295 unsigned int nSize = 0;
genesis 296 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
genesis 297 return false;
genesis 298 vchSig.resize(nSize);
genesis 299 memcpy(&vchSig[0], pchSig, nSize);
genesis 300 return true;
genesis 301 }
genesis 302
genesis 303
genesis 304
genesis 305
genesis 306
genesis 307 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
genesis 308 {
genesis 309 bool fOk = false;
genesis 310 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
genesis 311 if (sig==NULL)
genesis 312 return false;
genesis 313 vchSig.clear();
genesis 314 vchSig.resize(65,0);
genesis 315 int nBitsR = BN_num_bits(sig->r);
genesis 316 int nBitsS = BN_num_bits(sig->s);
genesis 317 if (nBitsR <= 256 && nBitsS <= 256)
genesis 318 {
genesis 319 int nRecId = -1;
genesis 320 for (int i=0; i<4; i++)
genesis 321 {
genesis 322 CKey keyRec;
genesis 323 keyRec.fSet = true;
genesis 324 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
genesis 325 if (keyRec.GetPubKey() == this->GetPubKey())
genesis 326 {
genesis 327 nRecId = i;
genesis 328 break;
genesis 329 }
genesis 330 }
genesis 331
genesis 332 if (nRecId == -1)
genesis 333 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
genesis 334
genesis 335 vchSig[0] = nRecId+27;
genesis 336 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
genesis 337 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
genesis 338 fOk = true;
genesis 339 }
genesis 340 ECDSA_SIG_free(sig);
genesis 341 return fOk;
genesis 342 }
genesis 343
genesis 344
genesis 345
genesis 346
genesis 347
genesis 348 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 349 {
genesis 350 if (vchSig.size() != 65)
genesis 351 return false;
genesis 352 if (vchSig[0]<27 || vchSig[0]>=31)
genesis 353 return false;
genesis 354 ECDSA_SIG *sig = ECDSA_SIG_new();
genesis 355 BN_bin2bn(&vchSig[1],32,sig->r);
genesis 356 BN_bin2bn(&vchSig[33],32,sig->s);
genesis 357
genesis 358 EC_KEY_free(pkey);
genesis 359 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 360 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
genesis 361 {
genesis 362 fSet = true;
genesis 363 ECDSA_SIG_free(sig);
genesis 364 return true;
genesis 365 }
genesis 366 return false;
genesis 367 }
genesis 368
genesis 369 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 370 {
genesis 371
genesis 372 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
genesis 373 return false;
genesis 374 return true;
genesis 375 }
genesis 376
genesis 377
genesis 378 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 379 {
genesis 380 CKey key;
genesis 381 if (!key.SetCompactSignature(hash, vchSig))
genesis 382 return false;
genesis 383 if (GetPubKey() != key.GetPubKey())
genesis 384 return false;
genesis 385 return true;
genesis 386 }
genesis 387
genesis 388
genesis 389 CBitcoinAddress GetAddress() const
genesis 390 {
genesis 391 return CBitcoinAddress(GetPubKey());
genesis 392 }
genesis 393
genesis 394 bool IsValid()
genesis 395 {
genesis 396 if (!fSet)
genesis 397 return false;
genesis 398
genesis 399 CSecret secret = GetSecret();
genesis 400 CKey key2;
genesis 401 key2.SetSecret(secret);
genesis 402 return GetPubKey() == key2.GetPubKey();
genesis 403 }
genesis 404 };
genesis 405
genesis 406 #endif