From 6bffc46a874320a3845aebe81040c2c6b119faab Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 28 Sep 2016 13:44:31 +1300 Subject: [PATCH] Implement CSecureDataStream for streaming CKeyingMaterial --- src/streams.h | 81 +++++++++++++++++++++++++++--------------- src/wallet/crypter.cpp | 8 ++--- src/wallet/crypter.h | 13 +++++++ 3 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/streams.h b/src/streams.h index fa1e18def..787d8e297 100644 --- a/src/streams.h +++ b/src/streams.h @@ -27,54 +27,55 @@ * >> and << read and write unformatted data using the above serialization templates. * Fills with data in linear time; some stringstream implementations take N^2 time. */ -class CDataStream +template +class CBaseDataStream { protected: - typedef CSerializeData vector_type; + typedef SerializeType vector_type; vector_type vch; unsigned int nReadPos; public: int nType; int nVersion; - typedef vector_type::allocator_type allocator_type; - typedef vector_type::size_type size_type; - typedef vector_type::difference_type difference_type; - typedef vector_type::reference reference; - typedef vector_type::const_reference const_reference; - typedef vector_type::value_type value_type; - typedef vector_type::iterator iterator; - typedef vector_type::const_iterator const_iterator; - typedef vector_type::reverse_iterator reverse_iterator; + typedef typename vector_type::allocator_type allocator_type; + typedef typename vector_type::size_type size_type; + typedef typename vector_type::difference_type difference_type; + typedef typename vector_type::reference reference; + typedef typename vector_type::const_reference const_reference; + typedef typename vector_type::value_type value_type; + typedef typename vector_type::iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::reverse_iterator reverse_iterator; - explicit CDataStream(int nTypeIn, int nVersionIn) + explicit CBaseDataStream(int nTypeIn, int nVersionIn) { Init(nTypeIn, nVersionIn); } - CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) + CBaseDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) { Init(nTypeIn, nVersionIn); } #if !defined(_MSC_VER) || _MSC_VER >= 1300 - CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) + CBaseDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) { Init(nTypeIn, nVersionIn); } #endif - CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) + CBaseDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) { Init(nTypeIn, nVersionIn); } - CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) + CBaseDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) { Init(nTypeIn, nVersionIn); } - CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) + CBaseDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) { Init(nTypeIn, nVersionIn); } @@ -86,15 +87,15 @@ public: nVersion = nVersionIn; } - CDataStream& operator+=(const CDataStream& b) + CBaseDataStream& operator+=(const CBaseDataStream& b) { vch.insert(vch.end(), b.begin(), b.end()); return *this; } - friend CDataStream operator+(const CDataStream& a, const CDataStream& b) + friend CBaseDataStream operator+(const CBaseDataStream& a, const CBaseDataStream& b) { - CDataStream ret = a; + CBaseDataStream ret = a; ret += b; return (ret); } @@ -207,7 +208,7 @@ public: // Stream subset // bool eof() const { return size() == 0; } - CDataStream* rdbuf() { return this; } + CBaseDataStream* rdbuf() { return this; } int in_avail() { return size(); } void SetType(int n) { nType = n; } @@ -217,7 +218,7 @@ public: void ReadVersion() { *this >> nVersion; } void WriteVersion() { *this << nVersion; } - CDataStream& read(char* pch, size_t nSize) + CBaseDataStream& read(char* pch, size_t nSize) { // Read from the beginning of the buffer unsigned int nReadPosNext = nReadPos + nSize; @@ -225,7 +226,7 @@ public: { if (nReadPosNext > vch.size()) { - throw std::ios_base::failure("CDataStream::read(): end of data"); + throw std::ios_base::failure("CBaseDataStream::read(): end of data"); } memcpy(pch, &vch[nReadPos], nSize); nReadPos = 0; @@ -237,7 +238,7 @@ public: return (*this); } - CDataStream& ignore(int nSize) + CBaseDataStream& ignore(int nSize) { // Ignore from the beginning of the buffer assert(nSize >= 0); @@ -245,7 +246,7 @@ public: if (nReadPosNext >= vch.size()) { if (nReadPosNext > vch.size()) - throw std::ios_base::failure("CDataStream::ignore(): end of data"); + throw std::ios_base::failure("CBaseDataStream::ignore(): end of data"); nReadPos = 0; vch.clear(); return (*this); @@ -254,7 +255,7 @@ public: return (*this); } - CDataStream& write(const char* pch, size_t nSize) + CBaseDataStream& write(const char* pch, size_t nSize) { // Write to the end of the buffer vch.insert(vch.end(), pch, pch + nSize); @@ -277,7 +278,7 @@ public: } template - CDataStream& operator<<(const T& obj) + CBaseDataStream& operator<<(const T& obj) { // Serialize to this stream ::Serialize(*this, obj, nType, nVersion); @@ -285,7 +286,7 @@ public: } template - CDataStream& operator>>(T& obj) + CBaseDataStream& operator>>(T& obj) { // Unserialize from this stream ::Unserialize(*this, obj, nType, nVersion); @@ -298,6 +299,30 @@ public: } }; +class CDataStream : public CBaseDataStream +{ +public: + explicit CDataStream(int nTypeIn, int nVersionIn) : CBaseDataStream(nTypeIn, nVersionIn) { } + + CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : + CBaseDataStream(pbegin, pend, nTypeIn, nVersionIn) { } + +#if !defined(_MSC_VER) || _MSC_VER >= 1300 + CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : + CBaseDataStream(pbegin, pend, nTypeIn, nVersionIn) { } +#endif + + CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : + CBaseDataStream(vchIn, nTypeIn, nVersionIn) { } + + CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : + CBaseDataStream(vchIn, nTypeIn, nVersionIn) { } + + CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : + CBaseDataStream(vchIn, nTypeIn, nVersionIn) { } + +}; + diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 06ace79c6..5572ebe2f 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -148,9 +148,7 @@ static bool DecryptSpendingKey(const CKeyingMaterial& vMasterKey, if (vchSecret.size() != libzcash::SerializedSpendingKeySize) return false; - // TODO does this undo the benefits of using CKeyingMaterial? - std::vector serialized(vchSecret.begin(), vchSecret.end()); - CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); + CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION); ss >> sk; return sk.address() == address; } @@ -313,7 +311,7 @@ bool CCryptoKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk) return false; std::vector vchCryptedSecret; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << sk; CKeyingMaterial vchSecret(ss.begin(), ss.end()); auto address = sk.address(); @@ -378,7 +376,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) BOOST_FOREACH(SpendingKeyMap::value_type& mSpendingKey, mapSpendingKeys) { const libzcash::SpendingKey &sk = mSpendingKey.second; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << sk; CKeyingMaterial vchSecret(ss.begin(), ss.end()); libzcash::PaymentAddress address = sk.address(); diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 4dfffa50e..e95a841a4 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -7,6 +7,7 @@ #include "keystore.h" #include "serialize.h" +#include "streams.h" #include "support/allocators/secure.h" #include "zcash/Address.hpp" @@ -67,6 +68,18 @@ public: typedef std::vector > CKeyingMaterial; +class CSecureDataStream : public CBaseDataStream +{ +public: + explicit CSecureDataStream(int nTypeIn, int nVersionIn) : CBaseDataStream(nTypeIn, nVersionIn) { } + + CSecureDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : + CBaseDataStream(pbegin, pend, nTypeIn, nVersionIn) { } + + CSecureDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : + CBaseDataStream(vchIn, nTypeIn, nVersionIn) { } +}; + /** Encryption/decryption context with key information */ class CCrypter {