Move signature verification functions to CPubKey.
authorCryptoManiac <balthazar@yandex.ru>
Tue, 29 Mar 2016 01:22:25 +0000 (04:22 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Tue, 29 Mar 2016 01:22:25 +0000 (04:22 +0300)
21 files changed:
src/alert.cpp
src/bitcoinrpc.cpp
src/bitcoinrpc.h
src/checkpoints.cpp
src/key.cpp
src/key.h
src/keystore.cpp
src/keystore.h
src/main.cpp
src/qt/multisigaddressentry.cpp
src/qt/multisigdialog.cpp
src/qt/signverifymessagedialog.cpp
src/rpcdump.cpp
src/rpcrawtransaction.cpp
src/rpcwallet.cpp
src/script.cpp
src/script.h
src/wallet.cpp
src/wallet.h
src/walletdb.cpp
src/walletdb.h

index 121bd1e..65927ed 100644 (file)
@@ -149,9 +149,8 @@ bool CAlert::RelayTo(CNode* pnode) const
 
 bool CAlert::CheckSignature() const
 {
-    CKey key;
-    if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
-        return error("CAlert::CheckSignature() : SetPubKey failed");
+    CPubKey key;
+    key.Set(ParseHex(fTestNet ? pszTestKey : pszMainKey));
     if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
         return error("CAlert::CheckSignature() : verify signature failed");
 
index b555f0b..bd1c1f4 100644 (file)
@@ -297,6 +297,7 @@ static const CRPCCommand vRPCCommands[] =
     { "submitblock",            &submitblock,            false,  false },
     { "listsinceblock",         &listsinceblock,         false,  false },
     { "dumpprivkey",            &dumpprivkey,            false,  false },
+    { "dumppem",                &dumppem,                true,   false },
     { "dumpwallet",             &dumpwallet,             true,   false },
     { "importwallet",           &importwallet,           false,  false },
     { "importprivkey",          &importprivkey,          false,  false },
index 5befb76..3c9106b 100644 (file)
@@ -212,6 +212,7 @@ extern json_spirit::Value adjustmalleablepubkey(const json_spirit::Array& params
 extern json_spirit::Value listmalleableviews(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value dumpmalleablekey(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value importmalleablekey(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value dumppem(const json_spirit::Array& params, bool fHelp);
 
 extern json_spirit::Value encryptdata(const json_spirit::Array& params, bool fHelp); // in rpccrypt.cpp
 extern json_spirit::Value decryptdata(const json_spirit::Array& params, bool fHelp);
index 54f5790..c6fb487 100644 (file)
@@ -396,9 +396,7 @@ std::string CSyncCheckpoint::strMasterPrivKey = "";
 // ppcoin: verify signature of sync-checkpoint message
 bool CSyncCheckpoint::CheckSignature()
 {
-    CKey key;
-    if (!key.SetPubKey(ParseHex(CSyncCheckpoint::strMasterPubKey)))
-        return error("CSyncCheckpoint::CheckSignature() : SetPubKey failed");
+    CPubKey key(ParseHex(CSyncCheckpoint::strMasterPubKey));
     if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
         return error("CSyncCheckpoint::CheckSignature() : verify signature failed");
 
index 546d95f..20ea691 100644 (file)
@@ -5,6 +5,7 @@
 #include <map>
 
 #include <openssl/ecdsa.h>
+#include <openssl/evp.h>
 #include <openssl/obj_mac.h>
 
 #include "key.h"
@@ -164,8 +165,6 @@ const unsigned char vchMaxModHalfOrder[32] = {
 
 const unsigned char *vchZero = NULL;
 
-
-
 void CKey::SetCompressedPubKey()
 {
     EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
@@ -174,13 +173,12 @@ void CKey::SetCompressedPubKey()
 
 void CKey::Reset()
 {
-    fCompressedPubKey = false;
+    fCompressedPubKey = fSet = 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");
-    fSet = false;
 }
 
 CKey::CKey()
@@ -217,7 +215,8 @@ CKey& CKey::operator=(const CKey& b)
 
 CKey::~CKey()
 {
-    EC_KEY_free(pkey);
+    if (pkey != NULL)
+        EC_KEY_free(pkey);
 }
 
 bool CKey::IsNull() const
@@ -235,7 +234,7 @@ bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
         CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
 }
 
-bool CKey::ReserealizeSignature(std::vector<unsigned char>& vchSig)
+bool CPubKey::ReserealizeSignature(std::vector<unsigned char>& vchSig)
 {
     if (vchSig.empty())
         return false;
@@ -299,6 +298,7 @@ bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
     pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
     if (pkey == NULL)
         throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
+
     if (vchSecret.size() != 32)
         throw key_error("CKey::SetSecret() : secret must be 32 bytes");
     BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
@@ -331,6 +331,37 @@ CSecret CKey::GetSecret(bool &fCompressed) const
     return vchRet;
 }
 
+bool CKey::WritePEM(BIO *streamObj, const SecureString &strPassKey) const // dumppem 4KJLA99FyqMMhjjDe7KnRXK4sjtv9cCtNS /tmp/test.pem 123
+{
+    EVP_PKEY *evpKey = EVP_PKEY_new();
+    bool result = true;
+
+    do
+    {
+        if (!EVP_PKEY_assign_EC_KEY(evpKey, pkey))
+        {
+            result = error("CKey::WritePEM() : Error initializing EVP_PKEY instance.");
+            break;
+        }
+
+        if(!PEM_write_bio_PKCS8PrivateKey(streamObj, evpKey, EVP_aes_256_cbc(), (char *)&strPassKey[0], strPassKey.size(), NULL, NULL))
+        {
+            result = error("CKey::WritePEM() : Error writing private key data to stream object");
+            break;
+        }
+
+        if(!PEM_write_bio_PUBKEY(streamObj, evpKey))
+        {
+            result = error("CKey::WritePEM() : Error writing public key data to stream object");
+            break;
+        }
+    }
+    while(false);
+
+    EVP_PKEY_free(evpKey);
+    return result;
+}
+
 CSecret CKey::GetSecret() const
 {
     bool fCompressed;
@@ -349,21 +380,6 @@ CPrivKey CKey::GetPrivKey() const
     return vchPrivKey;
 }
 
-bool CKey::SetPubKey(const CPubKey& vchPubKey)
-{
-    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;
-}
-
 CPubKey CKey::GetPubKey() const
 {
     int nSize = i2o_ECPublicKey(pkey, NULL);
@@ -462,7 +478,7 @@ bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
 // This is only slightly more CPU intensive than just verifying it.
 // If this function succeeds, the recovered public key is guaranteed to be valid
 // (the signature is a valid signature of the given data for that key)
-bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
+bool CPubKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
 {
     if (vchSig.size() != 65)
         return false;
@@ -473,28 +489,46 @@ bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& v
     BN_bin2bn(&vchSig[1],32,sig->r);
     BN_bin2bn(&vchSig[33],32,sig->s);
 
-    EC_KEY_free(pkey);
-    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+    EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
     if (nV >= 31)
     {
-        SetCompressedPubKey();
         nV -= 4;
+        EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
     }
-    if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
+
+    do
     {
-        fSet = true;
+        if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) != 1)
+            break;
         ECDSA_SIG_free(sig);
-        return true;
-    }
+
+        int nSize = i2o_ECPublicKey(pkey, NULL);
+        if (!nSize)
+            break;
+        std::vector<unsigned char> vchPubKey(nSize, 0);
+        unsigned char* pbegin = &vchPubKey[0];
+        if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
+            break;
+        Set(vchPubKey.begin(), vchPubKey.end());
+        return IsValid();
+
+    } while (false);
+
     ECDSA_SIG_free(sig);
+    Invalidate();
     return false;
 }
 
-bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
+bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const
 {
-    if (vchSig.empty())
+    if (vchSig.empty() || !IsValid())
         return false;
 
+    const unsigned char* pbegin = &vbytes[0];
+    EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+    if (!o2i_ECPublicKey(&pkey, &pbegin, size()))
+        return false; // Unable to parse public key
+
     // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
     unsigned char *norm_der = NULL;
     ECDSA_SIG *norm_sig = ECDSA_SIG_new();
@@ -522,14 +556,13 @@ bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
     return ret;
 }
 
-bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
+bool CPubKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
 {
-    CKey key;
+    CPubKey key;
     if (!key.SetCompactSignature(hash, vchSig))
         return false;
-    if (GetPubKey() != key.GetPubKey())
+    if ((*this) != key)
         return false;
-
     return true;
 }
 
@@ -545,6 +578,7 @@ bool CKey::IsValid()
     CSecret secret = GetSecret(fCompr);
     CKey key2;
     key2.SetSecret(secret, fCompr);
+
     return GetPubKey() == key2.GetPubKey();
 }
 
@@ -604,9 +638,10 @@ bool CPoint::setBytes(const std::vector<unsigned char> &vchBytes)
 }
 
 // Initialize from octets stream
-bool CPoint::setPubKey(const CPubKey &vchPubKey)
+bool CPoint::setPubKey(const CPubKey &key)
 {
-    return setBytes(vchPubKey.Raw());
+    std::vector<uint8_t> vchPubKey(key.begin(), key.end());
+    return setBytes(vchPubKey);
 }
 
 // Serialize to octets stream
@@ -824,7 +859,7 @@ bool CMalleableKey::SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSe
 CMalleablePubKey CMalleableKey::GetMalleablePubKey() const
 {
     CKey L(vchSecretL), H(vchSecretH);
-    return CMalleablePubKey(L.GetPubKey().Raw(), H.GetPubKey().Raw());
+    return CMalleablePubKey(L.GetPubKey(), H.GetPubKey());
 }
 
 // Check ownership
@@ -851,7 +886,7 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     }
 
     CKey H(vchSecretH);
-    std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
+    CPubKey vchPubKeyH = H.GetPubKey();
 
     CPoint point_H;
     if (!point_H.setPubKey(vchPubKeyH)) {
@@ -928,7 +963,7 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     }
 
     CKey H(vchSecretH);
-    std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
+    CPubKey vchPubKeyH = H.GetPubKey();
 
     CPoint point_H;
     if (!point_H.setPubKey(vchPubKeyH)) {
@@ -1040,7 +1075,7 @@ CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
     vchSecretL = b.vchSecretL;
 
     CKey H(b.vchSecretH);
-    vchPubKeyH = H.GetPubKey().Raw();
+    vchPubKeyH = H.GetPubKey();
 }
 
 CMalleableKeyView::CMalleableKeyView(const CMalleableKeyView &b)
@@ -1054,7 +1089,7 @@ CMalleableKeyView& CMalleableKeyView::operator=(const CMalleableKey &b)
     vchSecretL = b.vchSecretL;
 
     CKey H(b.vchSecretH);
-    vchPubKeyH = H.GetPubKey().Raw();
+    vchPubKeyH = H.GetPubKey();
 
     return (*this);
 }
@@ -1184,18 +1219,15 @@ bool CMalleableKeyView::IsValid() const
 
 void CPubKey::EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted)
 {
-    CKey key;
-    key.SetPubKey(*this);
-
-    key.EncryptData(data, encrypted);
-}
-
-void CKey::EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted)
-{
     ies_ctx_t *ctx;
     char error[1024] = "Unknown error";
     cryptogram_t *cryptogram;
 
+    const unsigned char* pbegin = &vbytes[0];
+    EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+    if (!o2i_ECPublicKey(&pkey, &pbegin, size()))
+        throw key_error("Unable to parse EC key");
+
     ctx = create_context(pkey);
     if (!EC_KEY_get0_public_key(ctx->user_key))
         throw key_error("Given EC key is not public key");
index 2d8e618..2489dfc 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -62,55 +62,162 @@ public:
     CScriptID(const uint160 &in) : uint160(in) { }
 };
 
