use nom::be_u64;
use std::io::{Error, ErrorKind};
use toxcore::binary_io::*;
use toxcore::crypto_core::*;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CookieRequest {
pub pk: PublicKey,
pub nonce: Nonce,
pub payload: Vec<u8>,
}
impl ToBytes for CookieRequest {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
do_gen!(buf,
gen_be_u8!(0x18) >>
gen_slice!(self.pk.as_ref()) >>
gen_slice!(self.nonce.as_ref()) >>
gen_slice!(self.payload.as_slice())
)
}
}
impl FromBytes for CookieRequest {
named!(from_bytes<CookieRequest>, do_parse!(
tag!("\x18") >>
pk: call!(PublicKey::from_bytes) >>
nonce: call!(Nonce::from_bytes) >>
payload: take!(88) >>
(CookieRequest { pk, nonce, payload: payload.to_vec() })
));
}
impl CookieRequest {
pub fn new(shared_secret: &PrecomputedKey, pk: &PublicKey, payload: CookieRequestPayload) -> CookieRequest {
let nonce = gen_nonce();
let mut buf = [0; 72];
let (_, size) = payload.to_bytes((&mut buf, 0)).unwrap();
let payload = seal_precomputed(&buf[..size], &nonce, shared_secret);
CookieRequest {
pk: *pk,
nonce,
payload,
}
}
pub fn get_payload(&self, own_secret_key: &SecretKey) -> Result<CookieRequestPayload, Error> {
let decrypted = open(&self.payload, &self.nonce, &self.pk, own_secret_key)
.map_err(|()| {
debug!("Decrypting CookieRequest failed!");
Error::new(ErrorKind::Other, "CookieRequest decrypt error.")
})?;
match CookieRequestPayload::from_bytes(&decrypted) {
IResult::Incomplete(e) => {
debug!(target: "Dht", "CookieRequestPayload return deserialize error: {:?}", e);
Err(Error::new(ErrorKind::Other,
format!("CookieRequestPayload return deserialize error: {:?}", e)))
},
IResult::Error(e) => {
debug!(target: "Dht", "CookieRequestPayload return deserialize error: {:?}", e);
Err(Error::new(ErrorKind::Other,
format!("CookieRequestPayload return deserialize error: {:?}", e)))
},
IResult::Done(_, payload) => {
Ok(payload)
}
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CookieRequestPayload {
pub pk: PublicKey,
pub id: u64,
}
impl ToBytes for CookieRequestPayload {
fn to_bytes<'a>(&self, buf: (&'a mut [u8], usize)) -> Result<(&'a mut [u8], usize), GenError> {
do_gen!(buf,
gen_slice!(self.pk.as_ref()) >>
gen_slice!(&[0; 32]) >> gen_be_u64!(self.id)
)
}
}
impl FromBytes for CookieRequestPayload {
named!(from_bytes<CookieRequestPayload>, do_parse!(
pk: call!(PublicKey::from_bytes) >>
take!(32) >> id: be_u64 >>
eof!() >>
(CookieRequestPayload { pk, id })
));
}
#[cfg(test)]
mod tests {
use toxcore::dht::packet::cookie_request::*;
encode_decode_test!(
cookie_request_encode_decode,
CookieRequest {
pk: gen_keypair().0,
nonce: gen_nonce(),
payload: vec![42; 88],
}
);
encode_decode_test!(
cookie_request_payload_encode_decode,
CookieRequestPayload {
pk: gen_keypair().0,
id: 42
}
);
dht_packet_encrypt_decrypt!(
cookie_request_payload_encrypt_decrypt,
CookieRequest,
CookieRequestPayload { pk: gen_keypair().0, id: 42 }
);
dht_packet_encrypt_decrypt_invalid_key!(
cookie_request_payload_encrypt_decrypt_invalid_key,
CookieRequest,
CookieRequestPayload { pk: gen_keypair().0, id: 42 }
);
dht_packet_decode_invalid!(cookie_request_decode_invalid, CookieRequest);
}