// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2011 The Bitcoin developers
+// 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.
#ifndef BITCOIN_KEY_H
protected:
EC_KEY* pkey;
bool fSet;
+ bool fCompressedPubKey;
+
+ void SetCompressedPubKey()
+ {
+ EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
+ fCompressedPubKey = true;
+ }
public:
- CKey()
+
+ void Reset()
{
+ fCompressedPubKey = false;
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
if (pkey == NULL)
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
fSet = false;
}
+ CKey()
+ {
+ Reset();
+ }
+
CKey(const CKey& b)
{
pkey = EC_KEY_dup(b.pkey);
return !fSet;
}
- void MakeNewKey()
+ bool IsCompressed() const
+ {
+ return fCompressedPubKey;
+ }
+
+ void MakeNewKey(bool fCompressed = true)
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
+ if (fCompressed)
+ SetCompressedPubKey();
fSet = true;
}
return true;
}
- bool SetSecret(const CSecret& vchSecret)
+ bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
{
EC_KEY_free(pkey);
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
BN_clear_free(bn);
fSet = true;
+ if (fCompressed || fCompressedPubKey)
+ SetCompressedPubKey();
return true;
}
- CSecret GetSecret() const
+ CSecret GetSecret(bool &fCompressed) const
{
CSecret vchRet;
vchRet.resize(32);
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
if (n != nBytes)
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
+ fCompressed = fCompressedPubKey;
return vchRet;
}
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
return false;
fSet = true;
+ if (vchPubKey.size() == 33)
+ SetCompressedPubKey();
return true;
}
{
CKey keyRec;
keyRec.fSet = true;
+ if (fCompressedPubKey)
+ keyRec.SetCompressedPubKey();
if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
if (keyRec.GetPubKey() == this->GetPubKey())
{
if (nRecId == -1)
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
- vchSig[0] = nRecId+27;
+ vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
fOk = true;
{
if (vchSig.size() != 65)
return false;
- if (vchSig[0]<27 || vchSig[0]>=31)
+ int nV = vchSig[0];
+ if (nV<27 || nV>=35)
return false;
ECDSA_SIG *sig = ECDSA_SIG_new();
BN_bin2bn(&vchSig[1],32,sig->r);
EC_KEY_free(pkey);
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
- if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
+ if (nV >= 31)
+ {
+ SetCompressedPubKey();
+ nV -= 4;
+ }
+ if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
{
fSet = true;
ECDSA_SIG_free(sig);
return false;
return true;
}
+
+ bool IsValid()
+ {
+ if (!fSet)
+ return false;
+
+ bool fCompr;
+ CSecret secret = GetSecret(fCompr);
+ CKey key2;
+ key2.SetSecret(secret, fCompr);
+ return GetPubKey() == key2.GetPubKey();
+ }
};
#endif