Implement CSecureDataStream for streaming CKeyingMaterial

This commit is contained in:
Jack Grigg
2016-09-28 13:44:31 +13:00
parent 3bbf2c1422
commit 6bffc46a87
3 changed files with 69 additions and 33 deletions

View File

@@ -27,54 +27,55 @@
* >> and << read and write unformatted data using the above serialization templates. * >> and << read and write unformatted data using the above serialization templates.
* Fills with data in linear time; some stringstream implementations take N^2 time. * Fills with data in linear time; some stringstream implementations take N^2 time.
*/ */
class CDataStream template<typename SerializeType>
class CBaseDataStream
{ {
protected: protected:
typedef CSerializeData vector_type; typedef SerializeType vector_type;
vector_type vch; vector_type vch;
unsigned int nReadPos; unsigned int nReadPos;
public: public:
int nType; int nType;
int nVersion; int nVersion;
typedef vector_type::allocator_type allocator_type; typedef typename vector_type::allocator_type allocator_type;
typedef vector_type::size_type size_type; typedef typename vector_type::size_type size_type;
typedef vector_type::difference_type difference_type; typedef typename vector_type::difference_type difference_type;
typedef vector_type::reference reference; typedef typename vector_type::reference reference;
typedef vector_type::const_reference const_reference; typedef typename vector_type::const_reference const_reference;
typedef vector_type::value_type value_type; typedef typename vector_type::value_type value_type;
typedef vector_type::iterator iterator; typedef typename vector_type::iterator iterator;
typedef vector_type::const_iterator const_iterator; typedef typename vector_type::const_iterator const_iterator;
typedef vector_type::reverse_iterator reverse_iterator; typedef typename vector_type::reverse_iterator reverse_iterator;
explicit CDataStream(int nTypeIn, int nVersionIn) explicit CBaseDataStream(int nTypeIn, int nVersionIn)
{ {
Init(nTypeIn, 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); Init(nTypeIn, nVersionIn);
} }
#if !defined(_MSC_VER) || _MSC_VER >= 1300 #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); Init(nTypeIn, nVersionIn);
} }
#endif #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); Init(nTypeIn, nVersionIn);
} }
CDataStream(const std::vector<char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) CBaseDataStream(const std::vector<char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
{ {
Init(nTypeIn, nVersionIn); Init(nTypeIn, nVersionIn);
} }
CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) CBaseDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
{ {
Init(nTypeIn, nVersionIn); Init(nTypeIn, nVersionIn);
} }
@@ -86,15 +87,15 @@ public:
nVersion = nVersionIn; nVersion = nVersionIn;
} }
CDataStream& operator+=(const CDataStream& b) CBaseDataStream& operator+=(const CBaseDataStream& b)
{ {
vch.insert(vch.end(), b.begin(), b.end()); vch.insert(vch.end(), b.begin(), b.end());
return *this; 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; ret += b;
return (ret); return (ret);
} }
@@ -207,7 +208,7 @@ public:
// Stream subset // Stream subset
// //
bool eof() const { return size() == 0; } bool eof() const { return size() == 0; }
CDataStream* rdbuf() { return this; } CBaseDataStream* rdbuf() { return this; }
int in_avail() { return size(); } int in_avail() { return size(); }
void SetType(int n) { nType = n; } void SetType(int n) { nType = n; }
@@ -217,7 +218,7 @@ public:
void ReadVersion() { *this >> nVersion; } void ReadVersion() { *this >> nVersion; }
void WriteVersion() { *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 // Read from the beginning of the buffer
unsigned int nReadPosNext = nReadPos + nSize; unsigned int nReadPosNext = nReadPos + nSize;
@@ -225,7 +226,7 @@ public:
{ {
if (nReadPosNext > vch.size()) 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); memcpy(pch, &vch[nReadPos], nSize);
nReadPos = 0; nReadPos = 0;
@@ -237,7 +238,7 @@ public:
return (*this); return (*this);
} }
CDataStream& ignore(int nSize) CBaseDataStream& ignore(int nSize)
{ {
// Ignore from the beginning of the buffer // Ignore from the beginning of the buffer
assert(nSize >= 0); assert(nSize >= 0);
@@ -245,7 +246,7 @@ public:
if (nReadPosNext >= vch.size()) if (nReadPosNext >= vch.size())
{ {
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; nReadPos = 0;
vch.clear(); vch.clear();
return (*this); return (*this);
@@ -254,7 +255,7 @@ public:
return (*this); 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 // Write to the end of the buffer
vch.insert(vch.end(), pch, pch + nSize); vch.insert(vch.end(), pch, pch + nSize);
@@ -277,7 +278,7 @@ public:
} }
template<typename T> template<typename T>
CDataStream& operator<<(const T& obj) CBaseDataStream& operator<<(const T& obj)
{ {
// Serialize to this stream // Serialize to this stream
::Serialize(*this, obj, nType, nVersion); ::Serialize(*this, obj, nType, nVersion);
@@ -285,7 +286,7 @@ public:
} }
template<typename T> template<typename T>
CDataStream& operator>>(T& obj) CBaseDataStream& operator>>(T& obj)
{ {
// Unserialize from this stream // Unserialize from this stream
::Unserialize(*this, obj, nType, nVersion); ::Unserialize(*this, obj, nType, nVersion);
@@ -298,6 +299,30 @@ public:
} }
}; };
class CDataStream : public CBaseDataStream<CSerializeData>
{
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<char>& vchIn, int nTypeIn, int nVersionIn) :
CBaseDataStream(vchIn, nTypeIn, nVersionIn) { }
CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) :
CBaseDataStream(vchIn, nTypeIn, nVersionIn) { }
};

