1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
11 #include <openssl/ec.h>
12 #include <openssl/ecdsa.h>
13 #include <openssl/obj_mac.h>
15 #include "serialize.h"
19 // const unsigned int PRIVATE_KEY_SIZE = 192;
20 // const unsigned int PUBLIC_KEY_SIZE = 41;
21 // const unsigned int SIGNATURE_SIZE = 48;
24 // const unsigned int PRIVATE_KEY_SIZE = 222;
25 // const unsigned int PUBLIC_KEY_SIZE = 49;
26 // const unsigned int SIGNATURE_SIZE = 57;
29 // const unsigned int PRIVATE_KEY_SIZE = 250;
30 // const unsigned int PUBLIC_KEY_SIZE = 57;
31 // const unsigned int SIGNATURE_SIZE = 66;
34 // const unsigned int PRIVATE_KEY_SIZE = 279;
35 // const unsigned int PUBLIC_KEY_SIZE = 65;
36 // const unsigned int SIGNATURE_SIZE = 72;
38 // see www.keylength.com
39 // script supports up to 75 for single byte push
41 int extern EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key);
42 int extern ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check);
44 class key_error : public std::runtime_error
47 explicit key_error(const std::string& str) : std::runtime_error(str) {}
51 // secure_allocator is defined in serialize.h
52 // CPrivKey is a serialized private key, with all parameters included (279 bytes)
53 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
54 // CSecret is a serialization of just the secret parameter (32 bytes)
55 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
66 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
68 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
74 pkey = EC_KEY_dup(b.pkey);
76 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
80 CKey& operator=(const CKey& b)
82 if (!EC_KEY_copy(pkey, b.pkey))
83 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
100 if (!EC_KEY_generate_key(pkey))
101 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
105 bool SetPrivKey(const CPrivKey& vchPrivKey)
107 const unsigned char* pbegin = &vchPrivKey[0];
108 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
114 bool SetSecret(const CSecret& vchSecret)
117 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
119 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
120 if (vchSecret.size() != 32)
121 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
122 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
124 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
125 if (!EC_KEY_regenerate_key(pkey,bn))
126 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
132 CSecret GetSecret() const
136 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
137 int nBytes = BN_num_bytes(bn);
139 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
140 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
142 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
146 CPrivKey GetPrivKey() const
148 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
150 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
151 CPrivKey vchPrivKey(nSize, 0);
152 unsigned char* pbegin = &vchPrivKey[0];
153 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
154 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
158 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
160 const unsigned char* pbegin = &vchPubKey[0];
161 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
167 std::vector<unsigned char> GetPubKey() const
169 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
171 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
172 std::vector<unsigned char> vchPubKey(nSize, 0);
173 unsigned char* pbegin = &vchPubKey[0];
174 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
175 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
179 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
181 unsigned int nSize = ECDSA_size(pkey);
182 vchSig.resize(nSize); // Make sure it is big enough
183 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
188 vchSig.resize(nSize); // Shrink to fit actual size
192 // create a compact signature (65 bytes), which allows reconstructing the used public key
193 // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
194 // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
195 // 0x1D = second key with even y, 0x1E = second key with odd y
196 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
199 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
204 int nBitsR = BN_num_bits(sig->r);
205 int nBitsS = BN_num_bits(sig->s);
206 if (nBitsR <= 256 && nBitsS <= 256)
209 for (int i=0; i<4; i++)
213 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
214 if (keyRec.GetPubKey() == this->GetPubKey())
222 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
224 vchSig[0] = nRecId+27;
225 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
226 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
233 // reconstruct public key from a compact signature
234 // This is only slightly more CPU intensive than just verifying it.
235 // If this function succeeds, the recovered public key is guaranteed to be valid
236 // (the signature is a valid signature of the given data for that key)
237 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
239 if (vchSig.size() != 65)
241 if (vchSig[0]<27 || vchSig[0]>=31)
243 ECDSA_SIG *sig = ECDSA_SIG_new();
244 BN_bin2bn(&vchSig[1],32,sig->r);
245 BN_bin2bn(&vchSig[33],32,sig->s);
248 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
249 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
258 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
260 // -1 = error, 0 = bad sig, 1 = good
261 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
266 // Verify a compact signature
267 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
270 if (!key.SetCompactSignature(hash, vchSig))
272 if (GetPubKey() != key.GetPubKey())