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"
20 // const unsigned int PRIVATE_KEY_SIZE = 192;
21 // const unsigned int PUBLIC_KEY_SIZE = 41;
22 // const unsigned int SIGNATURE_SIZE = 48;
25 // const unsigned int PRIVATE_KEY_SIZE = 222;
26 // const unsigned int PUBLIC_KEY_SIZE = 49;
27 // const unsigned int SIGNATURE_SIZE = 57;
30 // const unsigned int PRIVATE_KEY_SIZE = 250;
31 // const unsigned int PUBLIC_KEY_SIZE = 57;
32 // const unsigned int SIGNATURE_SIZE = 66;
35 // const unsigned int PRIVATE_KEY_SIZE = 279;
36 // const unsigned int PUBLIC_KEY_SIZE = 65;
37 // const unsigned int SIGNATURE_SIZE = 72;
39 // see www.keylength.com
40 // script supports up to 75 for single byte push
42 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
46 EC_POINT *pub_key = NULL;
50 const EC_GROUP *group = EC_KEY_get0_group(eckey);
52 if ((ctx = BN_CTX_new()) == NULL)
55 pub_key = EC_POINT_new(group);
60 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
63 EC_KEY_set_private_key(eckey,priv_key);
64 EC_KEY_set_public_key(eckey,pub_key);
71 EC_POINT_free(pub_key);
79 class key_error : public std::runtime_error
82 explicit key_error(const std::string& str) : std::runtime_error(str) {}
86 // secure_allocator is defined in serialize.h
87 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
88 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
99 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
101 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
107 pkey = EC_KEY_dup(b.pkey);
109 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
113 CKey& operator=(const CKey& b)
115 if (!EC_KEY_copy(pkey, b.pkey))
116 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
133 if (!EC_KEY_generate_key(pkey))
134 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
138 bool SetPrivKey(const CPrivKey& vchPrivKey)
140 const unsigned char* pbegin = &vchPrivKey[0];
141 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
147 bool SetSecret(const CSecret& vchSecret)
150 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
152 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
153 if (vchSecret.size() != 32)
154 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
155 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
157 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
158 if (!EC_KEY_regenerate_key(pkey,bn))
159 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
165 CSecret GetSecret() const
169 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
170 int nBytes = BN_num_bytes(bn);
172 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
173 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
175 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
179 CPrivKey GetPrivKey() const
181 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
183 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
184 CPrivKey vchPrivKey(nSize, 0);
185 unsigned char* pbegin = &vchPrivKey[0];
186 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
187 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
191 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
193 const unsigned char* pbegin = &vchPubKey[0];
194 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
200 std::vector<unsigned char> GetPubKey() const
202 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
204 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
205 std::vector<unsigned char> vchPubKey(nSize, 0);
206 unsigned char* pbegin = &vchPubKey[0];
207 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
208 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
212 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
215 unsigned char pchSig[10000];
216 unsigned int nSize = 0;
217 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
219 vchSig.resize(nSize);
220 memcpy(&vchSig[0], pchSig, nSize);
224 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
226 // -1 = error, 0 = bad sig, 1 = good
227 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
232 CBitcoinAddress GetAddress() const
234 return CBitcoinAddress(GetPubKey());