-/** An encapsulated public key. */
-class CPubKey {
+/** An encapsulated OpenSSL Elliptic Curve key (public) */
+class CPubKey
+{
 private:
-    std::vector<unsigned char> vchPubKey;
-    friend class CKey;
+
+    /**
+     * Just store the serialized data.
+     * Its length can very cheaply be computed from the first byte.
+     */
+    unsigned char vbytes[65];
+
+    //! Compute the length of a pubkey with a given first byte.
+    unsigned int static GetLen(unsigned char chHeader)
+    {
+        if (chHeader == 2 || chHeader == 3)
+            return 33;
+        if (chHeader == 4 || chHeader == 6 || chHeader == 7)
+            return 65;
+        return 0;
+    }
+
+    // Set this key data to be invalid
+    void Invalidate()
+    {
+        vbytes[0] = 0xFF;
+    }
 
 public:
-    CPubKey() { }
-    CPubKey(const std::vector<unsigned char> &vchPubKeyIn) : vchPubKey(vchPubKeyIn) { }
-    friend bool operator==(const CPubKey &a, const CPubKey &b) { return a.vchPubKey == b.vchPubKey; }
-    friend bool operator!=(const CPubKey &a, const CPubKey &b) { return a.vchPubKey != b.vchPubKey; }
-    friend bool operator<(const CPubKey &a, const CPubKey &b) { return a.vchPubKey < b.vchPubKey; }
+    // Construct an invalid public key.
+    CPubKey()
+    {
+        Invalidate();
+    }
 
-    IMPLEMENT_SERIALIZE(
-        READWRITE(vchPubKey);
-    )
+    // Initialize a public key using begin/end iterators to byte data.
+    template <typename T>
+    void Set(const T pbegin, const T pend)
+    {
+        int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
+        if (len && len == (pend - pbegin))
+            memcpy(vbytes, (unsigned char*)&pbegin[0], len);
+        else
+            Invalidate();
+    }
 
-    CKeyID GetID() const {
-        return CKeyID(Hash160(vchPubKey));
+    void Set(const std::vector<unsigned char>& vch)
+    {
+        Set(vch.begin(), vch.end());
     }
 
-    uint256 GetHash() const {
-        return Hash(vchPubKey.begin(), vchPubKey.end());
+    template <typename T>
+    CPubKey(const T pbegin, const T pend)
+    {
+        Set(pbegin, pend);
     }
 
-    bool IsValid() const {
-        return vchPubKey.size() == 33 || vchPubKey.size() == 65;
+    CPubKey(const std::vector<unsigned char>& vch)
+    {
+        Set(vch.begin(), vch.end());
     }
 
-    bool IsCompressed() const {
-        return vchPubKey.size() == 33;
+    // Read-only vector-like interface to the data.
+    unsigned int size() const { return GetLen(vbytes[0]); }
+    const unsigned char* begin() const { return vbytes; }
+    const unsigned char* end() const { return vbytes + size(); }
+    const unsigned char& operator[](unsigned int pos) const { return vbytes[pos]; }
+
+    friend bool operator==(const CPubKey& a, const CPubKey& b) { return a.vbytes[0] == b.vbytes[0] && memcmp(a.vbytes, b.vbytes, a.size()) == 0; }
+    friend bool operator!=(const CPubKey& a, const CPubKey& b) { return !(a == b); }
+    friend bool operator<(const CPubKey& a, const CPubKey& b)  { return a.vbytes[0] < b.vbytes[0] || (a.vbytes[0] == b.vbytes[0] && memcmp(a.vbytes, b.vbytes, a.size()) < 0); }
+
+    //! Implement serialization, as if this was a byte vector.
+    unsigned int GetSerializeSize(int nType, int nVersion) const
+    {
+        return size() + 1;
+    }
+    template <typename Stream>
+    void Serialize(Stream& s, int nType, int nVersion) const
+    {
+        unsigned int len = size();
+        ::WriteCompactSize(s, len);
+        s.write((char*)vbytes, len);
+    }
+    template <typename Stream>
+    void Unserialize(Stream& s, int nType, int nVersion)
+    {
+        unsigned int len = ::ReadCompactSize(s);
+        if (len <= 65) {
+            s.read((char*)vbytes, len);
+        } else {
+            // invalid pubkey, skip available data
+            char dummy;
+            while (len--)
+                s.read(&dummy, 1);
+            Invalidate();
+        }
     }
 
-    std::vector<unsigned char> Raw() const {
-        return vchPubKey;
+    CKeyID GetID() const
+    {
+        return CKeyID(Hash160(vbytes, vbytes + size()));
     }
 
+    uint256 GetHash() const
+    {
+        return Hash(vbytes, vbytes + size());
+    }
+
+    /*
+     * Check syntactic correctness.
+     *
+     * Note that this is consensus critical as CheckSig() calls it!
+     */
+    bool IsValid() const
+    {
+        return size() > 0;
+    }
+
+    //! fully validate whether this is a valid public key (more expensive than IsValid())
+    bool IsFullyValid() const
+    {
+        const unsigned char* pbegin = &vbytes[0];
+        EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+        if (o2i_ECPublicKey(&pkey, &pbegin, size()))
+        {
+            EC_KEY_free(pkey);
+            return true;
+        }
+        return false;
+    }
+
+    //! Check whether this is a compressed public key.
+    bool IsCompressed() const
+    {
+        return size() == 33;
+    }
+
+    bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
+    bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
+
+    bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
+
+    // Reserialize to DER
+    static bool ReserealizeSignature(std::vector<unsigned char>& vchSig);
+
     // Encrypt data
     void EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted);
 };
 
-
 // secure_allocator is defined in allocators.h
 // CPrivKey is a serialized private key, with all parameters included (279 bytes)
 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
 // CSecret is a serialization of just the secret parameter (32 bytes)
 typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
 
-/** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
+/** An encapsulated OpenSSL Elliptic Curve key (private) */
 class CKey
 {
 protected:
@@ -118,8 +225,6 @@ protected:
     bool fSet;
     bool fCompressedPubKey;
 
-    void SetCompressedPubKey();
-
 public:
 
     void Reset();
@@ -135,14 +240,15 @@ public:
     bool IsNull() const;
     bool IsCompressed() const;
 
+    void SetCompressedPubKey();
     void MakeNewKey(bool fCompressed=true);
     bool SetPrivKey(const CPrivKey& vchPrivKey);
     bool SetSecret(const CSecret& vchSecret, bool fCompressed = true);
     CSecret GetSecret(bool &fCompressed) const;
     CSecret GetSecret() const;
     CPrivKey GetPrivKey() const;
-    bool SetPubKey(const CPubKey& vchPubKey);
     CPubKey GetPubKey() const;
+    bool WritePEM(BIO *streamObj, const SecureString &strPassKey) const;
 
     bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
 
@@ -152,28 +258,11 @@ public:
     //                  0x1D = second key with even y, 0x1E = second key with odd y
     bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
 
-    // reconstruct public key from a compact signature
-    // This is only slightly more CPU intensive than just verifying it.
-    // If this function succeeds, the recovered public key is guaranteed to be valid
-    // (the signature is a valid signature of the given data for that key)
-    bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
-
-    bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
-
-    // Verify a compact signature
-    bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
-
     bool IsValid();
 
     // Check whether an element of a signature (r or s) is valid.
     static bool CheckSignatureElement(const unsigned char *vch, int len, bool half);
 
-    // Reserialize to DER
-    static bool ReserealizeSignature(std::vector<unsigned char>& vchSig);
-
-    // Encrypt data
-    void EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted);
-
     // Decrypt data
     void DecryptData(const std::vector<unsigned char>& encrypted, std::vector<unsigned char>& data);
 };
index 215590e..33b8eb1 100644 (file)
@@ -157,8 +157,9 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
             if (vchSecret.size() != 32)
                 return false;
             CKey key;
-            key.SetPubKey(vchPubKey);
             key.SetSecret(vchSecret);
+            if (vchPubKey.size() == 33)
+                key.SetCompressedPubKey();
             if (key.GetPubKey() == vchPubKey)
                 break;
             return false;
@@ -316,8 +317,9 @@ bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
                 return false;
             if (vchSecret.size() != 32)
                 return false;
-            keyOut.SetPubKey(vchPubKey);
             keyOut.SetSecret(vchSecret);
+            if (vchPubKey.size() == 33)
+                keyOut.SetCompressedPubKey();
             return true;
         }
     }
@@ -396,8 +398,9 @@ bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
             if (vchSecret.size() != 32)
                 return false;
             CKey key;
-            key.SetPubKey(vchPubKey);
             key.SetSecret(vchSecret);
+            if (vchPubKey.size() == 33)
+                key.SetCompressedPubKey();
             if (!CBasicKeyStore::AddKey(key))
                 return false;
         }
index f4d0ad3..36149ba 100644 (file)
@@ -132,7 +132,6 @@ public:
             KeyMap::const_iterator mi = mapKeys.find(address);
             if (mi != mapKeys.end())
             {
-                keyOut.Reset();
                 keyOut.SetSecret((*mi).second.first, (*mi).second.second);
                 return true;
             }
index 0a6fda1..65001a3 100644 (file)
@@ -2508,7 +2508,7 @@ bool static ReserealizeBlockSignature(CBlock* pblock)
         return true;
     }
 
