Bugfix: avoid sub-cent change (lost in fees) whenever possible
[bitcoin.git] / key.h
blob06f88cc9078cd57ce2284a5ea7c567158164c03a
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.
6 // secp160k1
7 // const unsigned int PRIVATE_KEY_SIZE = 192;
8 // const unsigned int PUBLIC_KEY_SIZE = 41;
9 // const unsigned int SIGNATURE_SIZE = 48;
11 // secp192k1
12 // const unsigned int PRIVATE_KEY_SIZE = 222;
13 // const unsigned int PUBLIC_KEY_SIZE = 49;
14 // const unsigned int SIGNATURE_SIZE = 57;
16 // secp224k1
17 // const unsigned int PRIVATE_KEY_SIZE = 250;
18 // const unsigned int PUBLIC_KEY_SIZE = 57;
19 // const unsigned int SIGNATURE_SIZE = 66;
21 // secp256k1:
22 // const unsigned int PRIVATE_KEY_SIZE = 279;
23 // const unsigned int PUBLIC_KEY_SIZE = 65;
24 // const unsigned int SIGNATURE_SIZE = 72;
26 // see www.keylength.com
27 // script supports up to 75 for single byte push
31 class key_error : public std::runtime_error
33 public:
34 explicit key_error(const std::string& str) : std::runtime_error(str) {}
38 // secure_allocator is defined in serialize.h
39 typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
43 class CKey
45 protected:
46 EC_KEY* pkey;
47 bool fSet;
49 public:
50 CKey()
52 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
53 if (pkey == NULL)
54 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
55 fSet = false;
58 CKey(const CKey& b)
60 pkey = EC_KEY_dup(b.pkey);
61 if (pkey == NULL)
62 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
63 fSet = b.fSet;
66 CKey& operator=(const CKey& b)
68 if (!EC_KEY_copy(pkey, b.pkey))
69 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
70 fSet = b.fSet;
71 return (*this);
74 ~CKey()
76 EC_KEY_free(pkey);
79 bool IsNull() const
81 return !fSet;
84 void MakeNewKey()
86 if (!EC_KEY_generate_key(pkey))
87 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
88 fSet = true;
91 bool SetPrivKey(const CPrivKey& vchPrivKey)
93 const unsigned char* pbegin = &vchPrivKey[0];
94 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
95 return false;
96 fSet = true;
97 return true;
100 CPrivKey GetPrivKey() const
102 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
103 if (!nSize)
104 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
105 CPrivKey vchPrivKey(nSize, 0);
106 unsigned char* pbegin = &vchPrivKey[0];
107 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
108 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
109 return vchPrivKey;
112 bool SetPubKey(const vector<unsigned char>& vchPubKey)
114 const unsigned char* pbegin = &vchPubKey[0];
115 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
116 return false;
117 fSet = true;
118 return true;
121 vector<unsigned char> GetPubKey() const
123 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
124 if (!nSize)
125 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
126 vector<unsigned char> vchPubKey(nSize, 0);
127 unsigned char* pbegin = &vchPubKey[0];
128 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
129 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
130 return vchPubKey;
133 bool Sign(uint256 hash, vector<unsigned char>& vchSig)
135 vchSig.clear();
136 unsigned char pchSig[10000];
137 unsigned int nSize = 0;
138 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
139 return false;
140 vchSig.resize(nSize);
141 memcpy(&vchSig[0], pchSig, nSize);
142 return true;
145 bool Verify(uint256 hash, const vector<unsigned char>& vchSig)
147 // -1 = error, 0 = bad sig, 1 = good
148 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
149 return false;
150 return true;
153 static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, vector<unsigned char>& vchSig)
155 CKey key;
156 if (!key.SetPrivKey(vchPrivKey))
157 return false;
158 return key.Sign(hash, vchSig);
161 static bool Verify(const vector<unsigned char>& vchPubKey, uint256 hash, const vector<unsigned char>& vchSig)
163 CKey key;
164 if (!key.SetPubKey(vchPubKey))
165 return false;
166 return key.Verify(hash, vchSig);