Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

re-introduce the coordinator public key in the message header #514

Merged
merged 1 commit into from
Sep 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions rust/xaynet-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ where
/// Work flow for [`Client`]s selected as sum participants.
async fn summer(&mut self) -> Result<Task, ClientError<C::Error>> {
info!(client_id = %self.id, "selected to sum");
let msg = self.participant.compose_sum_message();
let msg = self.participant.compose_sum_message(self.coordinator_pk);
let sealed_msg = self.participant.seal_message(&self.coordinator_pk, &msg);

self.client.send_message(sealed_msg).await?;
Expand All @@ -251,7 +251,7 @@ where
debug!(client_id = %self.id, "seed dict received, sending sum2 message.");
let msg = self
.participant
.compose_sum2_message(&seeds, length)
.compose_sum2_message(self.coordinator_pk, &seeds, length)
.map_err(|e| {
error!("failed to compose sum2 message with seeds: {:?}", &seeds);
ClientError::ParticipantErr(e)
Expand Down Expand Up @@ -286,9 +286,12 @@ where
loop {
if let Some(sums) = self.client.get_sums().await? {
debug!(client_id = %self.id, "sum dict received, sending update message.");
let msg = self
.participant
.compose_update_message(&sums, self.scalar, model);
let msg = self.participant.compose_update_message(
self.coordinator_pk,
&sums,
self.scalar,
model,
);
let sealed_msg = self.participant.seal_message(&self.coordinator_pk, &msg);
self.client.send_message(sealed_msg).await?;

Expand Down
13 changes: 8 additions & 5 deletions rust/xaynet-client/src/mobile_client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl ClientState<Sum> {
async fn run<T: ApiClient>(&mut self, api: &mut T) -> Result<(), ClientError<T::Error>> {
self.check_round_freshness(api).await?;

let sum_msg = self.participant.compose_sum_message();
let sum_msg = self.participant.compose_sum_message(self.round_params.pk);
let sealed_msg = self
.participant
.seal_message(&self.round_params.pk, &sum_msg);
Expand Down Expand Up @@ -179,9 +179,12 @@ impl ClientState<Update> {
.await?
.ok_or(ClientError::TooEarly("sum dict"))?;

let upd_msg = self
.participant
.compose_update_message(&sums, scalar, local_model);
let upd_msg = self.participant.compose_update_message(
self.round_params.pk,
&sums,
scalar,
local_model,
);
let sealed_msg = self
.participant
.seal_message(&self.round_params.pk, &upd_msg);
Expand Down Expand Up @@ -233,7 +236,7 @@ impl ClientState<Sum2> {

let sum2_msg = self
.participant
.compose_sum2_message(&seeds, length as usize)
.compose_sum2_message(self.round_params.pk, &seeds, length as usize)
.map_err(|e| {
error!("failed to compose sum2 message with seeds: {:?}", &seeds);
ClientError::ParticipantErr(e)
Expand Down
4 changes: 3 additions & 1 deletion rust/xaynet-client/src/mobile_client/participant/sum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::mobile_client::participant::Sum2;
use xaynet_core::{
crypto::EncryptKeyPair,
message::{Message, Sum as SumMessage},
CoordinatorPublicKey,
ParticipantTaskSignature,
SumParticipantEphemeralPublicKey,
SumParticipantEphemeralSecretKey,
Expand All @@ -29,10 +30,11 @@ impl Participant<Sum> {
}

/// Compose a sum message given the coordinator public key.
pub fn compose_sum_message(&mut self) -> Message {
pub fn compose_sum_message(&mut self, coordinator_pk: CoordinatorPublicKey) -> Message {
Message {
signature: None,
participant_pk: self.state.keys.public,
coordinator_pk,
payload: SumMessage {
sum_signature: self.inner.sum_signature,
ephm_pk: self.inner.ephm_pk,
Expand Down
3 changes: 3 additions & 0 deletions rust/xaynet-client/src/mobile_client/participant/sum2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{Participant, ParticipantState};
use xaynet_core::{
mask::{Aggregation, MaskObject, MaskSeed},
message::{Message, Sum2 as Sum2Message},
CoordinatorPublicKey,
ParticipantPublicKey,
ParticipantTaskSignature,
PetError,
Expand Down Expand Up @@ -42,6 +43,7 @@ impl Participant<Sum2> {
/// seed dictionary, or computing the global mask.
pub fn compose_sum2_message(
&self,
coordinator_pk: CoordinatorPublicKey,
seed_dict: &UpdateSeedDict,
mask_len: usize,
) -> Result<Message, PetError> {
Expand All @@ -50,6 +52,7 @@ impl Participant<Sum2> {
Ok(Message {
signature: None,
participant_pk: self.state.keys.public,
coordinator_pk,
payload: Sum2Message {
sum_signature: self.inner.sum_signature,
model_mask,
Expand Down
3 changes: 3 additions & 0 deletions rust/xaynet-client/src/mobile_client/participant/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{Participant, ParticipantState};
use xaynet_core::{
mask::{MaskObject, MaskSeed, Masker, Model},
message::{Message, Update as UpdateMessage},
CoordinatorPublicKey,
LocalSeedDict,
ParticipantTaskSignature,
SumDict,
Expand Down Expand Up @@ -31,6 +32,7 @@ impl Participant<Update> {
/// dictionary, model scalar and local model update.
pub fn compose_update_message(
&self,
coordinator_pk: CoordinatorPublicKey,
sum_dict: &SumDict,
scalar: f64,
local_model: Model,
Expand All @@ -41,6 +43,7 @@ impl Participant<Update> {
Message {
signature: None,
participant_pk: self.state.keys.public,
coordinator_pk,
payload: UpdateMessage {
sum_signature: self.inner.sum_signature,
update_signature: self.inner.update_signature,
Expand Down
10 changes: 8 additions & 2 deletions rust/xaynet-client/src/participant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@ impl Participant {
self.task
}

/// Compose a sum message given the coordinator public key.
pub fn compose_sum_message(&mut self) -> Message {
/// Compose a sum message that embeds the given coordinator public
/// key.
pub fn compose_sum_message(&mut self, coordinator_pk: CoordinatorPublicKey) -> Message {
self.gen_ephm_keypair();

Message {
signature: None,
participant_pk: self.pk,
coordinator_pk,
payload: Sum {
sum_signature: self.sum_signature,
ephm_pk: self.ephm_pk,
Expand All @@ -137,6 +139,7 @@ impl Participant {
/// dictionary, model scalar and local model update.
pub fn compose_update_message(
&self,
coordinator_pk: CoordinatorPublicKey,
sum_dict: &SumDict,
scalar: f64,
local_model: Model,
Expand All @@ -147,6 +150,7 @@ impl Participant {
Message {
signature: None,
participant_pk: self.pk,
coordinator_pk,
payload: Update {
sum_signature: self.sum_signature,
update_signature: self.update_signature,
Expand All @@ -167,6 +171,7 @@ impl Participant {
/// seed dictionary, or computing the global mask.
pub fn compose_sum2_message(
&self,
coordinator_pk: CoordinatorPublicKey,
seed_dict: &UpdateSeedDict,
mask_len: usize,
) -> Result<Message, PetError> {
Expand All @@ -176,6 +181,7 @@ impl Participant {
Ok(Message {
signature: None,
participant_pk: self.pk,
coordinator_pk,
payload: Sum2 {
sum_signature: self.sum_signature,
model_mask,
Expand Down
82 changes: 73 additions & 9 deletions rust/xaynet-core/src/message/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::convert::{TryFrom, TryInto};
use anyhow::{anyhow, Context};

use crate::{
crypto::{ByteObject, PublicSigningKey, SecretSigningKey, Signature},
crypto::{ByteObject, PublicEncryptKey, PublicSigningKey, SecretSigningKey, Signature},
message::{Chunk, DecodeError, FromBytes, Payload, Sum, Sum2, ToBytes, Update},
};

Expand All @@ -25,8 +25,11 @@ pub(crate) mod ranges {
/// Byte range corresponding to the participant public key in a
/// message header
pub const PARTICIPANT_PK: Range<usize> = range(SIGNATURE.end, PublicSigningKey::LENGTH);
/// Byte range corresponding to the coordinator public key in a
/// message header
pub const COORDINATOR_PK: Range<usize> = range(PARTICIPANT_PK.end, PublicEncryptKey::LENGTH);
/// Byte range corresponding to the length field in a message header
pub const LENGTH: Range<usize> = range(PARTICIPANT_PK.end, 4);
pub const LENGTH: Range<usize> = range(COORDINATOR_PK.end, 4);
/// Byte range corresponding to the tag in a message header
pub const TAG: usize = LENGTH.end;
/// Byte range reserved for future use
Expand Down Expand Up @@ -93,6 +96,22 @@ pub const HEADER_LENGTH: usize = ranges::RESERVED.end;
/// + +
/// | |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | |
/// + +
/// | |
/// + +
/// | |
/// + +
/// | |
/// + coordinator_pk +
/// | |
/// + +
/// | |
/// + +
/// | |
/// + +
/// | |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | length |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | tag | reserved |
Expand All @@ -105,6 +124,12 @@ pub const HEADER_LENGTH: usize = ranges::RESERVED.end;
/// - `signature` contains the signature of the entire message
/// - `participant_pk` contains the public key for verifying the
/// signature
/// - `coordinator_pk` is the coordinator public encryption key. It is
/// embedded in the message for security reasons. See [_Donald
/// T. Davis, "Defective Sign & Encrypt in S/MIME, PKCS#7, MOSS,
/// PEM, PGP, and XML.", Proc. Usenix Tech. Conf. 2001 (Boston,
/// Mass., June 25-30,
/// 2001)_](http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html)
/// - `length` is the length in bytes of the _full_ message, _i.e._
/// including the header. This is a 32 bits field so in theory,
/// messages can be as big as 2^32 = 4,294,967,296 bytes.
Expand All @@ -120,7 +145,8 @@ pub const HEADER_LENGTH: usize = ranges::RESERVED.end;
///
/// let mut bytes = vec![0x11; 64]; // message signature
/// bytes.extend(vec![0x22; 32]); // participant public signing key
/// bytes.extend(&168_u32.to_be_bytes()); // Length field
/// bytes.extend(vec![0x33; 32]); // coordinator public encrypt key
/// bytes.extend(&200_u32.to_be_bytes()); // Length field
/// bytes.push(0x01); // tag (sum message)
/// bytes.extend(vec![0x00, 0x00, 0x00]); // reserved
///
Expand All @@ -131,6 +157,7 @@ pub const HEADER_LENGTH: usize = ranges::RESERVED.end;
/// let buffer = MessageBuffer::new(&bytes).unwrap();
/// assert_eq!(buffer.signature(), vec![0x11; 64].as_slice());
/// assert_eq!(buffer.participant_pk(), vec![0x22; 32].as_slice());
/// assert_eq!(buffer.coordinator_pk(), vec![0x33; 32].as_slice());
/// assert_eq!(Tag::try_from(buffer.tag()).unwrap(), Tag::Sum);
/// assert_eq!(
/// buffer.payload(),
Expand All @@ -146,7 +173,8 @@ pub const HEADER_LENGTH: usize = ranges::RESERVED.end;
///
/// let mut expected = vec![0x11; 64]; // message signature
/// expected.extend(vec![0x22; 32]); // participant public signing key
/// expected.extend(&168_u32.to_be_bytes()); // length field
/// expected.extend(vec![0x33; 32]); // coordinator public signing key
/// expected.extend(&200_u32.to_be_bytes()); // length field
/// expected.push(0x01); // tag (sum message)
/// expected.extend(vec![0x00, 0x00, 0x00]); // reserved
///
Expand All @@ -162,7 +190,10 @@ pub const HEADER_LENGTH: usize = ranges::RESERVED.end;
/// buffer
/// .participant_pk_mut()
/// .copy_from_slice(vec![0x22; 32].as_slice());
/// buffer.set_length(168 as u32);
/// buffer
/// .coordinator_pk_mut()
/// .copy_from_slice(vec![0x33; 32].as_slice());
/// buffer.set_length(200 as u32);
/// buffer.set_tag(Tag::Sum.into());
/// buffer
/// .payload_mut()
Expand Down Expand Up @@ -256,6 +287,14 @@ impl<'a, T: AsRef<[u8]> + ?Sized> MessageBuffer<&'a T> {
&self.inner.as_ref()[ranges::PARTICIPANT_PK]
}

/// Gets the coordinator public key field.
///
/// # Panics
/// Accessing the field may panic if the buffer has not been checked before.
pub fn coordinator_pk(&self) -> &'a [u8] {
&self.inner.as_ref()[ranges::COORDINATOR_PK]
}

/// Gets the rest of the message.
///
/// # Panics
Expand Down Expand Up @@ -325,6 +364,14 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>> MessageBuffer<T> {
&mut self.inner.as_mut()[ranges::PARTICIPANT_PK]
}

/// Gets a mutable reference to the coordinator public key field.
///
/// # Panics
/// Accessing the field may panic if the buffer has not been checked before.
pub fn coordinator_pk_mut(&mut self) -> &mut [u8] {
&mut self.inner.as_mut()[ranges::COORDINATOR_PK]
}

/// Gets a mutable reference to the rest of the message.
///
/// # Panics
Expand Down Expand Up @@ -392,6 +439,8 @@ pub struct Message {
/// The participant public key, used to verify the message
/// signature.
pub participant_pk: PublicSigningKey,
/// The coordinator public key
pub coordinator_pk: PublicEncryptKey,
/// Message payload
pub payload: Payload,
}
Expand All @@ -402,11 +451,12 @@ impl Message {
/// [`MessageBuffer.verify_signature`] before parsing the message.
pub fn from_bytes<T: AsRef<[u8]>>(buffer: &T) -> Result<Self, DecodeError> {
let reader = MessageBuffer::new(buffer.as_ref())?;
let participant_pk = PublicSigningKey::from_bytes(&reader.participant_pk())
.context("failed to parse public key")?;
let signature =
Signature::from_bytes(&reader.signature()).context("failed to parse signature")?;

let participant_pk = PublicSigningKey::from_bytes(&reader.participant_pk())
.context("failed to parse public key")?;
let coordinator_pk = PublicEncryptKey::from_bytes(&reader.coordinator_pk())
.context("failed to parse public key")?;
let payload = match reader.tag().try_into()? {
Tag::Sum => Sum::from_bytes(&reader.payload()).map(Into::into),
Tag::Update => Update::from_bytes(&reader.payload()).map(Into::into),
Expand All @@ -417,6 +467,7 @@ impl Message {

Ok(Self {
participant_pk,
coordinator_pk,
signature: Some(signature),
payload,
})
Expand All @@ -439,7 +490,8 @@ impl Message {

self.participant_pk
.to_bytes(&mut writer.participant_pk_mut());

self.coordinator_pk
.to_bytes(&mut writer.coordinator_pk_mut());
let tag = match self.payload {
Payload::Sum(_) => Tag::Sum,
Payload::Update(_) => Tag::Update,
Expand Down Expand Up @@ -485,15 +537,23 @@ pub(in crate::message) mod tests {
(bytes, pk)
}

fn coordinator_pk() -> (Vec<u8>, PublicEncryptKey) {
let bytes = vec![0xbb; 32];
let pk = PublicEncryptKey::from_slice(&bytes).unwrap();
(bytes, pk)
}

pub(crate) fn message() -> (Vec<u8>, Message) {
let message = Message {
signature: Some(signature().1),
participant_pk: participant_pk().1,
coordinator_pk: coordinator_pk().1,
payload: sum::tests::sum().into(),
};

let mut buf = signature().0;
buf.extend(participant_pk().0);
buf.extend(coordinator_pk().0);
let length = sum::tests::sum_bytes().len() + HEADER_LENGTH;
buf.extend(&(length as u32).to_be_bytes());
buf.push(Tag::Sum.into());
Expand All @@ -510,6 +570,7 @@ pub(in crate::message) mod tests {
assert_eq!(Tag::try_from(buffer.tag()).unwrap(), Tag::Sum);
assert_eq!(buffer.signature(), signature().0.as_slice());
assert_eq!(buffer.participant_pk(), participant_pk().0.as_slice());
assert_eq!(buffer.coordinator_pk(), coordinator_pk().0.as_slice());
assert_eq!(buffer.length() as usize, bytes.len());
assert_eq!(buffer.payload(), sum::tests::sum_bytes().as_slice());
}
Expand All @@ -526,6 +587,9 @@ pub(in crate::message) mod tests {
buffer
.participant_pk_mut()
.copy_from_slice(participant_pk().0.as_slice());
buffer
.coordinator_pk_mut()
.copy_from_slice(coordinator_pk().0.as_slice());
buffer.set_tag(Tag::Sum.into());
buffer.set_length(expected.len() as u32);
buffer
Expand Down
Loading