// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <map>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
-// if check is nonzero, additional checks are performed
+// if check is non-zero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
if (!eckey) return 0;
void CKey::Reset()
{
fCompressedPubKey = false;
+ if (pkey != NULL)
+ EC_KEY_free(pkey);
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
if (pkey == NULL)
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
CKey::CKey()
{
+ pkey = NULL;
Reset();
}
bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
{
const unsigned char* pbegin = &vchPrivKey[0];
- if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
- return false;
- fSet = true;
- return true;
+ if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
+ {
+ // In testing, d2i_ECPrivateKey can return true
+ // but fill in pkey with a key that fails
+ // EC_KEY_check_key, so:
+ if (EC_KEY_check_key(pkey))
+ {
+ fSet = true;
+ return true;
+ }
+ }
+ // If vchPrivKey data is bad d2i_ECPrivateKey() can
+ // leave pkey in a state where calling EC_KEY_free()
+ // crashes. To avoid that, set pkey to NULL and
+ // leak the memory (a leak is better than a crash)
+ pkey = NULL;
+ Reset();
+ return false;
}
bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
return vchPrivKey;
}
-bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
+bool CKey::SetPubKey(const CPubKey& vchPubKey)
{
- const unsigned char* pbegin = &vchPubKey[0];
- if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
- return false;
- fSet = true;
- if (vchPubKey.size() == 33)
- SetCompressedPubKey();
- return true;
+ const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
+ if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
+ {
+ fSet = true;
+ if (vchPubKey.vchPubKey.size() == 33)
+ SetCompressedPubKey();
+ return true;
+ }
+ pkey = NULL;
+ Reset();
+ return false;
}
-std::vector<unsigned char> CKey::GetPubKey() const
+CPubKey CKey::GetPubKey() const
{
int nSize = i2o_ECPublicKey(pkey, NULL);
if (!nSize)
unsigned char* pbegin = &vchPubKey[0];
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
- return vchPubKey;
+ return CPubKey(vchPubKey);
}
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
return false;
+
return true;
}
return false;
if (GetPubKey() != key.GetPubKey())
return false;
+
return true;
}
if (!fSet)
return false;
+ if (!EC_KEY_check_key(pkey))
+ return false;
+
bool fCompr;
CSecret secret = GetSecret(fCompr);
CKey key2;