use crate::{
common::{
x25519_elligator2::{PublicKey, PublicRepresentative},
HmacSha256,
},
constants::*,
handshake::{get_epoch_hour, make_hs_pad, Authcode, AUTHCODE_LENGTH},
Result,
};
use bytes::BufMut;
use hmac::Mac;
use ptrs::trace;
use rand::Rng;
pub struct ServerHandshakeMessage {
server_auth: [u8; AUTHCODE_LENGTH],
pad_len: usize,
repres: PublicRepresentative,
pubkey: Option<PublicKey>,
epoch_hour: String,
}
impl ServerHandshakeMessage {
pub fn new(
repres: PublicRepresentative,
server_auth: [u8; AUTHCODE_LENGTH],
epoch_hr: String,
) -> Self {
Self {
server_auth,
pad_len: rand::thread_rng().gen_range(SERVER_MIN_PAD_LENGTH..SERVER_MAX_PAD_LENGTH),
repres,
pubkey: None,
epoch_hour: epoch_hr,
}
}
pub fn server_pubkey(&mut self) -> PublicKey {
match self.pubkey {
Some(pk) => pk,
None => {
let pk = PublicKey::from(&self.repres);
self.pubkey = Some(pk);
pk
}
}
}
pub fn server_auth(self) -> Authcode {
self.server_auth
}
pub fn marshall(&mut self, buf: &mut impl BufMut, mut h: HmacSha256) -> Result<()> {
trace!("serializing server handshake");
h.reset();
h.update(self.repres.as_bytes().as_ref());
let mark: &[u8] = &h.finalize_reset().into_bytes()[..MARK_LENGTH];
let pad: &[u8] = &make_hs_pad(self.pad_len)?;
let mut params = vec![];
params.extend_from_slice(self.repres.as_bytes());
params.extend_from_slice(&self.server_auth);
params.extend_from_slice(pad);
params.extend_from_slice(mark);
buf.put(params.as_slice());
h.update(¶ms);
h.update(self.epoch_hour.as_bytes());
buf.put(&h.finalize_reset().into_bytes()[..MAC_LENGTH]);
Ok(())
}
}
pub struct ClientHandshakeMessage {
pub(crate) pad_len: usize,
pub(crate) repres: PublicRepresentative,
pub(crate) pubkey: Option<PublicKey>,
pub(crate) epoch_hour: String,
}
impl ClientHandshakeMessage {
pub fn new(repres: PublicRepresentative, pad_len: usize, epoch_hour: String) -> Self {
Self {
pad_len,
repres,
pubkey: None,
epoch_hour,
}
}
pub fn get_public(&mut self) -> PublicKey {
trace!("repr: {}", hex::encode(self.repres));
match self.pubkey {
Some(pk) => pk,
None => {
let pk = PublicKey::from(&self.repres);
self.pubkey = Some(pk);
pk
}
}
}
#[allow(unused)]
pub fn get_representative(&self) -> PublicRepresentative {
self.repres
}
pub fn get_epoch_hr(&self) -> String {
self.epoch_hour.clone()
}
pub fn marshall(&mut self, buf: &mut impl BufMut, mut h: HmacSha256) -> Result<()> {
trace!("serializing client handshake");
h.reset();
h.update(self.repres.as_bytes().as_ref());
let mark: &[u8] = &h.finalize_reset().into_bytes()[..MARK_LENGTH];
let pad = make_hs_pad(self.pad_len)?;
let mut params = vec![];
params.extend_from_slice(self.repres.as_bytes());
params.extend_from_slice(&pad);
params.extend_from_slice(mark);
buf.put(params.as_slice());
h.update(¶ms);
self.epoch_hour = format!("{}", get_epoch_hour());
h.update(self.epoch_hour.as_bytes());
let mac = &h.finalize_reset().into_bytes()[..MARK_LENGTH];
buf.put(mac);
trace!("mark: {}, mac: {}", hex::encode(mark), hex::encode(mac));
Ok(())
}
}