use crate::{
error::FastCryptoError,
traits::{AllowedRng, Generate, ToFromBytes},
};
use aes::cipher::{
BlockCipher, BlockDecrypt, BlockDecryptMut, BlockEncrypt, BlockEncryptMut, BlockSizeUser,
KeyInit, KeyIvInit, KeySizeUser, StreamCipher,
};
use aes_gcm::{AeadCore, AeadInPlace};
use fastcrypto_derive::{SilentDebug, SilentDisplay};
use generic_array::{ArrayLength, GenericArray};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::marker::PhantomData;
use typenum::U16;
use zeroize::{Zeroize, ZeroizeOnDrop};
pub trait EncryptionKey:
ToFromBytes + Serialize + DeserializeOwned + Send + Sync + Sized + Generate
{
}
pub trait Nonce:
ToFromBytes + Serialize + DeserializeOwned + Send + Sync + Sized + Generate
{
}
pub trait Cipher {
type IVType: Nonce;
fn encrypt(&self, iv: &Self::IVType, plaintext: &[u8]) -> Vec<u8>;
fn decrypt(&self, iv: &Self::IVType, ciphertext: &[u8]) -> Result<Vec<u8>, FastCryptoError>;
}
pub trait AuthenticatedCipher {
type IVType: Nonce;
fn encrypt_authenticated(&self, iv: &Self::IVType, aad: &[u8], plaintext: &[u8]) -> Vec<u8>;
fn decrypt_authenticated(
&self,
iv: &Self::IVType,
aad: &[u8],
ciphertext: &[u8],
) -> Result<Vec<u8>, FastCryptoError>;
}
impl<AC: AuthenticatedCipher> Cipher for AC {
type IVType = AC::IVType;
fn encrypt(&self, iv: &Self::IVType, plaintext: &[u8]) -> Vec<u8> {
self.encrypt_authenticated(iv, &[], plaintext)
}
fn decrypt(&self, iv: &Self::IVType, ciphertext: &[u8]) -> Result<Vec<u8>, FastCryptoError> {
self.decrypt_authenticated(iv, &[], ciphertext)
}
}
#[derive(Clone, Serialize, Deserialize, SilentDebug, SilentDisplay, ZeroizeOnDrop)]
#[serde(bound = "N: ArrayLength<u8>")]
pub struct GenericByteArray<N: ArrayLength<u8>> {
bytes: GenericArray<u8, N>,
}
impl<N: ArrayLength<u8>> AsRef<[u8]> for GenericByteArray<N> {
fn as_ref(&self) -> &[u8] {
self.bytes.as_ref()
}
}
impl<N> ToFromBytes for GenericByteArray<N>
where
N: ArrayLength<u8> + Debug,
{
fn from_bytes(bytes: &[u8]) -> Result<Self, FastCryptoError> {
match bytes.len() == N::USIZE {
true => Ok(GenericByteArray {
bytes: GenericArray::clone_from_slice(bytes),
}),
false => Err(FastCryptoError::InputLengthWrong(N::USIZE)),
}
}
fn as_bytes(&self) -> &[u8] {
&self.bytes
}
}
impl<N> Generate for GenericByteArray<N>
where
N: ArrayLength<u8> + Debug,
{
fn generate<R: AllowedRng>(rng: &mut R) -> AesKey<N> {
let mut bytes = GenericArray::<u8, N>::default();
rng.fill_bytes(&mut bytes);
GenericByteArray { bytes }
}
}
impl<N> Zeroize for GenericByteArray<N>
where
N: ArrayLength<u8>,
{
fn zeroize(&mut self) {
self.bytes.zeroize();
}
}
pub type AesKey<N> = GenericByteArray<N>;
impl<N> EncryptionKey for AesKey<N> where N: ArrayLength<u8> + Debug {}
pub type InitializationVector<N> = GenericByteArray<N>;
impl<N> Nonce for InitializationVector<N> where N: ArrayLength<u8> + Debug {}
pub struct AesCtr<Aes: KeySizeUser>(AesKey<Aes::KeySize>);
impl<Aes: KeySizeUser> AesCtr<Aes> {
pub fn new(key: AesKey<Aes::KeySize>) -> Self {
Self(key)
}
}
impl<Aes> Cipher for AesCtr<Aes>
where
Aes: KeySizeUser
+ KeyInit
+ BlockCipher
+ BlockSizeUser<BlockSize = U16>
+ BlockEncrypt
+ BlockDecrypt,
{
type IVType = InitializationVector<U16>;
fn encrypt(&self, iv: &Self::IVType, plaintext: &[u8]) -> Vec<u8> {
let mut buffer: Vec<u8> = vec![0; plaintext.len()];
let mut cipher = ctr::Ctr128BE::<Aes>::new(&self.0.bytes, &iv.bytes);
cipher.apply_keystream_b2b(plaintext, &mut buffer).unwrap();
buffer
}
fn decrypt(&self, iv: &Self::IVType, ciphertext: &[u8]) -> Result<Vec<u8>, FastCryptoError> {
let mut buffer: Vec<u8> = vec![0; ciphertext.len()];
let mut cipher = ctr::Ctr128BE::<Aes>::new(&self.0.bytes, &iv.bytes);
cipher.apply_keystream_b2b(ciphertext, &mut buffer).unwrap();
Ok(buffer)
}
}
pub type Aes128Ctr = AesCtr<aes::Aes128>;
pub type Aes192Ctr = AesCtr<aes::Aes192>;
pub type Aes256Ctr = AesCtr<aes::Aes256>;
pub struct AesCbc<Aes: KeySizeUser, Padding> {
key: AesKey<Aes::KeySize>,
padding: PhantomData<Padding>,
}
impl<Aes: KeySizeUser, Padding> AesCbc<Aes, Padding> {
pub fn new(key: AesKey<Aes::KeySize>) -> Self {
Self {
key,
padding: PhantomData,
}
}
}
impl<Aes, Padding> Cipher for AesCbc<Aes, Padding>
where
Aes: KeySizeUser
+ KeyInit
+ BlockCipher
+ BlockSizeUser<BlockSize = U16>
+ BlockEncrypt
+ BlockDecrypt,
Padding: aes::cipher::block_padding::Padding<U16>,
{
type IVType = InitializationVector<U16>;
fn encrypt(&self, iv: &Self::IVType, plaintext: &[u8]) -> Vec<u8> {
let cipher = cbc::Encryptor::<Aes>::new(&self.key.bytes, &iv.bytes);
cipher.encrypt_padded_vec_mut::<Padding>(plaintext)
}
fn decrypt(&self, iv: &Self::IVType, ciphertext: &[u8]) -> Result<Vec<u8>, FastCryptoError> {
let cipher = cbc::Decryptor::<Aes>::new(&self.key.bytes, &iv.bytes);
cipher
.decrypt_padded_vec_mut::<Padding>(ciphertext)
.map_err(|_| FastCryptoError::InvalidInput)
}
}
pub type Aes128CbcPkcs7 = AesCbc<aes::Aes128, aes::cipher::block_padding::Pkcs7>;
pub type Aes256CbcPkcs7 = AesCbc<aes::Aes256, aes::cipher::block_padding::Pkcs7>;
pub type Aes128CbcIso10126 = AesCbc<aes::Aes128, aes::cipher::block_padding::Iso10126>;
pub type Aes256CbcIso10126 = AesCbc<aes::Aes256, aes::cipher::block_padding::Iso10126>;
pub type Aes128CbcAnsiX923 = AesCbc<aes::Aes128, aes::cipher::block_padding::AnsiX923>;
pub type Aes256CbcAnsiX923 = AesCbc<aes::Aes256, aes::cipher::block_padding::AnsiX923>;
pub struct AeadWrapper<A: AeadInPlace>(A);
impl<A: KeyInit + AeadInPlace> AeadWrapper<A> {
pub fn new(key: AesKey<A::KeySize>) -> Self {
Self(A::new(&key.bytes))
}
}
impl<A: AeadInPlace> AuthenticatedCipher for AeadWrapper<A>
where
<A as AeadCore>::NonceSize: Debug,
{
type IVType = InitializationVector<<A as AeadCore>::NonceSize>;
fn encrypt_authenticated(&self, iv: &Self::IVType, aad: &[u8], plaintext: &[u8]) -> Vec<u8> {
let mut buffer: Vec<u8> = plaintext.to_vec();
self.0
.encrypt_in_place(&iv.bytes, aad, &mut buffer)
.unwrap();
buffer
}
fn decrypt_authenticated(
&self,
iv: &Self::IVType,
aad: &[u8],
ciphertext: &[u8],
) -> Result<Vec<u8>, FastCryptoError> {
if iv.as_bytes().is_empty() {
return Err(FastCryptoError::InputTooShort(1));
}
let mut buffer: Vec<u8> = ciphertext.to_vec();
self.0
.decrypt_in_place(&iv.bytes, aad, &mut buffer)
.map_err(|_| FastCryptoError::GeneralOpaqueError)?;
Ok(buffer)
}
}
pub type Aes128Gcm<NonceSize> = AeadWrapper<aes_gcm::AesGcm<aes::Aes128, NonceSize>>;
pub type Aes256Gcm<NonceSize> = AeadWrapper<aes_gcm::AesGcm<aes::Aes256, NonceSize>>;
pub type Aes256GcmSiv = AeadWrapper<aes_gcm_siv::Aes256GcmSiv>;