0001
0002
0003
0004
0005 #ifndef BITCOIN_KEY_H
0006 #define BITCOIN_KEY_H
0007
0008 #include <stdexcept>
0009 #include <vector>
0010
0011 #include <openssl/ec.h>
0012 #include <openssl/ecdsa.h>
0013 #include <openssl/obj_mac.h>
0014
0015 #include "serialize.h"
0016 #include "uint256.h"
0017 #include "base58.h"
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
0044 {
0045 int ok = 0;
0046 BN_CTX *ctx = NULL;
0047 EC_POINT *pub_key = NULL;
0048
0049 if (!eckey) return 0;
0050
0051 const EC_GROUP *group = EC_KEY_get0_group(eckey);
0052
0053 if ((ctx = BN_CTX_new()) == NULL)
0054 goto err;
0055
0056 pub_key = EC_POINT_new(group);
0057
0058 if (pub_key == NULL)
0059 goto err;
0060
0061 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
0062 goto err;
0063
0064 EC_KEY_set_private_key(eckey,priv_key);
0065 EC_KEY_set_public_key(eckey,pub_key);
0066
0067 ok = 1;
0068
0069 err:
0070
0071 if (pub_key)
0072 EC_POINT_free(pub_key);
0073 if (ctx != NULL)
0074 BN_CTX_free(ctx);
0075
0076 return(ok);
0077 }
0078
0079
0080
0081
0082 int static inline ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
0083 {
0084 if (!eckey) return 0;
0085
0086 int ret = 0;
0087 BN_CTX *ctx = NULL;
0088
0089 BIGNUM *x = NULL;
0090 BIGNUM *e = NULL;
0091 BIGNUM *order = NULL;
0092 BIGNUM *sor = NULL;
0093 BIGNUM *eor = NULL;
0094 BIGNUM *field = NULL;
0095 EC_POINT *R = NULL;
0096 EC_POINT *O = NULL;
0097 EC_POINT *Q = NULL;
0098 BIGNUM *rr = NULL;
0099 BIGNUM *zero = NULL;
0100 int n = 0;
0101 int i = recid / 2;
0102
0103 const EC_GROUP *group = EC_KEY_get0_group(eckey);
0104 if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
0105 BN_CTX_start(ctx);
0106 order = BN_CTX_get(ctx);
0107 if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
0108 x = BN_CTX_get(ctx);
0109 if (!BN_copy(x, order)) { ret=-1; goto err; }
0110 if (!BN_mul_word(x, i)) { ret=-1; goto err; }
0111 if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
0112 field = BN_CTX_get(ctx);
0113 if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
0114 if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
0115 if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
0116 if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
0117 if (check)
0118 {
0119 if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
0120 if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
0121 if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
0122 }
0123 if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
0124 n = EC_GROUP_get_degree(group);
0125 e = BN_CTX_get(ctx);
0126 if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
0127 if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
0128 zero = BN_CTX_get(ctx);
0129 if (!BN_zero(zero)) { ret=-1; goto err; }
0130 if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
0131 rr = BN_CTX_get(ctx);
0132 if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
0133 sor = BN_CTX_get(ctx);
0134 if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
0135 eor = BN_CTX_get(ctx);
0136 if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
0137 if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
0138 if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
0139
0140 ret = 1;
0141
0142 err:
0143 if (ctx) {
0144 BN_CTX_end(ctx);
0145 BN_CTX_free(ctx);
0146 }
0147 if (R != NULL) EC_POINT_free(R);
0148 if (O != NULL) EC_POINT_free(O);
0149 if (Q != NULL) EC_POINT_free(Q);
0150 return ret;
0151 }
0152
0153 class key_error : public std::runtime_error
0154 {
0155 public:
0156 explicit key_error(const std::string& str) : std::runtime_error(str) {}
0157 };
0158
0159
0160
0161
0162 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
0163
0164 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
0165
0166 class CKey
0167 {
0168 protected:
0169 EC_KEY* pkey;
0170 bool fSet;
0171
0172 public:
0173 CKey()
0174 {
0175 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
0176 if (pkey == NULL)
0177 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
0178 fSet = false;
0179 }
0180
0181 CKey(const CKey& b)
0182 {
0183 pkey = EC_KEY_dup(b.pkey);
0184 if (pkey == NULL)
0185 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
0186 fSet = b.fSet;
0187 }
0188
0189 CKey& operator=(const CKey& b)
0190 {
0191 if (!EC_KEY_copy(pkey, b.pkey))
0192 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
0193 fSet = b.fSet;
0194 return (*this);
0195 }
0196
0197 ~CKey()
0198 {
0199 EC_KEY_free(pkey);
0200 }
0201
0202 bool IsNull() const
0203 {
0204 return !fSet;
0205 }
0206
0207 void MakeNewKey()
0208 {
0209 if (!EC_KEY_generate_key(pkey))
0210 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
0211 fSet = true;
0212 }
0213
0214 bool SetPrivKey(const CPrivKey& vchPrivKey)
0215 {
0216 const unsigned char* pbegin = &vchPrivKey[0];
0217 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
0218 return false;
0219 fSet = true;
0220 return true;
0221 }
0222
0223 bool SetSecret(const CSecret& vchSecret)
0224 {
0225 EC_KEY_free(pkey);
0226 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
0227 if (pkey == NULL)
0228 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
0229 if (vchSecret.size() != 32)
0230 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
0231 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
0232 if (bn == NULL)
0233 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
0234 if (!EC_KEY_regenerate_key(pkey,bn))
0235 {
0236 BN_clear_free(bn);
0237 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
0238 }
0239 BN_clear_free(bn);
0240 fSet = true;
0241 return true;
0242 }
0243
0244 CSecret GetSecret() const
0245 {
0246 CSecret vchRet;
0247 vchRet.resize(32);
0248 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
0249 int nBytes = BN_num_bytes(bn);
0250 if (bn == NULL)
0251 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
0252 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
0253 if (n != nBytes)
0254 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
0255 return vchRet;
0256 }
0257
0258 CPrivKey GetPrivKey() const
0259 {
0260 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
0261 if (!nSize)
0262 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
0263 CPrivKey vchPrivKey(nSize, 0);
0264 unsigned char* pbegin = &vchPrivKey[0];
0265 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
0266 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
0267 return vchPrivKey;
0268 }
0269
0270 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
0271 {
0272 const unsigned char* pbegin = &vchPubKey[0];
0273 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
0274 return false;
0275 fSet = true;
0276 return true;
0277 }
0278
0279 std::vector<unsigned char> GetPubKey() const
0280 {
0281 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
0282 if (!nSize)
0283 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
0284 std::vector<unsigned char> vchPubKey(nSize, 0);
0285 unsigned char* pbegin = &vchPubKey[0];
0286 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
0287 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
0288 return vchPubKey;
0289 }
0290
0291 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
0292 {
0293 vchSig.clear();
0294 unsigned char pchSig[10000];
0295 unsigned int nSize = 0;
0296 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
0297 return false;
0298 vchSig.resize(nSize);
0299 memcpy(&vchSig[0], pchSig, nSize);
0300 return true;
0301 }
0302
0303
0304
0305
0306
0307 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
0308 {
0309 bool fOk = false;
0310 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
0311 if (sig==NULL)
0312 return false;
0313 vchSig.clear();
0314 vchSig.resize(65,0);
0315 int nBitsR = BN_num_bits(sig->r);
0316 int nBitsS = BN_num_bits(sig->s);
0317 if (nBitsR <= 256 && nBitsS <= 256)
0318 {
0319 int nRecId = -1;
0320 for (int i=0; i<4; i++)
0321 {
0322 CKey keyRec;
0323 keyRec.fSet = true;
0324 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
0325 if (keyRec.GetPubKey() == this->GetPubKey())
0326 {
0327 nRecId = i;
0328 break;
0329 }
0330 }
0331
0332 if (nRecId == -1)
0333 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
0334
0335 vchSig[0] = nRecId+27;
0336 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
0337 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
0338 fOk = true;
0339 }
0340 ECDSA_SIG_free(sig);
0341 return fOk;
0342 }
0343
0344
0345
0346
0347
0348 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
0349 {
0350 if (vchSig.size() != 65)
0351 return false;
0352 if (vchSig[0]<27 || vchSig[0]>=31)
0353 return false;
0354 ECDSA_SIG *sig = ECDSA_SIG_new();
0355 BN_bin2bn(&vchSig[1],32,sig->r);
0356 BN_bin2bn(&vchSig[33],32,sig->s);
0357
0358 EC_KEY_free(pkey);
0359 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
0360 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
0361 {
0362 fSet = true;
0363 ECDSA_SIG_free(sig);
0364 return true;
0365 }
0366 return false;
0367 }
0368
0369 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
0370 {
0371
0372 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
0373 return false;
0374 return true;
0375 }
0376
0377
0378 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
0379 {
0380 CKey key;
0381 if (!key.SetCompactSignature(hash, vchSig))
0382 return false;
0383 if (GetPubKey() != key.GetPubKey())
0384 return false;
0385 return true;
0386 }
0387
0388
0389 CBitcoinAddress GetAddress() const
0390 {
0391 return CBitcoinAddress(GetPubKey());
0392 }
0393
0394 bool IsValid()
0395 {
0396 if (!fSet)
0397 return false;
0398
0399 CSecret secret = GetSecret();
0400 CKey key2;
0401 key2.SetSecret(secret);
0402 return GetPubKey() == key2.GetPubKey();
0403 }
0404 };
0405
0406 #endif