use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
use serde::{Deserialize, Serialize};
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::{
errors::RecipherError,
key::{GenRandom, Key},
permutation::Permutation,
};
#[derive(Clone, Default, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
pub struct EncryptionKeySet {
pub(crate) p1: Permutation,
pub(crate) p2: Permutation,
pub(crate) p3: Permutation,
}
opaque_debug::implement!(EncryptionKeySet);
impl EncryptionKeySet {
pub fn generate() -> Result<Self, RecipherError> {
let mut rng = ChaCha20Rng::from_entropy();
let k1: Key = GenRandom::gen_random(&mut rng)?;
let k2: Key = GenRandom::gen_random(&mut rng)?;
let k3: Key = GenRandom::gen_random(&mut rng)?;
let p1 = Permutation::generate(&k1, 16);
let p2 = Permutation::generate(&k2, 16);
let p3 = Permutation::generate(&k3, 33);
Ok(EncryptionKeySet { p1, p2, p3 })
}
pub fn grant(
&self,
domain: &EncryptionKeySet,
authority: &EncryptionKeySet,
) -> EncryptionKeySet {
let p1 = authority.p1.permute(&domain.p1.invert()).permute(&self.p1);
let p3 = authority.p3.permute(&domain.p3.invert()).permute(&self.p3);
Self {
p1,
p2: authority.p2.clone(),
p3,
}
}
pub fn to_bytes(&self) -> Result<Vec<u8>, RecipherError> {
serde_cbor::to_vec(self).map_err(RecipherError::Serialization)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, RecipherError> {
Ok(serde_cbor::from_slice(bytes)?)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::keyset::ProxyKeySet;
use rand::{thread_rng, Fill};
#[test]
fn composition() {
let d1 = EncryptionKeySet::generate().unwrap();
let a1 = EncryptionKeySet::generate().unwrap();
let client = ProxyKeySet::generate(&a1, &d1);
let mut input = [0u8; 16];
input.try_fill(&mut thread_rng()).unwrap();
let mut check = input;
a1.p1.permute_slice_mut(&mut input);
client.p1.permute_slice_mut(&mut input);
d1.p1.permute_slice_mut(&mut check);
assert_eq!(input, check);
let mut input = [0u8; 33];
input.try_fill(&mut thread_rng()).unwrap();
let mut check = input;
a1.p3.permute_slice_mut(&mut input);
client.p3.permute_slice_mut(&mut input);
d1.p3.permute_slice_mut(&mut check);
assert_eq!(input, check);
}
#[test]
fn delegate_test() {
let d1 = EncryptionKeySet::generate().unwrap();
let a1 = EncryptionKeySet::generate().unwrap();
let client = ProxyKeySet::generate(&a1, &d1);
let d2 = EncryptionKeySet::generate().unwrap();
let a2 = d2.grant(&d1, &a1);
let mut input_p1 = [0u8; 16];
let mut input_p3 = [0u8; 33];
input_p1.try_fill(&mut thread_rng()).unwrap();
input_p3.try_fill(&mut thread_rng()).unwrap();
let mut check_p1 = input_p1;
let mut check_p3 = input_p3;
a2.p1.permute_slice_mut(&mut input_p1);
client.p1.permute_slice_mut(&mut input_p1);
a2.p3.permute_slice_mut(&mut input_p3);
client.p3.permute_slice_mut(&mut input_p3);
d2.p1.permute_slice_mut(&mut check_p1);
d2.p3.permute_slice_mut(&mut check_p3);
assert_eq!(input_p1, check_p1);
assert_eq!(input_p3, check_p3);
assert_eq!(a2.p2.permutation, a1.p2.permutation);
}
}