-    return CKey::ReserealizeSignature(pblock->vchBlockSig);
+    return CPubKey::ReserealizeSignature(pblock->vchBlockSig);
 }
 
 bool static IsCanonicalBlockSignature(CBlock* pblock)
@@ -2667,8 +2667,8 @@ bool CBlock::CheckBlockSignature() const
     if (whichType == TX_PUBKEY)
     {
         valtype& vchPubKey = vSolutions[0];
-        CKey key;
-        if (!key.SetPubKey(vchPubKey))
+        CPubKey key(vchPubKey);
+        if (!key.IsValid())
             return false;
         return key.Verify(GetHash(), vchBlockSig);
     }
index 166b9ed..4b07e11 100644 (file)
@@ -108,7 +108,7 @@ void MultisigAddressEntry::on_address_textChanged(const QString &address)
     {
         CPubKey vchPubKey;
         model->getPubKey(keyID, vchPubKey);
-        std::string pubkey = HexStr(vchPubKey.Raw());
+        std::string pubkey = HexStr(vchPubKey.begin(), vchPubKey.end());
         if(!pubkey.empty())
             ui->pubkey->setText(pubkey.c_str());
     }
index a82f76e..97e49cf 100644 (file)
@@ -149,7 +149,7 @@ void MultisigDialog::on_createAddressButton_clicked()
     if(!model)
         return;
 