View File

@@ -148,9 +148,7 @@ static bool DecryptSpendingKey(const CKeyingMaterial& vMasterKey,
if (vchSecret.size() != libzcash::SerializedSpendingKeySize) if (vchSecret.size() != libzcash::SerializedSpendingKeySize)
return false; return false;
// TODO does this undo the benefits of using CKeyingMaterial? CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION);
std::vector<unsigned char> serialized(vchSecret.begin(), vchSecret.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
ss >> sk; ss >> sk;
return sk.address() == address; return sk.address() == address;
} }
@@ -313,7 +311,7 @@ bool CCryptoKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk)
return false; return false;
std::vector<unsigned char> vchCryptedSecret; std::vector<unsigned char> vchCryptedSecret;
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << sk; ss << sk;
CKeyingMaterial vchSecret(ss.begin(), ss.end()); CKeyingMaterial vchSecret(ss.begin(), ss.end());
auto address = sk.address(); auto address = sk.address();
@@ -378,7 +376,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
BOOST_FOREACH(SpendingKeyMap::value_type& mSpendingKey, mapSpendingKeys) BOOST_FOREACH(SpendingKeyMap::value_type& mSpendingKey, mapSpendingKeys)
{ {
const libzcash::SpendingKey &sk = mSpendingKey.second; const libzcash::SpendingKey &sk = mSpendingKey.second;
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << sk; ss << sk;
CKeyingMaterial vchSecret(ss.begin(), ss.end()); CKeyingMaterial vchSecret(ss.begin(), ss.end());
libzcash::PaymentAddress address = sk.address(); libzcash::PaymentAddress address = sk.address();

View File

@@ -7,6 +7,7 @@
#include "keystore.h" #include "keystore.h"
#include "serialize.h" #include "serialize.h"
#include "streams.h"
#include "support/allocators/secure.h" #include "support/allocators/secure.h"
#include "zcash/Address.hpp" #include "zcash/Address.hpp"
@@ -67,6 +68,18 @@ public:
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial; typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
class CSecureDataStream : public CBaseDataStream<CKeyingMaterial>
{
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 */ /** Encryption/decryption context with key information */
class CCrypter class CCrypter
{ {