use crate::backend::CipherKey;
use crate::{Aes256Cipher, AesCipherText};
use vitaminc_aead::{DecodeError, DecryptError, EncryptError, IntoAad, Unspecified};
use vitaminc_protected::{Controlled, Protected};
use vitaminc_random::{Generatable, RandomError, SafeRand};
#[derive(Debug)]
#[cfg_attr(test, derive(Clone))]
pub struct Key(Protected<[u8; 32]>);
impl Key {
pub fn wrap<'a>(
&self,
kek: &Aes256Cipher,
aad: impl IntoAad<'a>,
) -> Result<AesCipherText, EncryptError<Unspecified>> {
vitaminc_aead::encrypt(&self.0, kek, aad)
}
pub fn from_wrapped<'a>(
kek: &Aes256Cipher,
wrapped: AesCipherText,
aad: impl IntoAad<'a>,
) -> Result<Self, DecryptError<DecodeError, Unspecified>> {
vitaminc_aead::decrypt::<Protected<[u8; 32]>, _, _>(kek, wrapped, aad).map(Self)
}
pub(crate) fn cipher_key(&self) -> Result<CipherKey, Unspecified> {
CipherKey::new(self.0.risky_ref())
}
}
impl From<[u8; 32]> for Key {
fn from(key: [u8; 32]) -> Self {
Self(Protected::new(key))
}
}
impl Generatable for Key {
fn random(rng: &mut SafeRand) -> Result<Self, RandomError> {
Generatable::random(rng).map(Self)
}
}
#[cfg(test)]
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod tests {
use super::*;
use quickcheck::Arbitrary;
fn gen_array(g: &mut quickcheck::Gen) -> [u8; 32] {
let mut array = [0u8; 32];
for byte in array.iter_mut() {
*byte = u8::arbitrary(g);
}
array
}
impl quickcheck::Arbitrary for Key {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
Key::from(gen_array(g))
}
}
#[derive(Clone, Debug)]
pub(crate) struct DifferingKeyPair(pub Key, pub Key);
impl quickcheck::Arbitrary for DifferingKeyPair {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
let raw_a = gen_array(g);
let mut raw_b = gen_array(g);
while raw_a == raw_b {
raw_b = gen_array(g);
}
Self(Key::from(raw_a), Key::from(raw_b))
}
}
}