-    std::vector<CKey> pubkeys;
+    std::vector<CPubKey> pubkeys;
     pubkeys.resize(ui->pubkeyEntries->count());
     unsigned int required = ui->requiredSignatures->text().toUInt();
 
@@ -162,7 +162,7 @@ void MultisigDialog::on_createAddressButton_clicked()
         CPubKey vchPubKey(ParseHex(str.toStdString().c_str()));
         if(!vchPubKey.IsValid())
             return;
-        pubkeys[i].SetPubKey(vchPubKey);
+        pubkeys[i] = vchPubKey;
     }
 
     if(pubkeys.size() > 16)
index 8d011ab..0782a46 100644 (file)
@@ -220,7 +220,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
     ss << strMessageMagic;
     ss << ui->messageIn_VM->document()->toPlainText().toStdString();
 
-    CKey key;
+    CPubKey key;
     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
     {
         ui->signatureIn_VM->setValid(false);
@@ -229,7 +229,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
         return;
     }
 
-    if (!(CBitcoinAddress(key.GetPubKey().GetID()) == addr))
+    if (!(CBitcoinAddress(key.GetID()) == addr))
     {
         ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
         ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
index 48112a5..bb877bf 100644 (file)
@@ -217,7 +217,7 @@ Value dumpprivkey(const Array& params, bool fHelp)
     CBitcoinAddress address;
     if (!address.SetString(strAddress))
         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
-    if (fWalletUnlockMintOnly) // ppcoin: no dumpprivkey in mint-only mode
+    if (fWalletUnlockMintOnly)
         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for minting only.");
     CKeyID keyID;
     if (!address.GetKeyID(keyID))
@@ -229,6 +229,35 @@ Value dumpprivkey(const Array& params, bool fHelp)
     return CBitcoinSecret(vchSecret, fCompressed).ToString();
 }
 
