aboutsummaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-11-12 13:48:30 +0100
committerDennis Brentjes <d.brentjes@gmail.com>2016-11-12 13:48:30 +0100
commitf93d52bbd0053574fb35d72b85c4b299dc1f3ee5 (patch)
tree4a2120a162ce9161d70074fd9ffa3ed21d80a40e /node
parent8ff9babe2da4a2efc8529e800a6093fbd0327286 (diff)
downloadcmix-f93d52bbd0053574fb35d72b85c4b299dc1f3ee5.tar.gz
cmix-f93d52bbd0053574fb35d72b85c4b299dc1f3ee5.tar.bz2
cmix-f93d52bbd0053574fb35d72b85c4b299dc1f3ee5.zip
Fixes decryption share calculation, adds lots of debugging statements.
Diffstat (limited to 'node')
-rw-r--r--node/main.cpp2
-rw-r--r--node/node.cpp67
-rw-r--r--node/node.hpp39
-rw-r--r--node/node_client.cpp15
-rw-r--r--node/node_node.cpp157
5 files changed, 251 insertions, 29 deletions
diff --git a/node/main.cpp b/node/main.cpp
index 28ef60c..acfdafe 100644
--- a/node/main.cpp
+++ b/node/main.cpp
@@ -21,7 +21,7 @@ int main(int argc, char* argv[]) {
("interface6,6", po::value<std::string>()->default_value("::"), "Set the ipv6 address to listen on.")
("next_node,n", po::value<std::string>(), "The address of the next node in the network.")
("first,f", "This is the first node and will be the communication point for the clients.")
- ("last,f", "this is the last node and will be able to send the original message out of the network.")
+ ("last,l", "this is the last node and will be able to send the original message out of the network.")
("cert,c", po::value<std::string>(), "The cert file to use (in pem format).")
("key,k", po::value<std::string>(), "The key file (in pem format).")
("dhparam,d", po::value<std::string>(), "The dhparam file.")
diff --git a/node/node.cpp b/node/node.cpp
index b5c8506..5bce063 100644
--- a/node/node.cpp
+++ b/node/node.cpp
@@ -11,19 +11,40 @@ using namespace boost::asio::ip;
Node::Node(ListenSettings const& listen_settings, NodeNetworkSettings network_settings)
: io_service()
+, timer(io_service)
, ssl_ctx(std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23))
, server(io_service, listen_settings, ssl_ctx, [this](std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>&& socket, std::shared_ptr<boost::asio::ssl::context> ctx){accept_handler(std::move(socket), ctx);})
, clients()
, data()
+, messages()
, network_settings(network_settings)
, prev_node(SSLReceiver(std::unique_ptr<boost::asio::ssl::stream<tcp::socket>>(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(io_service, *ssl_ctx))))
, next_node(SSLSender(std::unique_ptr<boost::asio::ssl::stream<tcp::socket>>(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(io_service, *ssl_ctx))))
, cmix_ctx(initialize_cmix_context(get_implementation()))
-, precomputation_data()
, shutting_down(false)
{
initialize_keypair(&cmix_ctx);
+ std::string x = to_string(cmix_ctx.keypair.sec, cmix_ctx);
+ std::string y = to_string(cmix_ctx.keypair.pub, cmix_ctx);
+ {
+ std::stringstream ss;
+ ss << "sec: ";
+ for(auto&& c : x) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+
+ {
+ std::stringstream ss;
+ ss << "pub: ";
+ for(auto&& c : y) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+
GOOGLE_PROTOBUF_VERIFY_VERSION;
if(network_settings.is_first) {
@@ -131,14 +152,15 @@ void Node::handle_message(Purgatory::iterator handle, cmix_proto::CMixMessage me
}
void Node::start_precomputation() {
+ BOOST_LOG_TRIVIAL(trace) << "Starting precomputation for " << clients.size() << " clients.";
+ index_map.clear();
if(start_mix(&cmix_ctx, clients.size()) != no_error) {
exit(-1);
}
- int i = 0;
+ unsigned int i = 0;
for(auto&& pair : clients) {
index_map[pair.first] = i++;
- generate_random_message(&cmix_ctx, i);
}
if(initialize_mix_randomness(&cmix_ctx) != no_error) {
@@ -148,15 +170,54 @@ void Node::start_precomputation() {
cmix_proto::PrePre prepre;
for(size_t i = 0; i < cmix_ctx.nr_participants; ++i) {
+ prepre.add_m_er();
+ prepre.add_r_er();
+
size_t len = get_group_element_array_size(&cmix_ctx);
prepre.mutable_r_er(i)->resize(len);
prepre.mutable_m_er(i)->resize(len);
+ {
+ std::stringstream ss;
+ ss << "r: ";
+ std::string r = to_string(cmix_ctx.r[i], cmix_ctx);
+ for(auto&& c : r) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+
if(encrypt_r(&cmix_ctx, &(*prepre.mutable_r_er(i))[0], &(*prepre.mutable_m_er(i))[0], i) != no_error) {
exit(-1);
}
}
+ BOOST_LOG_TRIVIAL(trace) << "Sending prepre message: " << prepre.ShortDebugString();
next_node.async_send(prepre);
}
+
+void Node::start_realtime_phase() {
+
+ cmix_proto::RealPre realpre;
+
+ size_t len = get_group_element_array_size(&cmix_ctx);
+ for(auto&& pair : index_map) {
+ realpre.add_h();
+ realpre.add_m();
+ realpre.mutable_m(pair.second)->resize(len);
+ std::decay<decltype(pair)>::type::first_type const& handle = pair.first;
+ std::decay<decltype(pair)>::type::second_type const& index = pair.second;
+
+ auto& queue = messages[pair.first];
+ if(queue.empty()) {
+ std::vector<char> v(len);
+ generate_random_message(&cmix_ctx, v.data());
+ swap_k_for_r(&cmix_ctx, &(*realpre.mutable_m(index))[0], v.data(), data[handle].shared_value, index);
+ } else {
+ swap_k_for_r(&cmix_ctx, &(*realpre.mutable_m(index))[0], queue.front().data(), data[handle].shared_value, index);
+ }
+ *realpre.mutable_h(index) = handle;
+ }
+ next_node.async_send(realpre);
+}
diff --git a/node/node.hpp b/node/node.hpp
index a4c7992..b166c71 100644
--- a/node/node.hpp
+++ b/node/node.hpp
@@ -14,11 +14,23 @@
#include <list>
#include <string>
+#include <queue>
+#include <iomanip>
/*!
* \file
*/
+#ifndef NDEBUG
+inline std::string to_string(GroupElement el, CMixContext const& ctx) {
+ std::string ret;
+ ret.resize(get_group_element_array_size(&ctx));
+
+ element_to_buffer(&ctx, &ret[0], el);
+ return ret;
+}
+#endif
+
/*!
* \brief The NodeNetworkSettings struct
*/
@@ -30,29 +42,17 @@ struct NodeNetworkSettings {
std::string certdir; ///< Directory containing trusted certificate authorities.
};
-struct MixData {
- GroupElement r;
- GroupElement s;
- std::string client_handle;
- size_t new_location;
-
- ~MixData(){
- Api api = get_implementation();
- api.free_group_element(r);
- api.free_group_element(s);
- }
-};
-
/*!
* \brief The Node class
*/
class Node
{
struct CMixClientData {
- SharedKey shared_value;
+ GroupElement shared_value;
};
boost::asio::io_service io_service;
+ boost::asio::deadline_timer timer;
std::shared_ptr<boost::asio::ssl::context> ssl_ctx;
Server server;
@@ -63,6 +63,8 @@ class Node
ClientConnections clients;
typedef std::map<std::string, CMixClientData> ClientData;
ClientData data;
+ typedef std::map<std::string, std::queue<std::string>> ClientMessages;
+ ClientMessages messages;
NodeNetworkSettings network_settings;
@@ -71,26 +73,29 @@ class Node
CMixContext cmix_ctx;
- std::vector<MixData> precomputation_data;
- std::map<std::string, int> index_map;
+ std::map<std::string, unsigned int> index_map;
bool shutting_down;
void accept_handler(std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>&& socket, std::shared_ptr<boost::asio::ssl::context> ctx);
void connect_to_next_node();
- void start_precomputation();
void start_initialisation();
+ void start_precomputation();
+ void start_realtime_phase();
void handle_node_initialization(cmix_proto::Initialization const& init);
void handle_node_secretkey(cmix_proto::SecretKey const& secret);
void handle_node_prepre(cmix_proto::PrePre const& prepre);
void handle_node_premix(cmix_proto::PreMix const& premix);
void handle_node_prepost(cmix_proto::PrePost const& prepost);
+ void handle_node_realpre(cmix_proto::RealPre const& realpre);
+ void handle_node_realmix(cmix_proto::RealMix const& realmix);
void handle_node_message(cmix_proto::CMixMessage message);
void handle_client_keyexchange(ClientConnections::key_type handle, cmix_proto::KeyExchange const& ke);
void handle_client_bye(ClientConnections::key_type handle, cmix_proto::Bye const&);
+ void handle_client_usermessage(ClientConnections::key_type handle, cmix_proto::UserMessage const& um);
void handle_client_message(ClientConnections::key_type handle, cmix_proto::CMixMessage message);
void handle_imanode(Purgatory::iterator handle, cmix_proto::ImANode const&);
diff --git a/node/node_client.cpp b/node/node_client.cpp
index f60c48d..baf4251 100644
--- a/node/node_client.cpp
+++ b/node/node_client.cpp
@@ -10,7 +10,7 @@ void Node::handle_client_keyexchange(ClientConnections::key_type handle, cmix_pr
nke.mutable_public_key()->resize(len);
nke.mutable_value()->resize(len);
- key_exchange_responder(&cmix_ctx, &d.shared_value.shared, &(*nke.mutable_public_key())[0], &(*nke.mutable_value())[0], ke.public_key().data(), ke.value().data());
+ key_exchange_responder(&cmix_ctx, &d.shared_value, &(*nke.mutable_public_key())[0], &(*nke.mutable_value())[0], ke.public_key().data(), ke.value().data());
data[handle] = d;
@@ -23,6 +23,14 @@ void Node::handle_client_bye(ClientConnections::key_type handle, cmix_proto::Bye
clients.erase(handle);
}
+void Node::handle_client_usermessage(ClientConnections::key_type handle, cmix_proto::UserMessage const& um) {
+ if(!network_settings.is_first) {
+ BOOST_LOG_TRIVIAL(warning) << "Received a user message but I'm not the first node, ignoring.";
+ return;
+ }
+ messages[handle].push(um.m());
+}
+
void Node::handle_client_message(ClientConnections::key_type handle, cmix_proto::CMixMessage message)
{
switch(message.contents_case()) {
@@ -36,6 +44,11 @@ void Node::handle_client_message(ClientConnections::key_type handle, cmix_proto:
handle_client_bye(handle, message.bye());
return;
}
+ case cmix_proto::CMixMessage::ContentsCase::kUsermessage: {
+ BOOST_LOG_TRIVIAL(trace) << "Handling user message";
+ handle_client_usermessage(handle, message.usermessage());
+ break;
+ }
default: {
BOOST_LOG_TRIVIAL(error) << "handle_client_message: CMixMessage contains unknown contents.";
}
diff --git a/node/node_node.cpp b/node/node_node.cpp
index eea9eb0..f24ff0a 100644
--- a/node/node_node.cpp
+++ b/node/node_node.cpp
@@ -13,12 +13,25 @@ cmix_proto::PrePre fill_precomputation_pre_message(CMixContext& ctx, T const& rs
cmix_proto::PrePre prepre;
- for(size_t i = 0; i < ctx.nr_participants; ++i) {
+ for(size_t i = 0; i < ms.size(); ++i) {
+ prepre.add_m_er();
+ prepre.add_r_er();
+
size_t len = get_group_element_array_size(&ctx);
prepre.mutable_m_er(i)->resize(len);
prepre.mutable_r_er(i)->resize(len);
+ {
+ std::stringstream ss;
+ ss << "r: ";
+ std::string r = to_string(ctx.r[i], ctx);
+ for(auto&& c : r) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+
if(encrypt_r_and_multiply(
&ctx,
&(*prepre.mutable_r_er(i))[0],
@@ -36,14 +49,29 @@ cmix_proto::PrePre fill_precomputation_pre_message(CMixContext& ctx, T const& rs
template <typename T>
cmix_proto::PreMix fill_precomputation_mix_message(CMixContext const& ctx, T const& rs, T const& ms) {
cmix_proto::PreMix premix;
- for(size_t i = 0; i < ctx.nr_participants; ++i) {
+
+ for(size_t i = 0; i < ms.size(); ++i) {
+ premix.add_r_epirs();
+ premix.add_m_epirs();
+ }
+ for(size_t i = 0; i < ms.size(); ++i) {
auto new_pos = ctx.permutation[i];
size_t el_len = get_group_element_array_size(&ctx);
premix.mutable_r_epirs(new_pos)->resize(el_len);
premix.mutable_m_epirs(new_pos)->resize(el_len);
- multiply_s(
+ {
+ std::stringstream ss;
+ ss << "s: ";
+ std::string s = to_string(ctx.s[i], ctx);
+ for(auto&& c : s) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+
+ multiply_encrypted_s(
&ctx,
&(*premix.mutable_r_epirs(new_pos))[0],
&(*premix.mutable_m_epirs(new_pos))[0],
@@ -59,7 +87,10 @@ template <typename T>
cmix_proto::PrePost fill_precomputation_post_message(CMixContext& ctx, T const& rs, T const& ms) {
cmix_proto::PrePost prepost;
- for(size_t i = 0; i < ctx.nr_participants; ++i) {
+ for(size_t i = 0; i < ms.size(); ++i) {
+ prepost.add_r_epirs();
+ prepost.add_m_epirs();
+
size_t el_len = get_group_element_array_size(&ctx);
prepost.mutable_r_epirs(i)->resize(el_len);
@@ -74,6 +105,16 @@ cmix_proto::PrePost fill_precomputation_post_message(CMixContext& ctx, T const&
i
);
+ {
+ std::stringstream ss;
+ ss << "pirs: ";
+ std::string pirs = to_string(ctx.pirs[i], ctx);
+ for(auto&& c : pirs) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+
*prepost.mutable_r_epirs(i) = rs.Get(i);
*prepost.mutable_m_epirs(i) = ms.Get(i);
}
@@ -81,6 +122,56 @@ cmix_proto::PrePost fill_precomputation_post_message(CMixContext& ctx, T const&
return prepost;
}
+template <typename T>
+cmix_proto::RealPre fill_realtime_pre_message(CMixContext& ctx, T const& hs, T const& ms, Node::ClientData const& data) {
+ cmix_proto::RealPre realpre;
+
+ size_t len = get_group_element_array_size(&ctx);
+ for(int i = 0; i < ms.size(); ++i) {
+ realpre.add_h();
+ realpre.add_m();
+ realpre.mutable_m(i)->resize(len);
+
+ swap_k_for_r(
+ &ctx,
+ &(*realpre.mutable_m(i))[0],
+ ms.Get(i).data(),
+ data.at(hs.Get(i)).shared_value,
+ i
+ );
+ *realpre.mutable_h(i) = hs.Get(i);
+ }
+
+ return realpre;
+}
+
+template <typename T>
+cmix_proto::RealMix fill_realtime_mix_message(CMixContext& ctx, T const& ms) {
+ cmix_proto::RealMix realmix;
+
+ size_t len = get_group_element_array_size(&ctx);
+
+ for(int i = 0; i < ms.size(); ++i) {
+ realmix.add_m();
+ }
+
+ for(int i = 0; i < ms.size(); ++i) {
+ auto new_pos = ctx.permutation[i];
+
+ realmix.mutable_m(i)->resize(len);
+
+ multiply_s(
+ &ctx,
+ &(*realmix.mutable_m(new_pos))[0],
+ ms.Get(i).data(),
+ i
+ );
+
+ }
+
+ return realmix;
+}
+
void Node::handle_node_initialization(const cmix_proto::Initialization& init)
{
if(network_settings.is_first) {
@@ -97,7 +188,7 @@ void Node::handle_node_initialization(const cmix_proto::Initialization& init)
n_init.mutable_public_share()->resize(len);
add_public_share(&cmix_ctx, &(*n_init.mutable_public_share())[0], init.public_share().data());
- BOOST_LOG_TRIVIAL(trace) << "Sending intialization";
+ BOOST_LOG_TRIVIAL(trace) << "sending message: " << n_init.ShortDebugString();
next_node.async_send(n_init);
}
}
@@ -109,7 +200,10 @@ void Node::handle_node_secretkey(cmix_proto::SecretKey const& secret)
set_network_key(&cmix_ctx, secret.secret_key().data(), secret.secret_key().size());
if(network_settings.is_first) {
- start_precomputation();
+ timer.expires_from_now(boost::posix_time::seconds(4));
+ timer.async_wait([this](boost::system::error_code const& ec) {
+ start_precomputation();
+ });
} else {
next_node.async_send(secret);
}
@@ -137,15 +231,54 @@ void Node::handle_node_premix(cmix_proto::PreMix const& premix) {
void Node::handle_node_prepost(cmix_proto::PrePost const& prepost) {
if(network_settings.is_first) {
-
+ start_realtime_phase();
} else {
cmix_proto::PrePost n_prepost = fill_precomputation_post_message(cmix_ctx, prepost.r_epirs(), prepost.m_epirs());
next_node.async_send(n_prepost);
}
}
+void Node::handle_node_realpre(cmix_proto::RealPre const& realpre) {
+ if(network_settings.is_first) {
+ cmix_proto::RealMix n_realmix = fill_realtime_mix_message(cmix_ctx, realpre.m());
+ next_node.async_send(n_realmix);
+ } else {
+ cmix_proto::RealPre n_realpre = fill_realtime_pre_message(cmix_ctx, realpre.h(), realpre.m(), data);
+ next_node.async_send(n_realpre);
+ }
+}
+
+void Node::handle_node_realmix(cmix_proto::RealMix const& realmix) {
+ if(network_settings.is_last) {
+ BOOST_LOG_TRIVIAL(trace) << "Doing the last step:";
+
+ cmix_proto::RealMix n_realmix = fill_realtime_mix_message(cmix_ctx, realmix.m());
+
+ size_t len = get_group_element_array_size(&cmix_ctx);
+ std::string str;
+ str.resize(len);
+
+ for(int i = 0; i < n_realmix.m_size(); i++) {
+ remove_r_and_s(&cmix_ctx, &str[0], n_realmix.m(i).data(), i);
+
+ {
+ std::stringstream ss;
+ for(auto&& c : str) {
+ ss << "\\" << std::setw(3) << std::setfill('0') << std::oct << (unsigned int) c;
+ }
+ BOOST_LOG_TRIVIAL(trace) << ss.str();
+ }
+ }
+
+ } else {
+ cmix_proto::RealMix n_realmix = fill_realtime_mix_message(cmix_ctx, realmix.m());
+ next_node.async_send(n_realmix);
+ }
+}
+
void Node::handle_node_message(cmix_proto::CMixMessage message)
{
+ BOOST_LOG_TRIVIAL(trace) << "Message: " << message.ShortDebugString();
switch(message.contents_case()) {
case cmix_proto::CMixMessage::ContentsCase::kInitialization: {
BOOST_LOG_TRIVIAL(trace) << "Handling initialization";
@@ -177,6 +310,16 @@ void Node::handle_node_message(cmix_proto::CMixMessage message)
handle_node_prepost(message.prepost());
break;
}
+ case cmix_proto::CMixMessage::ContentsCase::kRealpre: {
+ BOOST_LOG_TRIVIAL(trace) << "Handling RealPre";
+ handle_node_realpre(message.realpre());
+ break;
+ }
+ case cmix_proto::CMixMessage::ContentsCase::kRealmix: {
+ BOOST_LOG_TRIVIAL(trace) << "Handling RealMix";
+ handle_node_realmix(message.realmix());
+ break;
+ }
default: {
BOOST_LOG_TRIVIAL(error) << "handle_node_message: CMixMessage contains unknown contents.";
}