Add option "-splash" so we can disable the splash screen.
[bitcoinplatinum.git] / src / key.h
blob4058f115fdd461a2a36db4909e7c1ba8e4e55576
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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.
5 #ifndef BITCOIN_KEY_H
6 #define BITCOIN_KEY_H
8 #include <stdexcept>
9 #include <vector>
11 #include <openssl/ec.h>
12 #include <openssl/ecdsa.h>
13 #include <openssl/obj_mac.h>
15 #include "serialize.h"
16 #include "uint256.h"
18 // secp160k1
19 // const unsigned int PRIVATE_KEY_SIZE = 192;
20 // const unsigned int PUBLIC_KEY_SIZE = 41;
21 // const unsigned int SIGNATURE_SIZE = 48;
23 // secp192k1
24 // const unsigned int PRIVATE_KEY_SIZE = 222;
25 // const unsigned int PUBLIC_KEY_SIZE = 49;
26 // const unsigned int SIGNATURE_SIZE = 57;
28 // secp224k1
29 // const unsigned int PRIVATE_KEY_SIZE = 250;
30 // const unsigned int PUBLIC_KEY_SIZE = 57;
31 // const unsigned int SIGNATURE_SIZE = 66;
33 // secp256k1:
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
46 public:
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;
57 class CKey
59 protected:
60 EC_KEY* pkey;
61 bool fSet;
62 bool fCompressedPubKey;
64 void SetCompressedPubKey()
66 EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
67 fCompressedPubKey = true;
70 public:
72 void Reset()
74 fCompressedPubKey = false;
75 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
76 if (pkey == NULL)
77 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
78 fSet = false;
81 CKey()
83 Reset();
86 CKey(const CKey& b)
88 pkey = EC_KEY_dup(b.pkey);
89 if (pkey == NULL)
90 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
91 fSet = b.fSet;
94 CKey& operator=(const CKey& b)
96 if (!EC_KEY_copy(pkey, b.pkey))
97 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
98 fSet = b.fSet;
99 return (*this);
102 ~CKey()
104 EC_KEY_free(pkey);
107 bool IsNull() const
109 return !fSet;
112 bool IsCompressed() const
114 return fCompressedPubKey;
117 void MakeNewKey(bool fCompressed)
119 if (!EC_KEY_generate_key(pkey))
120 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
121 if (fCompressed)
122 SetCompressedPubKey();
123 fSet = true;
126 bool SetPrivKey(const CPrivKey& vchPrivKey)
128 const unsigned char* pbegin = &vchPrivKey[0];
129 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
130 return false;
131 fSet = true;
132 return true;
135 bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
137 EC_KEY_free(pkey);
138 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
139 if (pkey == NULL)
140 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
141 if (vchSecret.size() != 32)
142 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
143 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
144 if (bn == NULL)
145 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
146 if (!EC_KEY_regenerate_key(pkey,bn))
148 BN_clear_free(bn);
149 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
151 BN_clear_free(bn);
152 fSet = true;
153 if (fCompressed || fCompressedPubKey)
154 SetCompressedPubKey();
155 return true;
158 CSecret GetSecret(bool &fCompressed) const
160 CSecret vchRet;
161 vchRet.resize(32);
162 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
163 int nBytes = BN_num_bytes(bn);
164 if (bn == NULL)
165 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
166 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
167 if (n != nBytes)
168 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
169 fCompressed = fCompressedPubKey;
170 return vchRet;
173 CPrivKey GetPrivKey() const
175 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
176 if (!nSize)
177 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
178 CPrivKey vchPrivKey(nSize, 0);
179 unsigned char* pbegin = &vchPrivKey[0];
180 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
181 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
182 return vchPrivKey;
185 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
187 const unsigned char* pbegin = &vchPubKey[0];
188 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
189 return false;
190 fSet = true;
191 if (vchPubKey.size() == 33)
192 SetCompressedPubKey();
193 return true;
196 std::vector<unsigned char> GetPubKey() const
198 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
199 if (!nSize)
200 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
201 std::vector<unsigned char> vchPubKey(nSize, 0);
202 unsigned char* pbegin = &vchPubKey[0];
203 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
204 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
205 return vchPubKey;
208 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
210 unsigned int nSize = ECDSA_size(pkey);
211 vchSig.resize(nSize); // Make sure it is big enough
212 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
214 vchSig.clear();
215 return false;
217 vchSig.resize(nSize); // Shrink to fit actual size
218 return true;
221 // create a compact signature (65 bytes), which allows reconstructing the used public key
222 // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
223 // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
224 // 0x1D = second key with even y, 0x1E = second key with odd y
225 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
227 bool fOk = false;
228 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
229 if (sig==NULL)
230 return false;
231 vchSig.clear();
232 vchSig.resize(65,0);
233 int nBitsR = BN_num_bits(sig->r);
234 int nBitsS = BN_num_bits(sig->s);
235 if (nBitsR <= 256 && nBitsS <= 256)
237 int nRecId = -1;
238 for (int i=0; i<4; i++)
240 CKey keyRec;
241 keyRec.fSet = true;
242 if (fCompressedPubKey)
243 keyRec.SetCompressedPubKey();
244 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
245 if (keyRec.GetPubKey() == this->GetPubKey())
247 nRecId = i;
248 break;
252 if (nRecId == -1)
253 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
255 vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
256 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
257 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
258 fOk = true;
260 ECDSA_SIG_free(sig);
261 return fOk;
264 // reconstruct public key from a compact signature
265 // This is only slightly more CPU intensive than just verifying it.
266 // If this function succeeds, the recovered public key is guaranteed to be valid
267 // (the signature is a valid signature of the given data for that key)
268 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
270 if (vchSig.size() != 65)
271 return false;
272 int nV = vchSig[0];
273 if (nV<27 || nV>=35)
274 return false;
275 ECDSA_SIG *sig = ECDSA_SIG_new();
276 BN_bin2bn(&vchSig[1],32,sig->r);
277 BN_bin2bn(&vchSig[33],32,sig->s);
279 EC_KEY_free(pkey);
280 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
281 if (nV >= 31)
283 SetCompressedPubKey();
284 nV -= 4;
286 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
288 fSet = true;
289 ECDSA_SIG_free(sig);
290 return true;
292 return false;
295 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
297 // -1 = error, 0 = bad sig, 1 = good
298 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
299 return false;
300 return true;
303 // Verify a compact signature
304 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
306 CKey key;
307 if (!key.SetCompactSignature(hash, vchSig))
308 return false;
309 if (GetPubKey() != key.GetPubKey())
310 return false;
311 return true;
314 bool IsValid()
316 if (!fSet)
317 return false;
319 bool fCompr;
320 CSecret secret = GetSecret(fCompr);
321 CKey key2;
322 key2.SetSecret(secret, fCompr);
323 return GetPubKey() == key2.GetPubKey();
327 #endif