Update License in File Headers
[bitcoinplatinum.git] / src / key.h
blobf687f334cee20cda95973818fd8daad05ebdad7b
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 COPYING 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 "allocators.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 /** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
58 class CKey
60 protected:
61 EC_KEY* pkey;
62 bool fSet;
63 bool fCompressedPubKey;
65 void SetCompressedPubKey()
67 EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
68 fCompressedPubKey = true;
71 public:
73 void Reset()
75 fCompressedPubKey = false;
76 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
77 if (pkey == NULL)
78 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
79 fSet = false;
82 CKey()
84 Reset();
87 CKey(const CKey& b)
89 pkey = EC_KEY_dup(b.pkey);
90 if (pkey == NULL)
91 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
92 fSet = b.fSet;
95 CKey& operator=(const CKey& b)
97 if (!EC_KEY_copy(pkey, b.pkey))
98 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
99 fSet = b.fSet;
100 return (*this);
103 ~CKey()
105 EC_KEY_free(pkey);
108 bool IsNull() const
110 return !fSet;
113 bool IsCompressed() const
115 return fCompressedPubKey;
118 void MakeNewKey(bool fCompressed)
120 if (!EC_KEY_generate_key(pkey))
121 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
122 if (fCompressed)
123 SetCompressedPubKey();
124 fSet = true;
127 bool SetPrivKey(const CPrivKey& vchPrivKey)
129 const unsigned char* pbegin = &vchPrivKey[0];
130 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
131 return false;
132 fSet = true;
133 return true;
136 bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
138 EC_KEY_free(pkey);
139 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
140 if (pkey == NULL)
141 throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
142 if (vchSecret.size() != 32)
143 throw key_error("CKey::SetSecret() : secret must be 32 bytes");
144 BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
145 if (bn == NULL)
146 throw key_error("CKey::SetSecret() : BN_bin2bn failed");
147 if (!EC_KEY_regenerate_key(pkey,bn))
149 BN_clear_free(bn);
150 throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
152 BN_clear_free(bn);
153 fSet = true;
154 if (fCompressed || fCompressedPubKey)
155 SetCompressedPubKey();
156 return true;
159 CSecret GetSecret(bool &fCompressed) const
161 CSecret vchRet;
162 vchRet.resize(32);
163 const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
164 int nBytes = BN_num_bytes(bn);
165 if (bn == NULL)
166 throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
167 int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
168 if (n != nBytes)
169 throw key_error("CKey::GetSecret(): BN_bn2bin failed");
170 fCompressed = fCompressedPubKey;
171 return vchRet;
174 CPrivKey GetPrivKey() const
176 int nSize = i2d_ECPrivateKey(pkey, NULL);
177 if (!nSize)
178 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
179 CPrivKey vchPrivKey(nSize, 0);
180 unsigned char* pbegin = &vchPrivKey[0];
181 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
182 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
183 return vchPrivKey;
186 bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
188 const unsigned char* pbegin = &vchPubKey[0];
189 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
190 return false;
191 fSet = true;
192 if (vchPubKey.size() == 33)
193 SetCompressedPubKey();
194 return true;
197 std::vector<unsigned char> GetPubKey() const
199 int nSize = i2o_ECPublicKey(pkey, NULL);
200 if (!nSize)
201 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
202 std::vector<unsigned char> vchPubKey(nSize, 0);
203 unsigned char* pbegin = &vchPubKey[0];
204 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
205 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
206 return vchPubKey;
209 bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
211 unsigned int nSize = ECDSA_size(pkey);
212 vchSig.resize(nSize); // Make sure it is big enough
213 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
215 vchSig.clear();
216 return false;
218 vchSig.resize(nSize); // Shrink to fit actual size
219 return true;
222 // create a compact signature (65 bytes), which allows reconstructing the used public key
223 // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
224 // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
225 // 0x1D = second key with even y, 0x1E = second key with odd y
226 bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
228 bool fOk = false;
229 ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
230 if (sig==NULL)
231 return false;
232 vchSig.clear();
233 vchSig.resize(65,0);
234 int nBitsR = BN_num_bits(sig->r);
235 int nBitsS = BN_num_bits(sig->s);
236 if (nBitsR <= 256 && nBitsS <= 256)
238 int nRecId = -1;
239 for (int i=0; i<4; i++)
241 CKey keyRec;
242 keyRec.fSet = true;
243 if (fCompressedPubKey)
244 keyRec.SetCompressedPubKey();
245 if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
246 if (keyRec.GetPubKey() == this->GetPubKey())
248 nRecId = i;
249 break;
253 if (nRecId == -1)
254 throw key_error("CKey::SignCompact() : unable to construct recoverable key");
256 vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
257 BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
258 BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
259 fOk = true;
261 ECDSA_SIG_free(sig);
262 return fOk;
265 // reconstruct public key from a compact signature
266 // This is only slightly more CPU intensive than just verifying it.
267 // If this function succeeds, the recovered public key is guaranteed to be valid
268 // (the signature is a valid signature of the given data for that key)
269 bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
271 if (vchSig.size() != 65)
272 return false;
273 int nV = vchSig[0];
274 if (nV<27 || nV>=35)
275 return false;
276 ECDSA_SIG *sig = ECDSA_SIG_new();
277 BN_bin2bn(&vchSig[1],32,sig->r);
278 BN_bin2bn(&vchSig[33],32,sig->s);
280 EC_KEY_free(pkey);
281 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
282 if (nV >= 31)
284 SetCompressedPubKey();
285 nV -= 4;
287 if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
289 fSet = true;
290 ECDSA_SIG_free(sig);
291 return true;
293 return false;
296 bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
298 // -1 = error, 0 = bad sig, 1 = good
299 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
300 return false;
301 return true;
304 // Verify a compact signature
305 bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
307 CKey key;
308 if (!key.SetCompactSignature(hash, vchSig))
309 return false;
310 if (GetPubKey() != key.GetPubKey())
311 return false;
312 return true;
315 bool IsValid()
317 if (!fSet)
318 return false;
320 bool fCompr;
321 CSecret secret = GetSecret(fCompr);
322 CKey key2;
323 key2.SetSecret(secret, fCompr);
324 return GetPubKey() == key2.GetPubKey();
328 #endif