1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
10 #include <openssl/ec.h>
11 #include <openssl/ecdsa.h>
12 #include <openssl/obj_mac.h>
14 #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 static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
45 EC_POINT *pub_key = NULL;
49 const EC_GROUP *group = EC_KEY_get0_group(eckey);
51 if ((ctx = BN_CTX_new()) == NULL)
54 pub_key = EC_POINT_new(group);
59 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
62 EC_KEY_set_private_key(eckey,priv_key);
63 EC_KEY_set_public_key(eckey,pub_key);
70 EC_POINT_free(pub_key);
78 class key_error : public std::runtime_error
81 explicit key_error(const std::string& str) : std::runtime_error(str) {}
85 // secure_allocator is defined in serialize.h
86 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
87 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
98 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
100 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
106 pkey = EC_KEY_dup(b.pkey);
108 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
112 CKey& operator=(const CKey& b)
114 if (!EC_KEY_copy(pkey, b.pkey))
115 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
132 if (!EC_KEY_generate_key(pkey))
133 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
137 bool SetPrivKey(const CPrivKey& vchPrivKey)
139 const unsigned char* pbegin = &vchPrivKey[0];
140 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
146 bool SetSecret(const CSecret& vchSecret)
149 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
151 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
152 if (vchSecret.size() != 32)
153 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
154 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
156 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
157 if (!EC_KEY_regenerate_key(pkey,bn))
158 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
164 CSecret GetSecret() const
168 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
169 int nBytes = BN_num_bytes(bn);
171 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
172 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
174 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
178 CPrivKey GetPrivKey() const
180 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
182 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
183 CPrivKey vchPrivKey(nSize, 0);
184 unsigned char* pbegin = &vchPrivKey[0];
185 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
186 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
190 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
192 const unsigned char* pbegin = &vchPubKey[0];
193 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
199 std::vector<unsigned char> GetPubKey() const
201 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
203 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
204 std::vector<unsigned char> vchPubKey(nSize, 0);
205 unsigned char* pbegin = &vchPubKey[0];
206 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
207 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
211 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
214 unsigned char pchSig[10000];
215 unsigned int nSize = 0;
216 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
218 vchSig.resize(nSize);
219 memcpy(&vchSig[0], pchSig, nSize);
223 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
225 // -1 = error, 0 = bad sig, 1 = good
226 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
231 CBitcoinAddress GetAddress() const
233 return CBitcoinAddress(GetPubKey());