Restructured p2p message signing keys.

This commit is contained in:
Ravin Perera
2019-10-28 18:27:52 +05:30
parent 7a6f835f44
commit 2715ff7242
8 changed files with 145 additions and 148 deletions

View File

@@ -48,26 +48,87 @@ int validate_and_extract_container(const Container **container_ref, std::string_
//Verify container message using flatbuffer verifier
if (!VerifyContainerBuffer(container_verifier))
{
LOG_DBG << "Flatbuffer verify: Bad container.";
LOG_DBG << "Flatbuffer verify: Bad peer message container.";
return -1;
}
//Get message container
const Container *container = GetContainer(container_buf_ptr);
//Validation are prioritzed base on expensiveness of validation.
//i.e - signature validation is done at the end.
//check protocol version of message whether it is greater than minimum supported protocol version.
const uint16_t version = container->version();
if (version < util::MIN_PEERMSG_VERSION)
{
LOG_DBG << "Recieved message is from unsupported protocol version (" << version << ")";
LOG_DBG << "Peer message is from unsupported protocol version (" << version << ").";
return -1;
}
int64_t time_now = util::get_epoch_milliseconds();
//check message timestamp.
if (container->timestamp() < (time_now - conf::cfg.roundtime * 4))
{
LOG_DBG << "Peer message is too old.";
return -1;
}
// After signature is verified, get message hash and see wheteher
// message is already recieved -> abandon if duplicate.
// auto messageHash = crypto::sha_512_hash(message, "PEERMSG", 7);
// if (recent_peer_msghash.count(messageHash) == 0)
// {
// recent_peer_msghash.try_emplace(std::move(messageHash), timestamp);
// }
// else
// {
// LOG_DBG << "Duplicate message";
// return -1;
// }
//Assign container and content out params.
*container_ref = container;
return 0;
}
/**
* Validates the container message signing keys to see if the message is from a trusted source (UNL).
* @return 0 on successful verification. -1 for failure.
*/
int validate_container_trust(const Container *container)
{
std::string_view msg_pubkey = flatbuff_bytes_to_sv(container->pubkey());
std::string_view msg_sig = flatbuff_bytes_to_sv(container->signature());
if (msg_pubkey.empty() || msg_sig.empty())
{
LOG_DBG << "Peer message key pair incomplete. Trust verification failed.";
return -1;
}
//validate if the message is not from a node of current node's unl list.
if (!conf::cfg.unl.count(std::string(msg_pubkey)))
{
LOG_DBG << "Peer message pubkey verification failed. Not in UNL.";
return -1;
}
//verify message signature.
//this is performed towards end since this is bit expensive
std::string_view msg_content = flatbuff_bytes_to_sv(container->content());
if (crypto::verify(msg_content, msg_sig, msg_pubkey) != 0)
{
LOG_DBG << "Peer message signature verification failed.";
return -1;
}
return 0;
}
/**
* Verifies the Content message structure and outputs faltbuffer Content pointer to access the given buffer.
*
@@ -94,81 +155,17 @@ int validate_and_extract_content(const Content **content_ref, const uint8_t *con
return 0;
}
/**
* Validate the incoming p2p message content on several criteria.
*
* @param message Message content data buffer.
* @param signature Binary message signature.
* @param pubkey Binary public key of message originating node.
* @param timestamp Message timestamp.
* @param version Message protocol version.
* @return 0 on successful validation. -1 for failure.
*/
int validate_content_message(std::string_view message, std::string_view signature, std::string_view pubkey, int64_t timestamp)
{
//Validation are prioritzed base on expensiveness of validation.
//i.e - signature validation is done at the end.
int64_t time_now = util::get_epoch_milliseconds();
// validate if the message is not from a node of current node's unl list.
if (!conf::cfg.unl.count(pubkey.data()))
{
LOG_DBG << "pubkey verification failed";
return -1;
}
//check message timestamp. < timestamp now - 4* round time.
/*todo:this might change to check only current stage related. (Base on how consensus algorithm implementation take shape)
check message stage is for valid stage(node's current consensus stage - 1)
*/
if (timestamp < (time_now - conf::cfg.roundtime * 4))
{
LOG_DBG << "Recieved message from peer is old";
return -1;
}
//verify message signature.
//this should be the last validation since this is bit expensive
auto signature_verified = crypto::verify(message, signature, pubkey);
if (signature_verified != 0)
{
LOG_DBG << "Signature verification failed";
return -1;
}
// After signature is verified, get message hash and see wheteher
// message is already recieved -> abandon if duplicate.
// auto messageHash = crypto::sha_512_hash(message, "PEERMSG", 7);
// if (recent_peer_msghash.count(messageHash) == 0)
// {
// recent_peer_msghash.try_emplace(std::move(messageHash), timestamp);
// }
// else
// {
// LOG_DBG << "Duplicate message";
// return -1;
// }
return 0;
}
/**
* Creates a proposal stuct from the given proposal message.
* @param The Flatbuffer poporal received from the peer.
* @return A proposal struct representing the message.
*/
const proposal create_proposal_from_msg(const Proposal_Message &msg)
const proposal create_proposal_from_msg(const Proposal_Message &msg, const flatbuffers::Vector<uint8_t> *pubkey)
{
proposal p;
if (msg.pubkey())
p.pubkey = flatbuff_bytes_to_sv(msg.pubkey());
p.pubkey = flatbuff_bytes_to_sv(pubkey);
p.time = msg.time();
p.timestamp = msg.timestamp();
p.stage = msg.stage();
if (msg.lcl())
@@ -208,8 +205,6 @@ void create_msg_from_proposal(flatbuffers::FlatBufferBuilder &container_builder,
flatbuffers::Offset<Proposal_Message> proposal =
CreateProposal_Message(
builder,
sv_to_flatbuff_bytes(builder, conf::cfg.pubkey),
p.timestamp,
p.stage,
p.time,
sv_to_flatbuff_bytes(builder, p.lcl),
@@ -224,7 +219,7 @@ void create_msg_from_proposal(flatbuffers::FlatBufferBuilder &container_builder,
// Now that we have built the content message,
// we need to sign it and place it inside a container message.
create_containermsg_from_content(container_builder, builder);
create_containermsg_from_content(container_builder, builder, true);
}
/**
@@ -232,9 +227,10 @@ void create_msg_from_proposal(flatbuffers::FlatBufferBuilder &container_builder,
* @param container_builder The Flatbuffer builder to which the final container message should be written to.
* @param content_builder The Flatbuffer builder containing the content message that should be placed
* inside the container message.
* @param sign Whether to sign the message content.
*/
void create_containermsg_from_content(
flatbuffers::FlatBufferBuilder &container_builder, const flatbuffers::FlatBufferBuilder &content_builder)
flatbuffers::FlatBufferBuilder &container_builder, const flatbuffers::FlatBufferBuilder &content_builder, bool sign)
{
uint8_t *content_buf = content_builder.GetBufferPointer();
flatbuffers::uoffset_t content_size = content_builder.GetSize();
@@ -242,14 +238,24 @@ void create_containermsg_from_content(
// Create container message content from serialised content from previous step.
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> content = container_builder.CreateVector(content_buf, content_size);
// Sign message content with this node's private key.
std::string_view content_to_sign(reinterpret_cast<const char *>(content_buf), content_size);
std::string sig = crypto::sign(content_to_sign, conf::cfg.seckey);
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> pubkey_offset = 0;
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> sig_offset = 0;
if (sign)
{
// Sign message content with this node's private key.
std::string_view content_to_sign(reinterpret_cast<const char *>(content_buf), content_size);
sig_offset = sv_to_flatbuff_bytes(container_builder, crypto::sign(content_to_sign, conf::cfg.seckey));
pubkey_offset = sv_to_flatbuff_bytes(container_builder, conf::cfg.pubkey);
}
flatbuffers::Offset<Container> container_message = CreateContainer(
container_builder,
util::PEERMSG_VERSION,
sv_to_flatbuff_bytes(container_builder, sig), //signature field
util::get_epoch_milliseconds(),
pubkey_offset,
sig_offset,
content);
// Finish building message container to get serialised message.