+Value dumppem(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() != 3)
+        throw runtime_error(
+            "dumppem <novacoinaddress> <filename> <passphrase>\n"
+            "Dump the key pair corresponding to <novacoinaddress> and store it as encrypted PEM file."
+            + HelpRequiringPassphrase());
+
+    EnsureWalletIsUnlocked();
+
+    string strAddress = params[0].get_str();
+    SecureString strPassKey;
+    strPassKey.reserve(100);
+    strPassKey = params[2].get_str().c_str();
+
+    CBitcoinAddress address;
+    if (!address.SetString(strAddress))
+        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address");
+    if (fWalletUnlockMintOnly)
+        throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for minting only.");
+    CKeyID keyID;
+    if (!address.GetKeyID(keyID))
+        throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
+    if (!pwalletMain->GetPEM(keyID, params[1].get_str(), strPassKey))
+        throw JSONRPCError(RPC_WALLET_ERROR, "Error dumping key pair to file");
+
+    return Value::null;
+}
+
 Value dumpwallet(const Array& params, bool fHelp)
 {
     if (fHelp || params.size() != 1)
index c2a10f3..b8365c6 100644 (file)
@@ -652,7 +652,7 @@ Value createmultisig(const Array& params, bool fHelp)
                       "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
     if (keys.size() > 16)
         throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
-    std::vector<CKey> pubkeys;
+    std::vector<CPubKey> pubkeys;
     pubkeys.resize(keys.size());
     for (unsigned int i = 0; i < keys.size(); i++)
     {
@@ -670,16 +670,18 @@ Value createmultisig(const Array& params, bool fHelp)
             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
                 throw runtime_error(
                     strprintf("no full public key for address %s",ks.c_str()));
-            if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
+            if (!vchPubKey.IsFullyValid())
                 throw runtime_error(" Invalid public key: "+ks);
+            pubkeys[i] = vchPubKey;
         }
 
         // Case 2: hex public key
         else if (IsHex(ks))
         {
             CPubKey vchPubKey(ParseHex(ks));
-            if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
+            if (!vchPubKey.IsFullyValid())
                 throw runtime_error(" Invalid public key: "+ks);
+            pubkeys[i] = vchPubKey;
         }
         else
         {
index b96f5c1..09bacfc 100644 (file)
@@ -451,11 +451,11 @@ Value verifymessage(const Array& params, bool fHelp)
     ss << strMessageMagic;
     ss << strMessage;
 
-    CKey key;
+    CPubKey key;
     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
         return false;
 
-    return (key.GetPubKey().GetID() == keyID);
+    return (key.GetID() == keyID);
 }
 
 
@@ -843,7 +843,7 @@ Value addmultisigaddress(const Array& params, bool fHelp)
                       "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
     if (keys.size() > 16)
         throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
-    std::vector<CKey> pubkeys;
+    std::vector<CPubKey> pubkeys;
     pubkeys.resize(keys.size());
     for (unsigned int i = 0; i < keys.size(); i++)
     {
@@ -861,16 +861,18 @@ Value addmultisigaddress(const Array& params, bool fHelp)
             if (!pwalletMain->GetPubKey(keyID, vchPubKey))
                 throw runtime_error(
                     strprintf("no full public key for address %s",ks.c_str()));
-            if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
+            if (!vchPubKey.IsValid())
                 throw runtime_error(" Invalid public key: "+ks);
+            pubkeys[i] = vchPubKey;
         }
 
         // Case 2: hex public key
         else if (IsHex(ks))
         {
             CPubKey vchPubKey(ParseHex(ks));
-            if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
+            if (!vchPubKey.IsValid())
                 throw runtime_error(" Invalid public key: "+ks);
+             pubkeys[i] = vchPubKey;
         }
         else
         {
@@ -1690,7 +1692,7 @@ public:
         obj.push_back(Pair("isscript", false));
         if (mine == MINE_SPENDABLE) {
             pwalletMain->GetPubKey(keyID, vchPubKey);
-            obj.push_back(Pair("pubkey", HexStr(vchPubKey.Raw())));
+            obj.push_back(Pair("pubkey", HexStr(vchPubKey.begin(), vchPubKey.end())));
             obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
         }
         return obj;
@@ -1886,8 +1888,9 @@ Value makekeypair(const Array& params, bool fHelp)
 
     bool fCompressed;
     CSecret vchSecret = key.GetSecret(fCompressed);
+    CPubKey vchPubKey = key.GetPubKey();
     result.push_back(Pair("Secret", HexStr<CSecret::iterator>(vchSecret.begin(), vchSecret.end())));
-    result.push_back(Pair("PublicKey", HexStr(key.GetPubKey().Raw())));
+    result.push_back(Pair("PublicKey", HexStr(vchPubKey.begin(), vchPubKey.end())));
     return result;
 }
 
@@ -1970,8 +1973,8 @@ Value adjustmalleablepubkey(const Array& params, bool fHelp)
     malleablePubKey.GetVariant(R, vchPubKeyVariant);
 
     Object result;
-    result.push_back(Pair("R", HexStr(R.Raw())));
-    result.push_back(Pair("PubkeyVariant", HexStr(vchPubKeyVariant.Raw())));
+    result.push_back(Pair("R", HexStr(R.begin(), R.end())));
+    result.push_back(Pair("PubkeyVariant", HexStr(vchPubKeyVariant.begin(), vchPubKeyVariant.end())));
     result.push_back(Pair("KeyVariantID", CBitcoinAddress(vchPubKeyVariant.GetID()).ToString()));
 
     return result;
index 0f31de1..ad31b76 100644 (file)
@@ -1284,10 +1284,7 @@ bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubK
 {
     static CSignatureCache signatureCache;
 
-    CKey key;
-    if (!key.SetPubKey(vchPubKey))
-         return false;
-    CPubKey pubkey = key.GetPubKey();
+    CPubKey pubkey(vchPubKey);
     if (!pubkey.IsValid())
         return false;
 
@@ -1305,7 +1302,7 @@ bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubK
     if (signatureCache.Get(sighash, vchSig, pubkey))
         return true;
 
-    if (!key.Verify(sighash, vchSig))
+    if (!pubkey.Verify(sighash, vchSig))
         return false;
 
     if (!(flags & SCRIPT_VERIFY_NOCACHE))
@@ -1315,12 +1312,6 @@ bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubK
 }
 
 
-
-
-
-
-
-
 //
 // Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
 //
@@ -2196,12 +2187,12 @@ void CScript::SetAddress(const CBitcoinAddress& dest)
     }
 }
 
