use crate::error::CryptoError;
use super::{aes_kw, concat_kdf, content_encryption, signing};
pub trait KeyWrap {
fn algorithm(&self) -> &'static str;
fn wrap(&self, kek: &[u8], key: &[u8]) -> Result<Vec<u8>, CryptoError>;
fn unwrap(&self, kek: &[u8], wrapped: &[u8]) -> Result<Vec<u8>, CryptoError>;
}
pub trait ContentEncryption {
fn enc(&self) -> &'static str;
fn cek_len(&self) -> usize;
fn iv_len(&self) -> usize;
fn tag_len(&self) -> usize;
fn encrypt(
&self,
plaintext: &[u8],
cek: &[u8],
iv: &[u8],
aad: &[u8],
) -> Result<(Vec<u8>, Vec<u8>), CryptoError>;
fn decrypt(
&self,
ciphertext: &[u8],
cek: &[u8],
iv: &[u8],
aad: &[u8],
tag: &[u8],
) -> Result<Vec<u8>, CryptoError>;
}
pub trait KeyDerivation {
fn derive(
&self,
z: &[u8],
alg: &[u8],
apu: &[u8],
apv: &[u8],
key_len_bits: u32,
cc_tag: &[u8],
) -> Result<Vec<u8>, CryptoError>;
}
pub trait JwsSigner {
fn algorithm(&self) -> &'static str;
fn sign(&self, data: &[u8], private_key: &[u8]) -> Result<Vec<u8>, CryptoError>;
}
pub trait JwsVerifier {
fn algorithm(&self) -> &'static str;
fn verify(&self, data: &[u8], signature: &[u8], public_key: &[u8]) -> Result<(), CryptoError>;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct A256Kw;
impl KeyWrap for A256Kw {
fn algorithm(&self) -> &'static str {
"A256KW"
}
fn wrap(&self, kek: &[u8], key: &[u8]) -> Result<Vec<u8>, CryptoError> {
let kek: &[u8; 32] = kek
.try_into()
.map_err(|_| CryptoError::KeyWrap("A256KW KEK must be 32 bytes".into()))?;
aes_kw::wrap(kek, key)
}
fn unwrap(&self, kek: &[u8], wrapped: &[u8]) -> Result<Vec<u8>, CryptoError> {
let kek: &[u8; 32] = kek
.try_into()
.map_err(|_| CryptoError::KeyWrap("A256KW KEK must be 32 bytes".into()))?;
aes_kw::unwrap(kek, wrapped)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct A256CbcHs512;
impl ContentEncryption for A256CbcHs512 {
fn enc(&self) -> &'static str {
"A256CBC-HS512"
}
fn cek_len(&self) -> usize {
content_encryption::CEK_SIZE
}
fn iv_len(&self) -> usize {
content_encryption::IV_SIZE
}
fn tag_len(&self) -> usize {
content_encryption::TAG_SIZE
}
fn encrypt(
&self,
plaintext: &[u8],
cek: &[u8],
iv: &[u8],
aad: &[u8],
) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
let cek: &[u8; content_encryption::CEK_SIZE] = cek
.try_into()
.map_err(|_| CryptoError::ContentEncryption("CEK must be 64 bytes".into()))?;
let iv: &[u8; content_encryption::IV_SIZE] = iv
.try_into()
.map_err(|_| CryptoError::ContentEncryption("IV must be 16 bytes".into()))?;
let (ct, tag) = content_encryption::encrypt(plaintext, cek, iv, aad)?;
Ok((ct, tag.to_vec()))
}
fn decrypt(
&self,
ciphertext: &[u8],
cek: &[u8],
iv: &[u8],
aad: &[u8],
tag: &[u8],
) -> Result<Vec<u8>, CryptoError> {
let cek: &[u8; content_encryption::CEK_SIZE] = cek
.try_into()
.map_err(|_| CryptoError::ContentEncryption("CEK must be 64 bytes".into()))?;
let iv: &[u8; content_encryption::IV_SIZE] = iv
.try_into()
.map_err(|_| CryptoError::ContentEncryption("IV must be 16 bytes".into()))?;
let tag: &[u8; content_encryption::TAG_SIZE] = tag
.try_into()
.map_err(|_| CryptoError::ContentEncryption("tag must be 32 bytes".into()))?;
content_encryption::decrypt(ciphertext, cek, iv, aad, tag)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ConcatKdf;
impl KeyDerivation for ConcatKdf {
fn derive(
&self,
z: &[u8],
alg: &[u8],
apu: &[u8],
apv: &[u8],
key_len_bits: u32,
cc_tag: &[u8],
) -> Result<Vec<u8>, CryptoError> {
if cc_tag.is_empty() {
concat_kdf::concat_kdf(z, alg, apu, apv, key_len_bits)
} else {
concat_kdf::concat_kdf_1pu(z, alg, apu, apv, key_len_bits, cc_tag)
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Ed25519;
impl JwsSigner for Ed25519 {
fn algorithm(&self) -> &'static str {
"EdDSA"
}
fn sign(&self, data: &[u8], private_key: &[u8]) -> Result<Vec<u8>, CryptoError> {
let sk: &[u8; 32] = private_key
.try_into()
.map_err(|_| CryptoError::Signing("Ed25519 private key must be 32 bytes".into()))?;
Ok(signing::sign(data, sk)?.to_vec())
}
}
impl JwsVerifier for Ed25519 {
fn algorithm(&self) -> &'static str {
"EdDSA"
}
fn verify(&self, data: &[u8], signature: &[u8], public_key: &[u8]) -> Result<(), CryptoError> {
let sig: &[u8; 64] = signature
.try_into()
.map_err(|_| CryptoError::Verification("Ed25519 signature must be 64 bytes".into()))?;
let pk: &[u8; 32] = public_key
.try_into()
.map_err(|_| CryptoError::Verification("Ed25519 public key must be 32 bytes".into()))?;
signing::verify(data, sig, pk)
}
}