You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
8.5 KiB

//! Advanced Encryption Standard
use super::*;
#[allow(unused_imports)]
use std::{
fmt,
marker::Unpin,
io,
};
use openssl::{
symm::{
Cipher,
Crypter,
Mode,
},
};
#[cfg(feature="async")]
use tokio::io::{
AsyncRead,
AsyncReadExt,
AsyncWrite,
AsyncWriteExt,
};
use getrandom::getrandom;
const KEYSIZE: usize = consts::AES_KEYSIZE;
const IVSIZE: usize = consts::AES_IVSIZE;
use consts::BUFFER_SIZE;
const BLOCKSIZE: usize = 16;
/// A key and IV for the AES algorithm
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, PartialOrd, Ord)]
#[cfg_attr(feature="serialise", derive(Serialize,Deserialize))]
#[repr(align(1))]
pub struct AesKey {
key: [u8; KEYSIZE],
iv: [u8; IVSIZE],
}
impl AesKey
{
/// Generate a new AES key and IV.
pub fn generate() -> Result<Self, Error>
{
let mut this = Self::default();
getrandom(&mut this.key[..])?;
getrandom(&mut this.iv[..])?;
Ok(this)
}
/// Generate a new random AES key and IV.
///
/// # Deprecated
/// Use `AesKey::generate()` instead.
#[deprecated] #[inline] pub fn random() -> Result<Self, Error>
{
Self::generate()
}
/// Create a new instance from a key and IV
pub const fn new(key: [u8; KEYSIZE], iv: [u8; IVSIZE]) -> Self
{
Self{key,iv}
}
/// Consume into the key and IV parts
pub const fn into_parts(self) -> ([u8; KEYSIZE], [u8; IVSIZE])
{
(self.key, self.iv)
}
/// Consume this instance into the full byte buffer
pub fn into_bytes(self) -> [u8; KEYSIZE+IVSIZE]
{
unsafe { std::mem::transmute(self) }
}
/// Consume a full byte buffer into an AES key
pub fn from_bytes(from: [u8; KEYSIZE+IVSIZE]) -> Self
{
unsafe { std::mem::transmute(from) }
}
/// Create a zero inisialised key
#[inline] pub const fn empty() -> Self
{
Self { iv: [0; IVSIZE], key: [0; KEYSIZE]}
}
/// Create a new instance from slices
pub fn from_slice(key: impl AsRef<[u8]>, iv: impl AsRef<[u8]>) -> Result<Self,Error>
{
let mut this = Self::default();
if bytes::copy_slice(&mut this.key[..], key.as_ref()) != this.key.len() {
Err(Error::Length{expected: Some(this.key.len()), got: None})
} else {
Ok(())
}?;
if bytes::copy_slice(&mut this.iv[..], iv.as_ref()) != this.iv.len() {
Err(Error::Length{expected: Some(this.iv.len()), got: None})
} else {
Ok(this)
}
}
/// The key part of this `AesKey` instance
pub fn k(&self) -> &[u8]
{
&self.key[..]
}
/// The IV part of this `AesKey` instance
pub fn i(&self) -> &[u8]
{
&self.iv[..]
}
/// A mutable reference of the key part of this `AesKey` instance
pub fn k_mut(&mut self) -> &mut [u8]
{
&mut self.key[..]
}
/// A mutable reference of the IV part of this `AesKey` instance
pub fn i_mut(&mut self) -> &mut [u8]
{
&mut self.iv[..]
}
}
impl AsRef<[u8]> for AesKey
{
fn as_ref(&self) -> &[u8]
{
bytes::refer(self)
}
}
impl AsMut<[u8]> for AesKey
{
fn as_mut(&mut self) -> &mut [u8]
{
bytes::refer_mut(self)
}
}
impl fmt::Display for AesKey
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "AesKey (Key: ")?;
for byte in self.key.iter() {
write!(f, "{:0x}", byte)?;
}
write!(f, ", IV: ")?;
for byte in self.iv.iter() {
write!(f, "{:0x}", byte)?;
}
write!(f, ")")
}
}
/// Encrypt a stream into another using a key
#[cfg(feature="async")]
pub async fn encrypt_stream<F,T>(key: &AesKey, from: &mut F, to: &mut T) -> Result<usize, Error>
where F: AsyncRead + Unpin + ?Sized,
T: AsyncWrite + Unpin + ?Sized
{
let mut read;
let mut done=0;
let mut crypter = Crypter::new(Cipher::aes_128_cbc(), Mode::Encrypt, &key.key[..], Some(&key.iv[..]))?;
let mut buffer = [0u8; BUFFER_SIZE];
let mut crypt_buffer = [0u8; BUFFER_SIZE + BLOCKSIZE];
while {read = from.read(&mut buffer[..]).await?; read!=0} {
let bytes_encrypted = crypter.update(&buffer[..read], &mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted]).await?;
done += bytes_encrypted;
}
let bytes_encrypted = crypter.finalize(&mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted]).await?;
Ok(done + bytes_encrypted)
}
/// Encrypt a stream into another using a key
pub fn encrypt_stream_sync<F,T>(key: &AesKey, from: &mut F, to: &mut T) -> Result<usize, Error>
where F: io::Read + ?Sized,
T: io::Write + ?Sized
{
let mut read;
let mut done=0;
let mut crypter = Crypter::new(Cipher::aes_128_cbc(), Mode::Encrypt, &key.key[..], Some(&key.iv[..]))?;
let mut buffer = [0u8; BUFFER_SIZE];
let mut crypt_buffer = [0u8; BUFFER_SIZE + BLOCKSIZE];
while {read = from.read(&mut buffer[..])?; read!=0} {
let bytes_encrypted = crypter.update(&buffer[..read], &mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted])?;
done += bytes_encrypted;
}
let bytes_encrypted = crypter.finalize(&mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted])?;
Ok(done + bytes_encrypted)
}
/// Decrypt a stream into another using a key
#[cfg(feature="async")]
pub async fn decrypt_stream<F,T>(key: &AesKey, from: &mut F, to: &mut T) -> Result<usize, Error>
where F: AsyncRead + Unpin + ?Sized,
T: AsyncWrite + Unpin + ?Sized
{
let mut read;
let mut done=0;
let mut crypter = Crypter::new(Cipher::aes_128_cbc(), Mode::Decrypt, &key.key[..], Some(&key.iv[..]))?;
let mut buffer = [0u8; BUFFER_SIZE];
let mut crypt_buffer = [0u8; BUFFER_SIZE + BLOCKSIZE];
while {read = from.read(&mut buffer[..]).await?; read!=0} {
let bytes_encrypted = crypter.update(&buffer[..read], &mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted]).await?;
done += bytes_encrypted;
}
let bytes_encrypted = crypter.finalize(&mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted]).await?;
Ok(done + bytes_encrypted)
}
/// Decrypt a stream into another using a key
pub fn decrypt_stream_sync<F,T>(key: &AesKey, from: &mut F, to: &mut T) -> Result<usize, Error>
where F: io::Read + ?Sized,
T: io::Write + ?Sized
{
let mut read;
let mut done=0;
let mut crypter = Crypter::new(Cipher::aes_128_cbc(), Mode::Decrypt, &key.key[..], Some(&key.iv[..]))?;
let mut buffer = [0u8; BUFFER_SIZE];
let mut crypt_buffer = [0u8; BUFFER_SIZE + BLOCKSIZE];
while {read = from.read(&mut buffer[..])?; read!=0} {
let bytes_encrypted = crypter.update(&buffer[..read], &mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted])?;
done += bytes_encrypted;
}
let bytes_encrypted = crypter.finalize(&mut crypt_buffer)?;
to.write_all(&crypt_buffer[..bytes_encrypted])?;
Ok(done + bytes_encrypted)
}
/// Decrypt a slice to a `Vec<u8>` async
#[cfg(feature="async")]
pub async fn decrypt_slice(key: &AesKey, from: impl AsRef<[u8]>) -> Result<Vec<u8>, Error>
{
let from = from.as_ref();
let mut to = Vec::with_capacity(from.len() + 128);
decrypt_stream(key, &mut &from[..], &mut to).await?;
Ok(to)
}
/// Decrypt a slice to a `Vec<u8>` sync
pub fn decrypt_slice_sync(key: &AesKey, from: impl AsRef<[u8]>) -> Result<Vec<u8>, Error>
{
let from = from.as_ref();
let mut to = Vec::with_capacity(from.len() + 128);
decrypt_stream_sync(key, &mut &from[..], &mut to)?;
Ok(to)
}
/// Encrypt a slice to a `Vec<u8>` async
#[cfg(feature="async")]
pub async fn encrypt_slice(key: &AesKey, from: impl AsRef<[u8]>) -> Result<Vec<u8>, Error>
{
let from = from.as_ref();
let mut to = Vec::with_capacity(from.len() + 128);
encrypt_stream(key, &mut &from[..], &mut to).await?;
Ok(to)
}
/// Encrypt a slice to a `Vec<u8>` sync
pub fn encrypt_slice_sync(key: &AesKey, from: impl AsRef<[u8]>) -> Result<Vec<u8>, Error>
{
let from = from.as_ref();
let mut to = Vec::with_capacity(from.len() + 128);
encrypt_stream_sync(key, &mut &from[..], &mut to)?;
Ok(to)
}
pub use crate::error::aes::Error;
#[cfg(test)]
mod tests
{
#[test]
fn transmute_safe()
{
use std::mem::{size_of, align_of};
assert_eq!(size_of::<super::AesKey>(), size_of::<[u8; super::KEYSIZE + super::IVSIZE]>());
assert_eq!(align_of::<super::AesKey>(), align_of::<[u8; super::KEYSIZE + super::IVSIZE]>());
let key = super::AesKey::generate().unwrap();
let bytes = Vec::from(key.as_ref());
let tbytes = key.clone().into_bytes();
let nkey = super::AesKey::from_bytes(tbytes);
assert_eq!(nkey, key);
assert_eq!(&bytes[..], &tbytes[..]);
assert_eq!(key.as_ref(), &tbytes[..]);
}
}