-void CScript::SetMultisig(int nRequired, const std::vector<CKey>& keys)
+void CScript::SetMultisig(int nRequired, const std::vector<CPubKey>& keys)
 {
     this->clear();
 
     *this << EncodeOP_N(nRequired);
-    BOOST_FOREACH(const CKey& key, keys)
-        *this << key.GetPubKey();
+    BOOST_FOREACH(const CPubKey& key, keys)
+        *this << key;
     *this << EncodeOP_N((int)(keys.size())) << OP_CHECKMULTISIG;
 }
index c24ab9c..8dd7ce9 100644 (file)
@@ -380,7 +380,7 @@ public:
 
     CScript& operator<<(const CPubKey& key)
     {
-        std::vector<uint8_t> vchKey = key.Raw();
+        std::vector<uint8_t> vchKey(key.begin(), key.end());
         return (*this) << vchKey;
     }
 
@@ -586,7 +586,7 @@ public:
 
     void SetDestination(const CTxDestination& address);
     void SetAddress(const CBitcoinAddress& dest);
-    void SetMultisig(int nRequired, const std::vector<CKey>& keys);
+    void SetMultisig(int nRequired, const std::vector<CPubKey>& keys);
 
 
     void PrintHex() const
index 87ffe93..a1fe81d 100644 (file)
@@ -12,6 +12,7 @@
 #include "kernel.h"
 #include "coincontrol.h"
 #include <boost/algorithm/string/replace.hpp>
