use crate::{
crypto::{CipherText, Encrypter},
error::{Error, Result},
wire::Encoder,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use sodiumoxide::crypto::box_::{self, Nonce, PublicKey, SecretKey};
pub(crate) type SharedKey = KeyPair;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct KeyPair {
pub_: PublicKey,
sec: SecretKey,
}
impl KeyPair {
pub(crate) fn new() -> Self {
let (pub_, sec) = box_::gen_keypair();
Self { pub_, sec }
}
}
impl<T> Encrypter<T> for KeyPair
where
T: Encoder<T> + Serialize + DeserializeOwned,
{
fn seal(&self, data: &T) -> Result<CipherText> {
let non = box_::gen_nonce();
let enc = data.encode()?;
let data = box_::seal(&enc, &non, &self.pub_, &self.sec);
let nonce = non.0.iter().cloned().collect();
Ok(CipherText { nonce, data })
}
fn open(&self, data: &CipherText) -> Result<T> {
let CipherText {
ref nonce,
ref data,
} = data;
let nonce = Nonce::from_slice(nonce.as_slice()).ok_or(Error::InternalError {
msg: "Failed to read nonce!".into(),
})?;
let clear = box_::open(data.as_slice(), &nonce, &self.pub_, &self.sec).map_err(|_| {
Error::InternalError {
msg: "Failed to decrypt data".into(),
}
})?;
Ok(T::decode(&clear)?)
}
}
#[test]
fn sign_and_encrypt() {
use ed25519_dalek::{Keypair as DKP, Signer};
use rand::rngs::OsRng;
let mut rng = OsRng {};
let DKP { secret, public } = DKP::generate(&mut rng);
let nacl_pair = KeyPair {
sec: SecretKey::from_slice(secret.as_bytes()).unwrap(),
pub_: PublicKey::from_slice(public.as_bytes()).unwrap(),
};
let dalek_pair = DKP { secret, public };
let message = "this can be signed and encrypted!";
let sign = dalek_pair.sign(message.as_bytes());
let ctext = nacl_pair
.seal(&message.as_bytes().iter().cloned().collect::<Vec<u8>>())
.unwrap();
dalek_pair.verify(message.as_bytes(), &sign).unwrap();
nacl_pair.open(&ctext).unwrap()
}