raw
genesis                 1 // Copyright (c) 2009-2010 Satoshi Nakamoto
genesis 2 // Copyright (c) 2009-2012 The Bitcoin developers
genesis 3 // Distributed under the MIT/X11 software license, see the accompanying
genesis 4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
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
genesis 18 // secp160k1
genesis 19 // const unsigned int PRIVATE_KEY_SIZE = 192;
genesis 20 // const unsigned int PUBLIC_KEY_SIZE = 41;
genesis 21 // const unsigned int SIGNATURE_SIZE = 48;
genesis 22 //
genesis 23 // secp192k1
genesis 24 // const unsigned int PRIVATE_KEY_SIZE = 222;
genesis 25 // const unsigned int PUBLIC_KEY_SIZE = 49;
genesis 26 // const unsigned int SIGNATURE_SIZE = 57;
genesis 27 //
genesis 28 // secp224k1
genesis 29 // const unsigned int PRIVATE_KEY_SIZE = 250;
genesis 30 // const unsigned int PUBLIC_KEY_SIZE = 57;
genesis 31 // const unsigned int SIGNATURE_SIZE = 66;
genesis 32 //
genesis 33 // secp256k1:
genesis 34 // const unsigned int PRIVATE_KEY_SIZE = 279;
genesis 35 // const unsigned int PUBLIC_KEY_SIZE = 65;
genesis 36 // const unsigned int SIGNATURE_SIZE = 72;
genesis 37 //
genesis 38 // see www.keylength.com
genesis 39 // script supports up to 75 for single byte push
genesis 40
genesis 41 // Generate a private key from just the secret parameter
genesis 42 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
genesis 43 {
genesis 44 int ok = 0;
genesis 45 BN_CTX *ctx = NULL;
genesis 46 EC_POINT *pub_key = NULL;
genesis 47
genesis 48 if (!eckey) return 0;
genesis 49
genesis 50 const EC_GROUP *group = EC_KEY_get0_group(eckey);
genesis 51
genesis 52 if ((ctx = BN_CTX_new()) == NULL)
genesis 53 goto err;
genesis 54
genesis 55 pub_key = EC_POINT_new(group);
genesis 56
genesis 57 if (pub_key == NULL)
genesis 58 goto err;
genesis 59
genesis 60 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
genesis 61 goto err;
genesis 62
genesis 63 EC_KEY_set_private_key(eckey,priv_key);
genesis 64 EC_KEY_set_public_key(eckey,pub_key);
genesis 65
genesis 66 ok = 1;
genesis 67
genesis 68 err:
genesis 69
genesis 70 if (pub_key)
genesis 71 EC_POINT_free(pub_key);
genesis 72 if (ctx != NULL)
genesis 73 BN_CTX_free(ctx);
genesis 74
genesis 75 return(ok);
genesis 76 }
genesis 77
genesis 78 // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
genesis 79 // recid selects which key is recovered
genesis 80 // if check is nonzero, additional checks are performed
genesis 81 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 82 {
genesis 83 if (!eckey) return 0;
genesis 84
genesis 85 int ret = 0;
genesis 86 BN_CTX *ctx = NULL;
genesis 87
genesis 88 BIGNUM *x = NULL;
genesis 89 BIGNUM *e = NULL;
genesis 90 BIGNUM *order = NULL;
genesis 91 BIGNUM *sor = NULL;
genesis 92 BIGNUM *eor = NULL;
genesis 93 BIGNUM *field = NULL;
genesis 94 EC_POINT *R = NULL;
genesis 95 EC_POINT *O = NULL;
genesis 96 EC_POINT *Q = NULL;
genesis 97 BIGNUM *rr = NULL;
genesis 98 BIGNUM *zero = NULL;
genesis 99 int n = 0;
genesis 100 int i = recid / 2;
genesis 101
genesis 102 const EC_GROUP *group = EC_KEY_get0_group(eckey);
genesis 103 if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
genesis 104 BN_CTX_start(ctx);
genesis 105 order = BN_CTX_get(ctx);
genesis 106 if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
genesis 107 x = BN_CTX_get(ctx);
genesis 108 if (!BN_copy(x, order)) { ret=-1; goto err; }
genesis 109 if (!BN_mul_word(x, i)) { ret=-1; goto err; }
genesis 110 if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
genesis 111 field = BN_CTX_get(ctx);
genesis 112 if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
genesis 113 if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
genesis 114 if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
genesis 115 if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
genesis 116 if (check)
genesis 117 {
genesis 118 if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
genesis 119 if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
genesis 120 if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
genesis 121 }
genesis 122 if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
genesis 123 n = EC_GROUP_get_degree(group);
genesis 124 e = BN_CTX_get(ctx);
genesis 125 if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
genesis 126 if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
genesis 127 zero = BN_CTX_get(ctx);
genesis 128 if (!BN_zero(zero)) { ret=-1; goto err; }
genesis 129 if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
genesis 130 rr = BN_CTX_get(ctx);
genesis 131 if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
genesis 132 sor = BN_CTX_get(ctx);
genesis 133 if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
genesis 134 eor = BN_CTX_get(ctx);
genesis 135 if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
genesis 136 if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
genesis 137 if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
genesis 138
genesis 139 ret = 1;
genesis 140
genesis 141 err:
genesis 142 if (ctx) {
genesis 143 BN_CTX_end(ctx);
genesis 144 BN_CTX_free(ctx);
genesis 145 }
genesis 146 if (R != NULL) EC_POINT_free(R);
genesis 147 if (O != NULL) EC_POINT_free(O);
genesis 148 if (Q != NULL) EC_POINT_free(Q);
genesis 149 return ret;
genesis 150 }
genesis 151
genesis 152 class key_error : public std::runtime_error
genesis 153 {
genesis 154 public:
genesis 155 explicit key_error(const std::string& str) : std::runtime_error(str) {}
genesis 156 };
genesis 157
genesis 158
genesis 159 // secure_allocator is defined in serialize.h
genesis 160 // CPrivKey is a serialized private key, with all parameters included (279 bytes)
genesis 161 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
genesis 162 // CSecret is a serialization of just the secret parameter (32 bytes)
genesis 163 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
genesis 164
genesis 165 class CKey
genesis 166 {
genesis 167 protected:
genesis 168 EC_KEY* pkey;
genesis 169 bool fSet;
genesis 170
genesis 171 public:
genesis 172 CKey()
genesis 173 {
genesis 174 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 175 if (pkey == NULL)
genesis 176 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
genesis 177 fSet = false;
genesis 178 }
genesis 179
genesis 180 CKey(const CKey& b)
genesis 181 {
genesis 182 pkey = EC_KEY_dup(b.pkey);
genesis 183 if (pkey == NULL)
genesis 184 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
genesis 185 fSet = b.fSet;
genesis 186 }
genesis 187
genesis 188 CKey& operator=(const CKey& b)
genesis 189 {
genesis 190 if (!EC_KEY_copy(pkey, b.pkey))
genesis 191 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
genesis 192 fSet = b.fSet;
genesis 193 return (*this);
genesis 194 }
genesis 195
genesis 196 ~CKey()
genesis 197 {
genesis 198 EC_KEY_free(pkey);
genesis 199 }
genesis 200
genesis 201 bool IsNull() const
genesis 202 {
genesis 203 return !fSet;
genesis 204 }
genesis 205
genesis 206 void MakeNewKey()
genesis 207 {
genesis 208 if (!EC_KEY_generate_key(pkey))
genesis 209 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
genesis 210 fSet = true;
genesis 211 }
genesis 212
genesis 213 bool SetPrivKey(const CPrivKey& vchPrivKey)
genesis 214 {
genesis 215 const unsigned char* pbegin = &vchPrivKey[0];
genesis 216 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
genesis 217 return false;
genesis 218 fSet = true;
genesis 219 return true;
genesis 220 }
genesis 221
genesis 222 bool SetSecret(const CSecret& vchSecret)
genesis 223 {
genesis 224 EC_KEY_free(pkey);
genesis 225 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 226 if (pkey == NULL)
genesis 227 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
genesis 228 if (vchSecret.size() != 32)
genesis 229 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
genesis 230 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
genesis 231 if (bn == NULL)
genesis 232 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
genesis 233 if (!EC_KEY_regenerate_key(pkey,bn))
genesis 234 {
genesis 235 BN_clear_free(bn);
genesis 236 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
genesis 237 }
genesis 238 BN_clear_free(bn);
genesis 239 fSet = true;
genesis 240 return true;
genesis 241 }
genesis 242
genesis 243 CSecret GetSecret() const
genesis 244 {
genesis 245 CSecret vchRet;
genesis 246 vchRet.resize(32);
genesis 247 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
genesis 248 int nBytes = BN_num_bytes(bn);
genesis 249 if (bn == NULL)
genesis 250 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
genesis 251 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
genesis 252 if (n != nBytes)
genesis 253 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
genesis 254 return vchRet;
genesis 255 }
genesis 256
genesis 257 CPrivKey GetPrivKey() const
genesis 258 {
genesis 259 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
genesis 260 if (!nSize)
genesis 261 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
genesis 262 CPrivKey vchPrivKey(nSize, 0);
genesis 263 unsigned char* pbegin = &vchPrivKey[0];
genesis 264 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
genesis 265 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
genesis 266 return vchPrivKey;
genesis 267 }
genesis 268
genesis 269 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
genesis 270 {
genesis 271 const unsigned char* pbegin = &vchPubKey[0];
genesis 272 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
genesis 273 return false;
genesis 274 fSet = true;
genesis 275 return true;
genesis 276 }
genesis 277
genesis 278 std::vector<unsigned char> GetPubKey() const
genesis 279 {
genesis 280 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
genesis 281 if (!nSize)
genesis 282 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
genesis 283 std::vector<unsigned char> vchPubKey(nSize, 0);
genesis 284 unsigned char* pbegin = &vchPubKey[0];
genesis 285 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
genesis 286 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
genesis 287 return vchPubKey;
genesis 288 }
genesis 289
genesis 290 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
genesis 291 {
genesis 292 vchSig.clear();
genesis 293 unsigned char pchSig[10000];
genesis 294 unsigned int nSize = 0;
genesis 295 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
genesis 296 return false;
genesis 297 vchSig.resize(nSize);
genesis 298 memcpy(&vchSig[0], pchSig, nSize);
genesis 299 return true;
genesis 300 }
genesis 301
genesis 302 // create a compact signature (65 bytes), which allows reconstructing the used public key
genesis 303 // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
genesis 304 // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
genesis 305 // 0x1D = second key with even y, 0x1E = second key with odd y
genesis 306 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
genesis 307 {
genesis 308 bool fOk = false;
genesis 309 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
genesis 310 if (sig==NULL)
genesis 311 return false;
genesis 312 vchSig.clear();
genesis 313 vchSig.resize(65,0);
genesis 314 int nBitsR = BN_num_bits(sig->r);
genesis 315 int nBitsS = BN_num_bits(sig->s);
genesis 316 if (nBitsR <= 256 && nBitsS <= 256)
genesis 317 {
genesis 318 int nRecId = -1;
genesis 319 for (int i=0; i<4; i++)
genesis 320 {
genesis 321 CKey keyRec;
genesis 322 keyRec.fSet = true;
genesis 323 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
genesis 324 if (keyRec.GetPubKey() == this->GetPubKey())
genesis 325 {
genesis 326 nRecId = i;
genesis 327 break;
genesis 328 }
genesis 329 }
genesis 330
genesis 331 if (nRecId == -1)
genesis 332 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
genesis 333
genesis 334 vchSig[0] = nRecId+27;
genesis 335 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
genesis 336 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
genesis 337 fOk = true;
genesis 338 }
genesis 339 ECDSA_SIG_free(sig);
genesis 340 return fOk;
genesis 341 }
genesis 342
genesis 343 // reconstruct public key from a compact signature
genesis 344 // This is only slightly more CPU intensive than just verifying it.
genesis 345 // If this function succeeds, the recovered public key is guaranteed to be valid
genesis 346 // (the signature is a valid signature of the given data for that key)
genesis 347 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 348 {
genesis 349 if (vchSig.size() != 65)
genesis 350 return false;
genesis 351 if (vchSig[0]<27 || vchSig[0]>=31)
genesis 352 return false;
genesis 353 ECDSA_SIG *sig = ECDSA_SIG_new();
genesis 354 BN_bin2bn(&vchSig[1],32,sig->r);
genesis 355 BN_bin2bn(&vchSig[33],32,sig->s);
genesis 356
genesis 357 EC_KEY_free(pkey);
genesis 358 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
genesis 359 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
genesis 360 {
genesis 361 fSet = true;
genesis 362 ECDSA_SIG_free(sig);
genesis 363 return true;
genesis 364 }
genesis 365 return false;
genesis 366 }
genesis 367
genesis 368 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 369 {
genesis 370 // -1 = error, 0 = bad sig, 1 = good
genesis 371 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
genesis 372 return false;
genesis 373 return true;
genesis 374 }
genesis 375
genesis 376 // Verify a compact signature
genesis 377 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
genesis 378 {
genesis 379 CKey key;
genesis 380 if (!key.SetCompactSignature(hash, vchSig))
genesis 381 return false;
genesis 382 if (GetPubKey() != key.GetPubKey())
genesis 383 return false;
genesis 384 return true;
genesis 385 }
genesis 386
genesis 387 bool IsValid()
genesis 388 {
genesis 389 if (!fSet)
genesis 390 return false;
genesis 391
genesis 392 CSecret secret = GetSecret();
genesis 393 CKey key2;
genesis 394 key2.SetSecret(secret);
genesis 395 return GetPubKey() == key2.GetPubKey();
genesis 396 }
genesis 397 };
genesis 398
genesis 399 #endif