use tox_crypto::*;
use std::cell::RefCell;
pub struct Session {
pk: PublicKey,
sk: SecretKey,
nonce: Nonce
}
impl Session {
pub fn random() -> Session {
let (pk, sk) = gen_keypair();
let nonce = gen_nonce();
Session { pk, sk, nonce }
}
pub fn pk(&self) -> &PublicKey {
&self.pk
}
pub fn nonce(&self) -> &Nonce {
&self.nonce
}
pub fn create_precomputed_key(&self, other_pk: &PublicKey) -> PrecomputedKey {
encrypt_precompute(other_pk, &self.sk)
}
}
pub struct Channel {
precomputed_key: PrecomputedKey,
sent_nonce: RefCell<Nonce>,
recv_nonce: RefCell<Nonce>
}
impl Channel {
pub fn new(our_session: &Session, their_pk: &PublicKey, their_nonce: &Nonce) -> Channel {
let precomputed = our_session.create_precomputed_key(their_pk);
let sent_n = RefCell::new(*our_session.nonce());
let recv_n = RefCell::new(*their_nonce);
Channel { precomputed_key: precomputed, sent_nonce: sent_n, recv_nonce: recv_n }
}
pub fn encrypt(&self, plain: &[u8]) -> Vec<u8> {
let mut nonce = self.sent_nonce.borrow_mut();
let encrypted = encrypt_data_symmetric(&self.precomputed_key, &nonce, plain);
increment_nonce( &mut nonce );
encrypted
}
pub fn decrypt(&self, encrypted: &[u8]) -> Result<Vec<u8>, ()> {
let mut nonce = self.recv_nonce.borrow_mut();
let decrypted = decrypt_data_symmetric(&self.precomputed_key, &nonce, encrypted);
increment_nonce( &mut nonce );
decrypted
}
}
#[cfg(test)]
mod tests {
use crate::relay::secure::*;
fn create_channels() -> (Channel, Channel) {
crypto_init().unwrap();
let alice_session = Session::random();
let bob_session = Session::random();
let alice_pk = *alice_session.pk();
let alice_nonce = *alice_session.nonce();
let bob_pk = *bob_session.pk();
let bob_nonce = *bob_session.nonce();
let alice_channel = Channel::new(&alice_session, &bob_pk, &bob_nonce);
let bob_channel = Channel::new(&bob_session, &alice_pk, &alice_nonce);
(alice_channel, bob_channel)
}
#[test]
fn test_secure_communication() {
crypto_init().unwrap();
let (alice_channel, bob_channel) = create_channels();
let alice_msg = "Hello Bob!";
let alice_msg_encrypted = alice_channel.encrypt(alice_msg.as_bytes());
assert_ne!(alice_msg.as_bytes().to_vec(), alice_msg_encrypted);
assert_eq!( alice_msg.as_bytes().to_vec(), bob_channel.decrypt(alice_msg_encrypted.as_ref()).unwrap() );
let bob_msg = "Oh hello Alice!";
let bob_msg_encrypted = bob_channel.encrypt(bob_msg.as_bytes());
assert_ne!(bob_msg.as_bytes().to_vec(), bob_msg_encrypted);
assert_eq!( bob_msg.as_bytes().to_vec(), alice_channel.decrypt(bob_msg_encrypted.as_ref()).unwrap() );
}
}