use core::fmt::Debug;
use std::{
ops::{Deref, Sub},
vec::Vec,
};
use aead::{
consts::{U4, U5},
generic_array::{ArrayLength, GenericArray},
stream::{DecryptorBE32, DecryptorLE31, EncryptorBE32, EncryptorLE31},
Aead, AeadCore, AeadInPlace, KeyInit, Payload,
};
use crate::{CryptoCoreError, RandomFixedSizeCBytes, SecretCBytes};
pub trait Instantiable<const KEY_LENGTH: usize>: Debug {
type Secret: SecretCBytes<KEY_LENGTH>;
fn new(symmetric_key: &Self::Secret) -> Self;
}
pub trait Dem<
const KEY_LENGTH: usize,
const NONCE_LENGTH: usize,
const MAC_LENGTH: usize,
RustCryptoBackend,
>: Instantiable<KEY_LENGTH> + Deref<Target = RustCryptoBackend> where
RustCryptoBackend: Aead + KeyInit,
{
type Nonce: RandomFixedSizeCBytes<NONCE_LENGTH>;
fn encrypt(
&self,
nonce: &Self::Nonce,
plaintext: &[u8],
aad: Option<&[u8]>,
) -> Result<Vec<u8>, CryptoCoreError> {
self.deref()
.encrypt(
nonce.as_bytes().into(),
Payload {
msg: plaintext,
aad: aad.unwrap_or(b""),
},
)
.map_err(|_| CryptoCoreError::EncryptionError)
}
fn decrypt(
&self,
nonce: &Self::Nonce,
ciphertext: &[u8],
aad: Option<&[u8]>,
) -> Result<Vec<u8>, CryptoCoreError> {
self.deref()
.decrypt(
nonce.as_bytes().into(),
Payload {
msg: ciphertext,
aad: aad.unwrap_or(b""),
},
)
.map_err(|_| CryptoCoreError::DecryptionError)
}
}
pub trait DemInPlace<
const KEY_LENGTH: usize,
const NONCE_LENGTH: usize,
const MAC_LENGTH: usize,
RustCryptoBackend,
>: Instantiable<KEY_LENGTH> + Deref<Target = RustCryptoBackend> where
RustCryptoBackend: AeadInPlace + KeyInit,
{
type Nonce: RandomFixedSizeCBytes<NONCE_LENGTH>;
fn encrypt_in_place_detached(
&self,
nonce: &Self::Nonce,
plaintext: &mut [u8],
aad: Option<&[u8]>,
) -> Result<Vec<u8>, CryptoCoreError> {
self.deref()
.encrypt_in_place_detached(nonce.as_bytes().into(), aad.unwrap_or_default(), plaintext)
.map_err(|_| CryptoCoreError::EncryptionError)
.map(|tag| tag.to_vec())
}
fn decrypt_in_place_detached(
&self,
nonce: &Self::Nonce,
bytes: &mut [u8],
tag: &[u8],
aad: Option<&[u8]>,
) -> Result<(), CryptoCoreError> {
self.deref()
.decrypt_in_place_detached(
nonce.as_bytes().into(),
aad.unwrap_or_default(),
bytes,
GenericArray::from_slice(tag),
)
.map_err(|_| CryptoCoreError::DecryptionError)
}
}
pub trait DemStream<
const KEY_LENGTH: usize,
const NONCE_LENGTH: usize,
const MAC_LENGTH: usize,
RustCryptoBackend,
>: Instantiable<KEY_LENGTH> + Sized + Deref<Target = RustCryptoBackend> where
RustCryptoBackend: AeadInPlace + KeyInit,
<RustCryptoBackend as AeadCore>::NonceSize: Sub<U5>,
<RustCryptoBackend as AeadCore>::NonceSize: Sub<U4>,
<<RustCryptoBackend as AeadCore>::NonceSize as Sub<U5>>::Output: ArrayLength<u8>,
<<RustCryptoBackend as AeadCore>::NonceSize as Sub<U4>>::Output: ArrayLength<u8>,
{
type Nonce: RandomFixedSizeCBytes<NONCE_LENGTH>;
fn into_aead_stream_backend(self) -> RustCryptoBackend;
fn into_stream_encryptor_be32(self, nonce: &Self::Nonce) -> EncryptorBE32<RustCryptoBackend> {
EncryptorBE32::from_aead(
self.into_aead_stream_backend(),
nonce.as_bytes()[0..NONCE_LENGTH - 5].into(),
)
}
fn into_stream_decryptor_be32(self, nonce: &Self::Nonce) -> DecryptorBE32<RustCryptoBackend> {
DecryptorBE32::from_aead(
self.into_aead_stream_backend(),
nonce.as_bytes()[0..NONCE_LENGTH - 5].into(),
)
}
fn into_stream_encryptor_le31(self, nonce: &Self::Nonce) -> EncryptorLE31<RustCryptoBackend> {
EncryptorLE31::from_aead(
self.into_aead_stream_backend(),
nonce.as_bytes()[0..NONCE_LENGTH - 4].into(),
)
}
fn into_stream_decryptor_le31(self, nonce: &Self::Nonce) -> DecryptorLE31<RustCryptoBackend> {
DecryptorLE31::from_aead(
self.into_aead_stream_backend(),
nonce.as_bytes()[0..NONCE_LENGTH - 4].into(),
)
}
}