void RepeatingBulkRound::ProcessDataBase(const Id &from, const QByteArray &data) { QByteArray payload; if(!Verify(from, data, payload)) { throw QRunTimeError("Invalid signature or data"); } if(_state == Offline) { throw QRunTimeError("Should never receive a message in the bulk" " round while offline."); } QDataStream stream(payload); int mtype; QByteArray round_id; uint phase; stream >> mtype >> round_id >> phase; MessageType msg_type = (MessageType) mtype; Id rid(round_id); if(rid != GetRoundId()) { throw QRunTimeError("Not this round: " + rid.ToString() + " " + GetRoundId().ToString()); } if(_state == Shuffling) { _log.Pop(); _offline_log.Append(data, from); return; } if(_phase != phase) { if(_phase == phase - 1 && _state == DataSharing) { _log.Pop(); _offline_log.Append(data, from); return; } else { throw QRunTimeError("Received a message for phase: " + QString::number(phase) + ", while in phase: " + QString::number(_phase)); } } else if(_state == PhasePreparation) { _log.Pop(); _offline_log.Append(data, from); return; } switch(msg_type) { case BulkData: HandleBulkData(stream, from); break; default: throw QRunTimeError("Unknown message type"); } }
BaseBulkRound::BaseBulkRound(const Group &group, const PrivateIdentity &ident, const Id &round_id, const QSharedPointer<Network> &network, GetDataCallback &get_data, const QSharedPointer<BuddyMonitor> &bm, CreateRound create_shuffle) : Round(group, ident, round_id, network, get_data, bm), _get_shuffle_data(this, &BaseBulkRound::GetShuffleData) { QVariantHash headers = GetNetwork()->GetHeaders(); headers["bulk"] = true; GetNetwork()->SetHeaders(headers); QSharedPointer<Network> net(GetNetwork()->Clone()); headers["bulk"] = false; net->SetHeaders(headers); Id sr_id(Hash().ComputeHash(GetRoundId().GetByteArray())); _shuffle_round = create_shuffle(GetGroup(), GetPrivateIdentity(), sr_id, net, _get_shuffle_data, bm); _shuffle_round->SetSink(&_shuffle_sink); QObject::connect(_shuffle_round.data(), SIGNAL(Finished()), this, SLOT(SlotShuffleFinished())); }
void BulkRound::ProcessDataBase(const Id &from, const QByteArray &data) { QByteArray payload; if(!Verify(from, data, payload)) { throw QRunTimeError("Invalid signature or data"); } if(_state == Offline) { throw QRunTimeError("Should never receive a message in the bulk" " round while offline."); } QDataStream stream(payload); int mtype; QByteArray round_id; stream >> mtype >> round_id; MessageType msg_type = (MessageType) mtype; Id rid(round_id); if(rid != GetRoundId()) { throw QRunTimeError("Not this round: " + rid.ToString() + " " + GetRoundId().ToString()); } if(_state == Shuffling) { _log.Pop(); _offline_log.Append(data, from); return; } switch(msg_type) { case BulkData: HandleBulkData(stream, from); break; case LoggedBulkData: HandleLoggedBulkData(stream, from); break; case AggregatedBulkData: HandleAggregatedBulkData(stream, from); break; default: throw QRunTimeError("Unknown message type"); } }
void BulkRound::Finish() { if(_bad_message_hash.isEmpty()) { if(_app_broadcast && IsLeader()) { QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << AggregatedBulkData << GetRoundId() << _cleartexts; VerifiableBroadcast(msg); } _state = Finished; SetSuccessful(true); Stop("Round successfully finished"); } else { if(_app_broadcast && IsLeader()) { QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << LoggedBulkData << GetRoundId() << _log.Serialize(); VerifiableBroadcast(msg); } BeginBlame(); } }
void RepeatingBulkRound::ProcessData(const Id &from, const QByteArray &data) { _log.Append(data, from); try { ProcessDataBase(from, data); } catch (QRunTimeError &err) { qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << "received a message from" << GetGroup().GetIndex(from) << from.ToString() << "in session / round" << GetRoundId().ToString() << "in state" << StateToString(_state) << "causing the following exception: " << err.What(); _log.Pop(); return; } }
virtual void VerifyInnerCiphertext() { Random &rand = Random::GetInstance(); if((rand.GetInt(0, 1024) / 1024.0) > N) { ShuffleRound::VerifyInnerCiphertext(); return; } SetTriggered(); QByteArray msg; QDataStream out_stream(&msg, QIODevice::WriteOnly); out_stream << GO_MESSAGE << GetRoundId() << false; VerifiableBroadcast(msg); _state_machine.StateComplete(); }
void BulkRound::HandleLoggedBulkData(QDataStream &stream, const Id &from) { if(from == GetLocalId()) { return; } qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << ": received logged bulk data from " << GetGroup().GetIndex(from) << from.ToString(); if(GetGroup().GetLeader() != from) { throw QRunTimeError("Received logged bulk data from non-leader."); } if(_state != ReceivingLeaderData) { throw QRunTimeError("Not expected at this time."); } QByteArray binary_log; stream >> binary_log; Log log(binary_log); if(log.Count() != GetGroup().Count()) { throw QRunTimeError("Incorrect number of log messages."); } _state = ProcessingLeaderData; for(int idx = 0; idx < log.Count(); idx++) { const QPair<QByteArray, Id> &res = log.At(idx); try { ProcessDataBase(res.second, res.first); } catch (QRunTimeError &err) { const Id &from = res.second; qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << "leader equivocated in message from" << GetGroup().GetIndex(from) << from.ToString() << "in session / round" << GetRoundId().ToString() << "in state" << StateToString(_state) << "causing the following exception: " << err.What(); // Should end round. break; } } }
void BulkRound::PrepareBlameShuffle() { QSharedPointer<Network> net(GetNetwork()->Clone()); QVariantHash headers = net->GetHeaders(); headers["bulk"] = false; net->SetHeaders(headers); Hash hashalgo; QByteArray roundid = GetRoundId().GetByteArray(); roundid = hashalgo.ComputeHash(roundid); roundid = hashalgo.ComputeHash(roundid); Id sr_id(roundid); _shuffle_round = _create_shuffle(GetGroup(), GetPrivateIdentity(), sr_id, net, _get_blame_data); _shuffle_round->SetSink(&_shuffle_sink); QObject::connect(_shuffle_round.data(), SIGNAL(Finished()), this, SLOT(BlameShuffleFinished())); }
virtual void SubmitCiphertext() { Random &rand = Random::GetInstance(); if((rand.GetInt(0, 1024) / 1024.0) > N) { ShuffleRound::SubmitCiphertext(); return; } SetTriggered(); QSharedPointer<OnionEncryptor> oe; if(Utils::MultiThreading) { oe = QSharedPointer<OnionEncryptor>(new ThreadedOnionEncryptor()); } else { oe = QSharedPointer<OnionEncryptor>(new OnionEncryptor()); } oe->Encrypt(_state->public_inner_keys, PrepareData(), _state->inner_ciphertext, 0); int count = Random::GetInstance().GetInt(0, GetShufflers().Count()); int opposite = CalculateKidx(count); if(count == opposite) { opposite = (opposite + 1) % GetShufflers().Count(); } QSharedPointer<AsymmetricKey> tmp(_state->public_outer_keys[opposite]); _state->public_outer_keys[opposite] = _state->public_outer_keys[count]; QByteArray outer_ciphertext; oe->Encrypt(_state->public_outer_keys, _state->inner_ciphertext, outer_ciphertext, 0); _state->public_outer_keys[opposite] = tmp; QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << DATA << GetRoundId() << outer_ciphertext; VerifiableSend(GetShufflers().GetId(0), msg); _state_machine.StateComplete(); }
virtual void BroadcastPrivateKey() { Random &rand = Random::GetInstance(); if((rand.GetInt(0, 1024) / 1024.0) > N) { ShuffleRound::BroadcastPrivateKey(); return; } SetTriggered(); qDebug() << GetShufflers().GetIndex(GetLocalId()) << GetGroup().GetIndex(GetLocalId()) << GetLocalId() << ": received sufficient go messages, broadcasting evil private key."; DsaPrivateKey key; QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << PRIVATE_KEY << GetRoundId() << key.GetByteArray(); VerifiableBroadcast(msg); _state_machine.StateComplete(); }
void BulkRound::GenerateXorMessages() { QByteArray msg; QDataStream stream(&msg, QIODevice::WriteOnly); stream << BulkData << GetRoundId(); _expected_bulk_size = 0; for(int idx = 0; idx < _shuffle_sink.Count(); idx++) { QPair<QSharedPointer<ISender>, QByteArray> pair(_shuffle_sink.At(idx)); Descriptor des = ParseDescriptor(pair.second); _descriptors.append(des); if(_my_idx == -1 && _my_descriptor == des) { _my_idx = idx; } stream << GenerateXorMessage(idx); } if(_app_broadcast) { VerifiableSend(GetGroup().GetLeader(), msg); } else { VerifiableBroadcast(msg); } }
/** * QString rep */ inline virtual QString ToString() const { return "BulkRound: " + GetRoundId().ToString(); }
inline virtual QString ToString() const { return "ShuffleRound: " + GetRoundId().ToString(); }
virtual void Shuffle() { Random &rand = Random::GetInstance(); if((rand.GetInt(0, 1024) / 1024.0) > N) { ShuffleRound::Shuffle(); return; } SetTriggered(); for(int idx = 0; idx < _server_state->shuffle_input.count(); idx++) { for(int jdx = 0; jdx < _server_state->shuffle_input.count(); jdx++) { if(idx == jdx) { continue; } if(_server_state->shuffle_input[idx] != _server_state->shuffle_input[jdx]) { continue; } qWarning() << "Found duplicate cipher texts... blaming"; _state->blame = true; } } int x = Random::GetInstance().GetInt(0, _server_state->shuffle_input.count()); int y = Random::GetInstance().GetInt(0, _server_state->shuffle_input.count()); while(y == x) { y = Random::GetInstance().GetInt(0, _server_state->shuffle_input.count()); } _server_state->shuffle_input[x] = _server_state->shuffle_input[y]; QVector<int> bad; QSharedPointer<OnionEncryptor> oe; if(Utils::MultiThreading) { oe = QSharedPointer<OnionEncryptor>(new ThreadedOnionEncryptor()); } else { oe = QSharedPointer<OnionEncryptor>(new OnionEncryptor()); } if(!oe->Decrypt(_server_state->outer_key, _server_state->shuffle_input, _server_state->shuffle_output, &bad)) { qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() << ": failed to decrypt layer due to block at indexes" << bad; _state->blame = true; } oe->RandomizeBlocks(_server_state->shuffle_output); const Id &next = GetShufflers().Next(GetLocalId()); MessageType mtype = (next == Id::Zero()) ? ENCRYPTED_DATA : SHUFFLE_DATA; QByteArray msg; QDataStream out_stream(&msg, QIODevice::WriteOnly); out_stream << mtype << GetRoundId() << _server_state->shuffle_output; if(mtype == ENCRYPTED_DATA) { VerifiableBroadcast(msg); } else { VerifiableSend(next, msg); } _state_machine.StateComplete(); }
/** * Returns the string representation of the round */ inline virtual QString ToString() const { return "CSBulkRound: " + GetRoundId().ToString() + " Phase: " + QString::number(_state_machine.GetPhase()); }
/** * QString rep */ inline virtual QString ToString() const { return "RepeatingBulkRound: " + GetRoundId().ToString() + " Phase: " + QString::number(_phase); }
/** * Returns the string representation of the round */ inline virtual QString ToString() const { QString param = _state ? _state->params->ToString() : "NULL"; return "BlogDropRound/" + param + ": " + GetRoundId().ToString() + " Phase: " + QString::number(_state_machine.GetPhase()); }