Browse Source

topic encryption with pbkdf2

cl-refactor
Vlad Gluhovsky 10 years ago
parent
commit
be05a43e22
  1. 81
      libwhisper/Message.cpp
  2. 2
      libwhisper/Message.h
  3. 103
      test/libwhisper/whisperMessage.cpp

81
libwhisper/Message.cpp

@ -35,34 +35,8 @@ Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s)
if (!decrypt(_s, &(_e.data()), b)) if (!decrypt(_s, &(_e.data()), b))
return; return;
else{} else{}
else else if (!openBroadcastEnvelope(_e, _fk, b))
{ return;
// public - need to get the key through combining with the topic/topicIndex we know.
unsigned topicIndex = 0;
Secret topicSecret;
// determine topicSecret/topicIndex from knowledge of the collapsed topics (which give the order) and our full-size filter topic.
CollapsedTopic knownTopic = collapse(_fk);
for (unsigned ti = 0; ti < _fk.size() && !topicSecret; ++ti)
for (unsigned i = 0; i < _e.topic().size(); ++i)
if (_e.topic()[i] == knownTopic[ti])
{
topicSecret = _fk[ti];
topicIndex = i;
break;
}
if (_e.data().size() < _e.topic().size() * 32)
return;
// get key from decrypted topic key: just xor
h256 tk = h256(bytesConstRef(&(_e.data())).cropped(32 * topicIndex, 32));
bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(32 * _e.topic().size());
// cdebug << "Decrypting(" << topicIndex << "): " << topicSecret << tk << (topicSecret ^ tk) << toHex(cipherText);
if (!decryptSym(topicSecret ^ tk, cipherText, b))
return;
// cdebug << "Got: " << toHex(b);
}
if (populate(b)) if (populate(b))
if (_s) if (_s)
@ -73,6 +47,40 @@ Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s)
} }
} }
bool Message::openBroadcastEnvelope(Envelope const& _e, FullTopic const& _fk, bytes& o_b)
{
// retrieve the key using the known topic and topicIndex.
unsigned topicIndex = 0;
Secret topicSecret;
// determine topicSecret/topicIndex from knowledge of the collapsed topics (which give the order) and our full-size filter topic.
CollapsedTopic knownTopic = collapse(_fk);
for (unsigned ti = 0; ti < _fk.size() && !topicSecret; ++ti)
for (unsigned i = 0; i < _e.topic().size(); ++i)
if (_e.topic()[i] == knownTopic[ti])
{
topicSecret = _fk[ti];
topicIndex = i;
break;
}
if (_e.data().size() < _e.topic().size() * 32)
return false;
h256 encryptedKey = h256(bytesConstRef(&(_e.data())).cropped(32 * topicIndex, 32));
h256 key = generateGamma(topicSecret) ^ encryptedKey;
bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(32 * _e.topic().size());
return decryptSym(key, cipherText, o_b);
}
h256 Message::generateGamma(h256 const& _seed) const
{
int const c_rounds = 128;
bytes zeroSalt;
bytes hashedTopic = dev::pbkdf2(_seed.hex(), zeroSalt, c_rounds);
return h256(hashedTopic);
}
bool Message::populate(bytes const& _data) bool Message::populate(bytes const& _data)
{ {
if (!_data.size()) if (!_data.size())
@ -116,23 +124,14 @@ Envelope Message::seal(Secret _from, FullTopic const& _fullTopic, unsigned _ttl,
encrypt(m_to, &input, ret.m_data); encrypt(m_to, &input, ret.m_data);
else else
{ {
// create the shared secret and encrypt // create the shared secret for encrypting the payload, then encrypt the shared secret with each topic
Secret s = Secret::random(); Secret s = Secret::random();
for (h256 const& t: _fullTopic) for (h256 const& t : _fullTopic)
ret.m_data += (t ^ s).asBytes(); ret.m_data += (generateGamma(t) ^ s).asBytes();
bytes d; bytes d;
encryptSym(s, &input, d); encryptSym(s, &input, d);
ret.m_data += d; ret.m_data += d;
for (unsigned i = 0; i < _fullTopic.size(); ++i)
{
bytes b;
h256 tk = h256(bytesConstRef(&(ret.m_data)).cropped(32 * i, 32));
bytesConstRef cipherText = bytesConstRef(&(ret.m_data)).cropped(32 * ret.topic().size());
cnote << "Test decrypting(" << i << "): " << _fullTopic[i] << tk << (_fullTopic[i] ^ tk) << toHex(cipherText);
assert(decryptSym(_fullTopic[i] ^ tk, cipherText, b));
cnote << "Got: " << toHex(b);
}
} }
ret.proveWork(_workToProve); ret.proveWork(_workToProve);

2
libwhisper/Message.h

@ -127,6 +127,8 @@ public:
private: private:
bool populate(bytes const& _data); bool populate(bytes const& _data);
h256 generateGamma(h256 const& _seed) const;
bool openBroadcastEnvelope(Envelope const& _e, FullTopic const& _fk, bytes& o_b);
Public m_from; Public m_from;
Public m_to; Public m_to;

103
test/libwhisper/whisperMessage.cpp

@ -0,0 +1,103 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file whisperMessage.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date May 2015
*/
#include <boost/test/unit_test.hpp>
#include <libwhisper/Message.h>
using namespace std;
using namespace dev;
using namespace dev::shh;
struct VerbosityHolder
{
VerbosityHolder() : oldLogVerbosity(g_logVerbosity) { g_logVerbosity = 10; }
~VerbosityHolder() { g_logVerbosity = oldLogVerbosity; }
int oldLogVerbosity;
};
FullTopic createRandomTopics(unsigned int i)
{
FullTopic ret;
h256 t(i);
for (int j = 0; j < 8; ++j)
{
t = sha3(t);
ret.push_back(t);
}
return move(ret);
}
bytes createRandomPayload(unsigned int i)
{
bytes ret;
srand(i);
int const sz = rand() % 1024;
for (int j = 0; j < sz; ++j)
ret.push_back(rand() % 256);
return move(ret);
}
void comparePayloads(Message const& m1, Message const& m2)
{
bytes const& p1 = m1.payload();
bytes const& p2 = m2.payload();
BOOST_REQUIRE_EQUAL(p1.size(), p2.size());
for (size_t i = 0; i < p1.size(); ++i)
BOOST_REQUIRE_EQUAL(p1[i], p2[i]);
}
void sealAndOpenSingleMessage(unsigned int i)
{
Secret zero;
FullTopic topics = createRandomTopics(i);
bytes const payload = createRandomPayload(i);
Message m1(payload);
Envelope e = m1.seal(zero, topics, 1, 1);
for (auto const& t: topics)
{
FullTopic singleTopic;
singleTopic.push_back(t);
Message m2(e, singleTopic, zero);
comparePayloads(m1, m2);
}
}
BOOST_AUTO_TEST_SUITE(whisperMessage)
BOOST_AUTO_TEST_CASE(seal)
{
VerbosityHolder verbosityHolder;
cnote << "Testing Envelope encryption...";
for (unsigned int i = 1; i < 32; ++i)
{
cnote << i;
sealAndOpenSingleMessage(i);
}
}
BOOST_AUTO_TEST_SUITE_END()
Loading…
Cancel
Save