Skip to content

Commit

Permalink
Add aes-gcm-siv
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas-lj committed Oct 24, 2024
1 parent 2f502fd commit 16f3420
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 24 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion fastcrypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ aes = { version = "0.8.2", optional = true }
ctr = { version = "0.9.2", optional = true }
cbc = { version = "0.1.2", features = ["std"], optional = true }
aes-gcm = { version = "0.10.1", optional = true }
aes-gcm-siv = { version = "0.11.1", optional = true }

[[bench]]
name = "crypto"
Expand Down Expand Up @@ -111,7 +112,7 @@ unsecure_schemes = ["dep:twox-hash", "dep:serde-big-array"]
experimental = ["dep:bulletproofs", "dep:merlin"]

# Include AES and its modes.
aes = ["dep:aes", "dep:cbc", "dep:aes-gcm", "dep:ctr"]
aes = ["dep:aes", "dep:cbc", "dep:aes-gcm", "dep:ctr", "dep:aes-gcm-siv"]

[dev-dependencies]
criterion = "0.4.0"
Expand Down
74 changes: 51 additions & 23 deletions fastcrypto/src/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ use aes::cipher::{
BlockCipher, BlockDecrypt, BlockDecryptMut, BlockEncrypt, BlockEncryptMut, BlockSizeUser,
KeyInit, KeyIvInit, KeySizeUser, StreamCipher,
};
use aes_gcm::AeadInPlace;
use aes_gcm::{aead::Aead, 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, U24, U32};
use typenum::{U12, U16, U24, U32};
use zeroize::{Zeroize, ZeroizeOnDrop};

/// Trait impl'd by encryption keys in symmetric cryptography
Expand Down Expand Up @@ -81,6 +81,18 @@ pub trait AuthenticatedCipher {
) -> 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)
}
}

/// Struct wrapping an instance of a `generic_array::GenericArray<u8, N>`.
#[derive(Clone, Serialize, Deserialize, SilentDebug, SilentDisplay, ZeroizeOnDrop)]
#[serde(bound = "N: ArrayLength<u8>")]
Expand Down Expand Up @@ -288,7 +300,7 @@ where
let cipher = aes_gcm::AesGcm::<Aes, NonceSize>::new(&self.key.bytes);
let mut buffer: Vec<u8> = plaintext.to_vec();
cipher
.encrypt_in_place(iv.as_bytes().into(), aad, &mut buffer)
.encrypt_in_place(&iv.bytes, aad, &mut buffer)
.unwrap();
buffer
}
Expand All @@ -305,34 +317,50 @@ where
let cipher = aes_gcm::AesGcm::<Aes, NonceSize>::new(&self.key.bytes);
let mut buffer: Vec<u8> = ciphertext.to_vec();
cipher
.decrypt_in_place(iv.as_bytes().into(), aad, &mut buffer)
.decrypt_in_place(&iv.bytes, aad, &mut buffer)
.map_err(|_| FastCryptoError::GeneralOpaqueError)?;
Ok(buffer)
}
}

impl<KeySize: ArrayLength<u8>, Aes, NonceSize> Cipher for AesGcm<KeySize, Aes, NonceSize>
where
Aes: KeySizeUser<KeySize = KeySize>
+ KeyInit
+ BlockCipher
+ BlockSizeUser<BlockSize = U16>
+ BlockEncrypt,
NonceSize: ArrayLength<u8> + Debug,
{
type IVType = InitializationVector<NonceSize>;
/// AES128 in GCM-mode (authenticated) using the given nonce size.
pub type Aes128Gcm<NonceSize> = AesGcm<U16, aes::Aes128, NonceSize>;

fn encrypt(&self, iv: &Self::IVType, plaintext: &[u8]) -> Vec<u8> {
self.encrypt_authenticated(iv, b"", plaintext)
}
/// AES256 in GCM-mode (authenticated) using the given nonce size.
pub type Aes256Gcm<NonceSize> = AesGcm<U32, aes::Aes256, NonceSize>;

fn decrypt(&self, iv: &Self::IVType, ciphertext: &[u8]) -> Result<Vec<u8>, FastCryptoError> {
self.decrypt_authenticated(iv, b"", ciphertext)
pub struct Aes256GcmSiv(aes_gcm_siv::Aes256GcmSiv);

impl Aes256GcmSiv {
fn new(key: AesKey<U32>) -> Self {
Aes256GcmSiv(aes_gcm_siv::Aes256GcmSiv::new(&key.bytes))
}
}

/// AES128 in GCM-mode (authenticated) using the given nonce size.
pub type Aes128Gcm<NonceSize> = AesGcm<U16, aes::Aes128, NonceSize>;
impl AuthenticatedCipher for Aes256GcmSiv {
type IVType = InitializationVector<U12>;

/// AES256 in GCM-mode (authenticated) using the given nonce size.
pub type Aes256Gcm<NonceSize> = AesGcm<U32, aes::Aes256, 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)
}
}

0 comments on commit 16f3420

Please sign in to comment.