mirror of https://github.com/poanetwork/hbbft.git
Remove generic ciphertext argument from Part and Ack messages.
This commit is contained in:
parent
824a43100b
commit
fe17fc9850
|
@ -174,12 +174,13 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
use std::string::ToString;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bincode;
|
use bincode;
|
||||||
use failure::Fail;
|
use failure::Fail;
|
||||||
use rand::{self, Rng};
|
use rand::{self, Rng};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::crypto::{
|
use crate::crypto::{
|
||||||
self,
|
self,
|
||||||
|
@ -193,38 +194,43 @@ use crate::NodeIdT;
|
||||||
|
|
||||||
/// A cryptographic key that allows decrypting messages that were encrypted to the key's owner.
|
/// A cryptographic key that allows decrypting messages that were encrypted to the key's owner.
|
||||||
pub trait SecretKey {
|
pub trait SecretKey {
|
||||||
/// The encrypted form of a message in this cryptosystem.
|
/// The decryption error type.
|
||||||
type Ciphertext: Serialize + DeserializeOwned;
|
type Error: ToString;
|
||||||
|
|
||||||
/// Decrypts a ciphertext; returns `None` if it was invalid.
|
/// Decrypts a ciphertext.
|
||||||
fn decrypt(&self, ct: &Self::Ciphertext) -> Option<Vec<u8>>;
|
fn decrypt(&self, ct: &[u8]) -> Result<Vec<u8>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A cryptographic public key that allows encrypting messages to the key's owner.
|
/// A cryptographic public key that allows encrypting messages to the key's owner.
|
||||||
pub trait PublicKey {
|
pub trait PublicKey {
|
||||||
/// The encrypted form of a message in this cryptosystem.
|
/// The encryption error type.
|
||||||
type Ciphertext: Serialize + DeserializeOwned;
|
type Error: ToString;
|
||||||
/// The corresponding secret key type. The secret key is known only to the key's owner.
|
/// The corresponding secret key type. The secret key is known only to the key's owner.
|
||||||
type SecretKey: SecretKey<Ciphertext = Self::Ciphertext>;
|
type SecretKey: SecretKey;
|
||||||
|
|
||||||
/// Encrypts a message to this key's owner and returns the ciphertext.
|
/// Encrypts a message to this key's owner and returns the ciphertext.
|
||||||
fn encrypt<M: AsRef<[u8]>, R: Rng>(&self, msg: M, rng: &mut R) -> Self::Ciphertext;
|
fn encrypt<M: AsRef<[u8]>, R: Rng>(&self, msg: M, rng: &mut R) -> Result<Vec<u8>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecretKey for crypto::SecretKey {
|
impl SecretKey for crypto::SecretKey {
|
||||||
type Ciphertext = crypto::Ciphertext;
|
type Error = bincode::Error;
|
||||||
|
|
||||||
fn decrypt(&self, ct: &crypto::Ciphertext) -> Option<Vec<u8>> {
|
fn decrypt(&self, ct: &[u8]) -> Result<Vec<u8>, bincode::Error> {
|
||||||
self.decrypt(ct)
|
self.decrypt(&bincode::deserialize(ct)?)
|
||||||
|
.ok_or_else(|| bincode::ErrorKind::Custom("Invalid ciphertext.".to_string()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PublicKey for crypto::PublicKey {
|
impl PublicKey for crypto::PublicKey {
|
||||||
type Ciphertext = crypto::Ciphertext;
|
type Error = bincode::Error;
|
||||||
type SecretKey = crypto::SecretKey;
|
type SecretKey = crypto::SecretKey;
|
||||||
|
|
||||||
fn encrypt<M: AsRef<[u8]>, R: Rng>(&self, msg: M, rng: &mut R) -> crypto::Ciphertext {
|
fn encrypt<M: AsRef<[u8]>, R: Rng>(
|
||||||
self.encrypt_with_rng(rng, msg)
|
&self,
|
||||||
|
msg: M,
|
||||||
|
rng: &mut R,
|
||||||
|
) -> Result<Vec<u8>, bincode::Error> {
|
||||||
|
bincode::serialize(&self.encrypt_with_rng(rng, msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +265,9 @@ pub enum Error {
|
||||||
/// Failed to serialize message.
|
/// Failed to serialize message.
|
||||||
#[fail(display = "Serialization error: {}", _0)]
|
#[fail(display = "Serialization error: {}", _0)]
|
||||||
Serialize(String),
|
Serialize(String),
|
||||||
|
/// Failed to encrypt message parts for a peer.
|
||||||
|
#[fail(display = "Encryption error: {}", _0)]
|
||||||
|
Encrypt(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<bincode::Error> for Error {
|
impl From<bincode::Error> for Error {
|
||||||
|
@ -267,6 +276,12 @@ impl From<bincode::Error> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
fn encrypt<E: ToString>(err: E) -> Error {
|
||||||
|
Error::Encrypt(err.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A submission by a validator for the key generation. It must to be sent to all participating
|
/// A submission by a validator for the key generation. It must to be sent to all participating
|
||||||
/// nodes and handled by all of them, including the one that produced it.
|
/// nodes and handled by all of them, including the one that produced it.
|
||||||
///
|
///
|
||||||
|
@ -274,9 +289,9 @@ impl From<bincode::Error> for Error {
|
||||||
/// row of values. If this message receives enough `Ack`s, it will be used as summand to produce
|
/// row of values. If this message receives enough `Ack`s, it will be used as summand to produce
|
||||||
/// the the key set in the end.
|
/// the the key set in the end.
|
||||||
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
|
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct Part<C = crypto::Ciphertext>(BivarCommitment, Vec<C>);
|
pub struct Part(BivarCommitment, Vec<Vec<u8>>);
|
||||||
|
|
||||||
impl<C> Debug for Part<C> {
|
impl Debug for Part {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_tuple("Part")
|
f.debug_tuple("Part")
|
||||||
.field(&format!("<degree {}>", self.0.degree()))
|
.field(&format!("<degree {}>", self.0.degree()))
|
||||||
|
@ -291,9 +306,9 @@ impl<C> Debug for Part<C> {
|
||||||
/// The message is only produced after we verified our row against the commitment in the `Part`.
|
/// The message is only produced after we verified our row against the commitment in the `Part`.
|
||||||
/// For each node, it contains one encrypted value of that row.
|
/// For each node, it contains one encrypted value of that row.
|
||||||
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
|
#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct Ack<C = crypto::Ciphertext>(u64, Vec<C>);
|
pub struct Ack(u64, Vec<Vec<u8>>);
|
||||||
|
|
||||||
impl<C> Debug for Ack<C> {
|
impl Debug for Ack {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_tuple("Ack")
|
f.debug_tuple("Ack")
|
||||||
.field(&self.0)
|
.field(&self.0)
|
||||||
|
@ -330,11 +345,11 @@ impl ProposalState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The outcome of handling and verifying a `Part` message.
|
/// The outcome of handling and verifying a `Part` message.
|
||||||
pub enum PartOutcome<C> {
|
pub enum PartOutcome {
|
||||||
/// The message was valid: the part of it that was encrypted to us matched the public
|
/// The message was valid: the part of it that was encrypted to us matched the public
|
||||||
/// commitment, so we can multicast an `Ack` message for it. If we are an observer or we have
|
/// commitment, so we can multicast an `Ack` message for it. If we are an observer or we have
|
||||||
/// already handled the same `Part` before, this contains `None` instead.
|
/// already handled the same `Part` before, this contains `None` instead.
|
||||||
Valid(Option<Ack<C>>),
|
Valid(Option<Ack>),
|
||||||
/// The message was invalid: We now know that the proposer is faulty, and dont' send an `Ack`.
|
/// The message was invalid: We now know that the proposer is faulty, and dont' send an `Ack`.
|
||||||
Invalid(PartFault),
|
Invalid(PartFault),
|
||||||
}
|
}
|
||||||
|
@ -347,9 +362,6 @@ pub enum AckOutcome {
|
||||||
Invalid(AckFault),
|
Invalid(AckFault),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either `None`, or a `Part` that can be used with the `PK` key type.
|
|
||||||
pub type OptPart<PK> = Option<Part<<PK as PublicKey>::Ciphertext>>;
|
|
||||||
|
|
||||||
/// A synchronous algorithm for dealerless distributed key generation.
|
/// A synchronous algorithm for dealerless distributed key generation.
|
||||||
///
|
///
|
||||||
/// It requires that all nodes handle all messages in the exact same order.
|
/// It requires that all nodes handle all messages in the exact same order.
|
||||||
|
@ -381,7 +393,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
pub_keys: PubKeyMap<N, PK>,
|
pub_keys: PubKeyMap<N, PK>,
|
||||||
threshold: usize,
|
threshold: usize,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> Result<(Self, OptPart<PK>), Error> {
|
) -> Result<(Self, Option<Part>), Error> {
|
||||||
let our_idx = pub_keys
|
let our_idx = pub_keys
|
||||||
.keys()
|
.keys()
|
||||||
.position(|id| *id == our_id)
|
.position(|id| *id == our_id)
|
||||||
|
@ -401,15 +413,15 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
let our_part = BivarPoly::random(threshold, rng);
|
let our_part = BivarPoly::random(threshold, rng);
|
||||||
let commit = our_part.commitment();
|
let commit = our_part.commitment();
|
||||||
let encrypt = |(i, pk): (usize, &PK)| {
|
let encrypt = |(i, pk): (usize, &PK)| {
|
||||||
let row = our_part.row(i + 1);
|
let row = bincode::serialize(&our_part.row(i + 1))?;
|
||||||
Ok(pk.encrypt(&bincode::serialize(&row)?, rng))
|
Ok(pk.encrypt(&row, rng).map_err(Error::encrypt)?)
|
||||||
};
|
};
|
||||||
let rows = key_gen
|
let rows = key_gen
|
||||||
.pub_keys
|
.pub_keys
|
||||||
.values()
|
.values()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(encrypt)
|
.map(encrypt)
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Vec<Vec<u8>>, Error>>()?;
|
||||||
Ok((key_gen, Some(Part(commit, rows))))
|
Ok((key_gen, Some(Part(commit, rows))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,9 +439,9 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
pub fn handle_part<R: rand::Rng>(
|
pub fn handle_part<R: rand::Rng>(
|
||||||
&mut self,
|
&mut self,
|
||||||
sender_id: &N,
|
sender_id: &N,
|
||||||
part: Part<PK::Ciphertext>,
|
part: Part,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
) -> Result<PartOutcome<PK::Ciphertext>, Error> {
|
) -> Result<PartOutcome, Error> {
|
||||||
let sender_idx = self.node_index(sender_id).ok_or(Error::UnknownSender)?;
|
let sender_idx = self.node_index(sender_id).ok_or(Error::UnknownSender)?;
|
||||||
let row = match self.handle_part_or_fault(sender_idx, part) {
|
let row = match self.handle_part_or_fault(sender_idx, part) {
|
||||||
Ok(Some(row)) => row,
|
Ok(Some(row)) => row,
|
||||||
|
@ -441,7 +453,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
for (idx, pk) in self.pub_keys.values().enumerate() {
|
for (idx, pk) in self.pub_keys.values().enumerate() {
|
||||||
let val = row.evaluate(idx + 1);
|
let val = row.evaluate(idx + 1);
|
||||||
let ser_val = bincode::serialize(&FieldWrap(val))?;
|
let ser_val = bincode::serialize(&FieldWrap(val))?;
|
||||||
values.push(pk.encrypt(ser_val, rng));
|
values.push(pk.encrypt(ser_val, rng).map_err(Error::encrypt)?);
|
||||||
}
|
}
|
||||||
Ok(PartOutcome::Valid(Some(Ack(sender_idx, values))))
|
Ok(PartOutcome::Valid(Some(Ack(sender_idx, values))))
|
||||||
}
|
}
|
||||||
|
@ -450,11 +462,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
///
|
///
|
||||||
/// All participating nodes must handle the exact same sequence of messages.
|
/// All participating nodes must handle the exact same sequence of messages.
|
||||||
/// Note that `handle_ack` also needs to explicitly be called with this instance's own `Ack`s.
|
/// Note that `handle_ack` also needs to explicitly be called with this instance's own `Ack`s.
|
||||||
pub fn handle_ack(
|
pub fn handle_ack(&mut self, sender_id: &N, ack: Ack) -> Result<AckOutcome, Error> {
|
||||||
&mut self,
|
|
||||||
sender_id: &N,
|
|
||||||
ack: Ack<PK::Ciphertext>,
|
|
||||||
) -> Result<AckOutcome, Error> {
|
|
||||||
let sender_idx = self.node_index(sender_id).ok_or(Error::UnknownSender)?;
|
let sender_idx = self.node_index(sender_id).ok_or(Error::UnknownSender)?;
|
||||||
Ok(match self.handle_ack_or_fault(sender_idx, ack) {
|
Ok(match self.handle_ack_or_fault(sender_idx, ack) {
|
||||||
Ok(()) => AckOutcome::Valid,
|
Ok(()) => AckOutcome::Valid,
|
||||||
|
@ -529,7 +537,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
fn handle_part_or_fault(
|
fn handle_part_or_fault(
|
||||||
&mut self,
|
&mut self,
|
||||||
sender_idx: u64,
|
sender_idx: u64,
|
||||||
Part(commit, rows): Part<PK::Ciphertext>,
|
Part(commit, rows): Part,
|
||||||
) -> Result<Option<Poly>, PartFault> {
|
) -> Result<Option<Poly>, PartFault> {
|
||||||
if rows.len() != self.pub_keys.len() {
|
if rows.len() != self.pub_keys.len() {
|
||||||
return Err(PartFault::RowCount);
|
return Err(PartFault::RowCount);
|
||||||
|
@ -551,7 +559,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
let ser_row = self
|
let ser_row = self
|
||||||
.sec_key
|
.sec_key
|
||||||
.decrypt(&rows[our_idx as usize])
|
.decrypt(&rows[our_idx as usize])
|
||||||
.ok_or(PartFault::DecryptRow)?;
|
.map_err(|_| PartFault::DecryptRow)?;
|
||||||
let row: Poly = bincode::deserialize(&ser_row).map_err(|_| PartFault::DeserializeRow)?;
|
let row: Poly = bincode::deserialize(&ser_row).map_err(|_| PartFault::DeserializeRow)?;
|
||||||
if row.commitment() != commit_row {
|
if row.commitment() != commit_row {
|
||||||
return Err(PartFault::RowCommitment);
|
return Err(PartFault::RowCommitment);
|
||||||
|
@ -563,7 +571,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
fn handle_ack_or_fault(
|
fn handle_ack_or_fault(
|
||||||
&mut self,
|
&mut self,
|
||||||
sender_idx: u64,
|
sender_idx: u64,
|
||||||
Ack(proposer_idx, values): Ack<PK::Ciphertext>,
|
Ack(proposer_idx, values): Ack,
|
||||||
) -> Result<(), AckFault> {
|
) -> Result<(), AckFault> {
|
||||||
if values.len() != self.pub_keys.len() {
|
if values.len() != self.pub_keys.len() {
|
||||||
return Err(AckFault::ValueCount);
|
return Err(AckFault::ValueCount);
|
||||||
|
@ -583,7 +591,7 @@ impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
|
||||||
let ser_val = self
|
let ser_val = self
|
||||||
.sec_key
|
.sec_key
|
||||||
.decrypt(&values[our_idx as usize])
|
.decrypt(&values[our_idx as usize])
|
||||||
.ok_or(AckFault::DecryptValue)?;
|
.map_err(|_| AckFault::DecryptValue)?;
|
||||||
let val = bincode::deserialize::<FieldWrap<Fr>>(&ser_val)
|
let val = bincode::deserialize::<FieldWrap<Fr>>(&ser_val)
|
||||||
.map_err(|_| AckFault::DeserializeValue)?
|
.map_err(|_| AckFault::DeserializeValue)?
|
||||||
.into_inner();
|
.into_inner();
|
||||||
|
|
Loading…
Reference in New Issue