+#include <openssl/bio.h>
 
 #include "main.h"
 
@@ -516,6 +517,19 @@ bool CWallet::DecryptWallet(const SecureString& strWalletPassphrase)
     return true;
 }
 
+bool CWallet::GetPEM(const CKeyID &keyID, const std::string &fileName, const SecureString &strPassKey) const
+{
+    BIO *pemOut = BIO_new_file(fileName.c_str(), "w");
+    if (pemOut == NULL)
+        return error("GetPEM() : failed to create file %s\n", fileName.c_str());
+    CKey key;
+    if (!GetKey(keyID, key))
+        return error("GetPEM() : failed to get key for address=%s\n", CBitcoinAddress(keyID).ToString().c_str());
+    bool result = key.WritePEM(pemOut, strPassKey);
+    BIO_free(pemOut);
+    return result;
+}
+
 int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
 {
     int64_t nRet = nOrderPosNext++;
index fb02d02..4db32e5 100644 (file)
@@ -191,6 +191,7 @@ public:
     bool DecryptWallet(const SecureString& strWalletPassphrase);
 
     void GetAddresses(std::map<CBitcoinAddress, int64_t> &mapAddresses) const;
+    bool GetPEM(const CKeyID &keyID, const std::string &fileName, const SecureString &strPassPhrase) const;
 
 
     /** Increment the next transaction order id
index cd90f97..ab85b07 100644 (file)
@@ -334,15 +334,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
         }
         else if (strType == "key" || strType == "wkey")
         {
-            vector<unsigned char> vchPubKey;
-            ssKey >> vchPubKey;
             CKey key;
+            CPubKey vchPubKey;
+            ssKey >> vchPubKey;
             if (strType == "key")
             {
                 wss.nKeys++;
                 CPrivKey pkey;
                 ssValue >> pkey;
-                key.SetPubKey(vchPubKey);
                 if (!key.SetPrivKey(pkey))
                 {
                     strErr = "Error reading wallet database: CPrivKey corrupt";
@@ -353,6 +352,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
                     strErr = "Error reading wallet database: CPrivKey pubkey inconsistency";
                     return false;
                 }
+                if (vchPubKey.size() == 33) {
+                    key.SetCompressedPubKey();
+                }
                 if (!key.IsValid())
                 {
                     strErr = "Error reading wallet database: invalid CPrivKey";
@@ -363,7 +365,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
             {
                 CWalletKey wkey;
                 ssValue >> wkey;
-                key.SetPubKey(vchPubKey);
                 if (!key.SetPrivKey(wkey.vchPrivKey))
                 {
                     strErr = "Error reading wallet database: CPrivKey corrupt";
@@ -374,6 +375,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
                     strErr = "Error reading wallet database: CWalletKey pubkey inconsistency";
                     return false;
                 }
+                if (vchPubKey.size() == 33) {
+                    key.SetCompressedPubKey();
+                }
                 if (!key.IsValid())
                 {
                     strErr = "Error reading wallet database: invalid CWalletKey";
@@ -405,7 +409,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
         else if (strType == "ckey")
         {
             wss.nCKeys++;
-            vector<unsigned char> vchPubKey;
+            CPubKey vchPubKey;
             ssKey >> vchPubKey;
             vector<unsigned char> vchPrivKey;
             ssValue >> vchPrivKey;
index 94b355f..714b3cc 100644 (file)
@@ -83,13 +83,13 @@ public:
         return Erase(std::make_pair(std::string("tx"), hash));
     }
 
-    bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta)
+    bool WriteKey(const CPubKey& key, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta)
     {
         nWalletDBUpdated++;
-        if(!Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta))
+        if(!Write(std::make_pair(std::string("keymeta"), key), keyMeta))
             return false;
 
-        if(!Write(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey, false))
+        if(!Write(std::make_pair(std::string("key"), key), vchPrivKey, false))
             return false;
 
         return true;
@@ -122,20 +122,20 @@ public:
     }
 
 
-    bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
+    bool WriteCryptedKey(const CPubKey& key, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
     {
         nWalletDBUpdated++;
         bool fEraseUnencryptedKey = true;
 
-        if(!Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta))
+        if(!Write(std::make_pair(std::string("keymeta"), key), keyMeta))
             return false;
 
-        if (!Write(std::make_pair(std::string("ckey"), vchPubKey.Raw()), vchCryptedSecret, false))
+        if (!Write(std::make_pair(std::string("ckey"), key), vchCryptedSecret, false))
             return false;
         if (fEraseUnencryptedKey)
         {
-            Erase(std::make_pair(std::string("key"), vchPubKey.Raw()));
-            Erase(std::make_pair(std::string("wkey"), vchPubKey.Raw()));
+            Erase(std::make_pair(std::string("key"), key));
+            Erase(std::make_pair(std::string("wkey"), key));
         }
         return true;
     }
@@ -152,9 +152,9 @@ public:
         return Erase(std::make_pair(std::string("mkey"), nID));
     }
 
-    bool EraseCryptedKey(const CPubKey& vchPubKey)
+    bool EraseCryptedKey(const CPubKey& key)
     {
-        return Erase(std::make_pair(std::string("ckey"), vchPubKey.Raw()));
+        return Erase(std::make_pair(std::string("ckey"), key));
     }
 
     bool EraseCryptedMalleableKey(const CMalleableKeyView& keyView)
@@ -197,10 +197,10 @@ public:
         return Write(std::string("orderposnext"), nOrderPosNext);
     }
 
-    bool WriteDefaultKey(const CPubKey& vchPubKey)
+    bool WriteDefaultKey(const CPubKey& key)
     {
         nWalletDBUpdated++;
-        return Write(std::string("defaultkey"), vchPubKey.Raw());
+        return Write(std::string("defaultkey"), key);
     }
 
     bool ReadPool(int64_t nPool, CKeyPool& keypool)