diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 6c42aa501..561f2f405 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -67,6 +67,9 @@ public: /// Explicitly construct, copying from a byte array. explicit FixedHash(bytes const& _b) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); } + /// Explicitly construct, copying from a byte array. + explicit FixedHash(bytesConstRef _b) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min(_b.size(), N)); } + /// Explicitly construct, copying from a bytes in memory with given pointer. explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 0d2c07747..55812f34a 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -173,9 +173,9 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, return _m.seal(_from, bt, ttl, workToProve); } -static pair toWatch(Json::Value const& _json) +static pair toWatch(Json::Value const& _json) { - shh::BuildTopicMask bt; + shh::BuildTopic bt; Public to; if (_json["to"].isString()) @@ -190,7 +190,7 @@ static pair toWatch(Json::Value const& _json) if (i.isString()) bt.shift(jsToBytes(i.asString())); } - return make_pair(bt.toTopicMask(), to); + return make_pair(bt, to); } static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message const& _m) @@ -571,6 +571,7 @@ Json::Value WebThreeStubServerBase::shh_changed(int const& _id) if (!pub || m_ids.count(pub)) for (h256 const& h: face()->checkWatch(_id)) { + face()->watchFilter(_id).topics(); auto e = face()->envelope(h); shh::Message m; if (pub) diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index bbc7ecdf7..a057157d1 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -37,6 +37,15 @@ Topic BuildTopic::toTopic() const return ret; } +FullTopic BuildTopic::toFullTopic() const +{ + FullTopic ret; + ret.reserve(m_parts.size()); + for (auto const& h: m_parts) + ret.push_back(h); + return ret; +} + BuildTopic& BuildTopic::shiftBytes(bytes const& _b) { m_parts.push_back(dev::sha3(_b)); diff --git a/libwhisper/Common.h b/libwhisper/Common.h index 5ce7d3b1c..442e71830 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -62,6 +62,7 @@ enum WhisperPacket using TopicPart = FixedHash<4>; using Topic = std::vector; +using FullTopic = std::vector; class BuildTopic { @@ -75,7 +76,9 @@ public: BuildTopic& shiftRaw(h256 const& _part) { m_parts.push_back(_part); return *this; } operator Topic() const { return toTopic(); } + operator FullTopic() const { return toFullTopic(); } Topic toTopic() const; + FullTopic toFullTopic() const { return m_parts; } protected: BuildTopic& shiftBytes(bytes const& _b); @@ -108,6 +111,7 @@ public: bool matches(Envelope const& _m) const; private: + h256s m_parts; TopicMasks m_topicMasks; }; diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index 0b7b52cf7..fdac29cba 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -47,8 +47,9 @@ class Watch; struct InstalledFilter { - InstalledFilter(TopicFilter const& _f): filter(_f) {} + InstalledFilter(FullTopic const& _f): full(_f), filter(fullToFilter(_f)) {} + FullTopic full; TopicFilter filter; unsigned refCount = 1; }; @@ -70,7 +71,8 @@ public: virtual void inject(Envelope const& _m, WhisperPeer* _from = nullptr) = 0; unsigned installWatch(TopicMask const& _mask); - virtual unsigned installWatch(TopicFilter const& _filter) = 0; + virtual FullTopic getFilter(unsigned _id) const = 0; + virtual unsigned installWatch(FullTopic const& _filter) = 0; virtual unsigned installWatchOnId(h256 _filterId) = 0; virtual void uninstallWatch(unsigned _watchId) = 0; virtual h256s peekWatch(unsigned _watchId) const = 0; @@ -108,6 +110,7 @@ public: Watch(Interface& _c, TopicFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {} ~Watch() { if (m_c) m_c->uninstallWatch(m_id); } + FullTopic fullTopic() const { return m_c ? m_c->fullTopic(m_id) : FullTopic(); } h256s check() { return m_c ? m_c->checkWatch(m_id) : h256s(); } h256s peek() { return m_c ? m_c->peekWatch(m_id) : h256s(); } diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 07620a7cf..5a10fc323 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -26,7 +26,7 @@ using namespace dev; using namespace dev::p2p; using namespace dev::shh; -Message::Message(Envelope const& _e, Secret const& _s) +Message::Message(Envelope const& _e, Secret const& _s, unsigned _topicIndex) { try { @@ -34,7 +34,18 @@ Message::Message(Envelope const& _e, Secret const& _s) if (_s) if (!decrypt(_s, &(_e.data()), b)) return; - if (populate(_s ? b : _e.data())) + else{} + else + { + // public - need to get the key through combining with the topic/topicIndex we know. + if (_e.data().size() < _e.topics().size() * 32) + return; + // get key from decrypted topic key: just xor + if (!decrypt(_s ^ h256(bytesConstRef(&(_e.data())).cropped(32 * _topicIndex, 32)), bytesConstRef(&(_e.data())).cropped(32 * _e.topics().size()), b)) + return; + } + + if (populate(b)) m_to = KeyPair(_s).pub(); } catch (...) // Invalid secret? TODO: replace ... with InvalidSecret @@ -63,7 +74,7 @@ bool Message::populate(bytes const& _data) return true; } -Envelope Message::seal(Secret _from, Topic const& _topic, unsigned _ttl, unsigned _workToProve) const +Envelope Message::seal(Secret _from, FullTopic const& _topic, unsigned _ttl, unsigned _workToProve) const { Envelope ret(time(0) + _ttl, _ttl, _topic); diff --git a/libwhisper/Message.h b/libwhisper/Message.h index 91765d33e..eeb7446eb 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -64,7 +64,7 @@ public: Topic const& topic() const { return m_topic; } bytes const& data() const { return m_data; } - Message open(Secret const& _s = Secret()) const; + Message open(Secret const& _s = Secret(), unsigned _topicIndex = (unsigned)-1) const; unsigned workProved() const; void proveWork(unsigned _ms); @@ -91,7 +91,7 @@ class Message { public: Message() {} - Message(Envelope const& _e, Secret const& _s = Secret()); + Message(Envelope const& _e, Secret const& _s = Secret(), unsigned _topicIndex = (unsigned)-1); Message(bytes const& _payload): m_payload(_payload) {} Message(bytesConstRef _payload): m_payload(_payload.toBytes()) {} Message(bytes&& _payload) { std::swap(_payload, m_payload); } @@ -108,11 +108,11 @@ public: operator bool() const { return !!m_payload.size() || m_from || m_to; } /// Turn this message into a ditributable Envelope. - Envelope seal(Secret _from, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) const; + Envelope seal(Secret _from, FullTopic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) const; // Overloads for skipping _from or specifying _to. - Envelope seal(Topic const& _topic, unsigned _ttl = 50, unsigned _workToProve = 50) const { return seal(Secret(), _topic, _workToProve, _ttl); } - Envelope sealTo(Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(Secret(), _topic, _workToProve, _ttl); } - Envelope sealTo(Secret _from, Public _to, Topic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(_from, _topic, _workToProve, _ttl); } + Envelope seal(FullTopic const& _topic, unsigned _ttl = 50, unsigned _workToProve = 50) const { return seal(Secret(), _topic, _workToProve, _ttl); } + Envelope sealTo(Public _to, FullTopic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(Secret(), _topic, _workToProve, _ttl); } + Envelope sealTo(Secret _from, Public _to, FullTopic const& _topic, unsigned _workToProve = 50, unsigned _ttl = 50) { m_to = _to; return seal(_from, _topic, _workToProve, _ttl); } private: bool populate(bytes const& _data);