How to use Aes256?

I want to use AES256 for en/-decryption of data with arbitrary size. Currently I'm stuck with the following code:

use aes::{
    cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
    Aes256,
};

use crate::def::{Encryption, ZarError};
use crate::options::Secret;

pub fn encrypt(data: Vec<u8>, secret: &Secret) -> Result<Vec<u8>, ZarError> {
    let key = GenericArray::from_slice(&secret.password.as_bytes());
    let cipher = Aes256::new(key);
    let mut encrypted = data
        .chunks_mut(16)
        .map(|_| GenericArray::from_slice)
        .collect(); // <-- This line fails to compile

    cipher.encrypt_blocks(&mut encrypted);
    Ok(encrypted.to_vec())
}

pub fn decrypt(
    data: Vec<u8>,
    encryption: &Encryption,
    secret: &Secret,
) -> Result<Vec<u8>, ZarError> {
    if encryption != &Encryption::AES256 {
        return Err(ZarError::DifferentEncryptionMethod("AES256".to_string()));
    }
    let key = GenericArray::from_slice(secret.password.as_bytes());
    let cipher = Aes256::new(key);
    let mut decrypted = GenericArray::clone_from_slice(&data);
    cipher.decrypt_block(&mut decrypted);
    Ok(decrypted.to_vec())
}

It fails to compile. The error message is:
"the size for values of type[GenericArray<u8, UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>>]cannot be known at compilation time\nthe traitSizedis not implemented for[GenericArray<u8, UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>>]\nall local variables must have a statically known size\nunsized locals are gated as an unstable feature"

This:

means "map a closure that ignores its argument and returns the GenericArray::from_slice method itself". That's likely not what you wanted. Did you mean, by any chance, the following?

.map(GenericArray::from_slice)

Unless you are 100% confident in your cryptographic knowledge, you should use an AEAD algorithm (a SIV mode would be the most forgiving one).

Your code is riddled with beginner mistakes:

  1. Using the ECB block mode of operation (sic!), at the very least you should use something like CBC or other block mode.
  2. Not using any ciphertext authentication.
  3. Using password as an encryption key directly instead of passing it through a password hash.
  4. Using manual chunking without padding, even though the cipher traits have convenience methods for that.
  5. Having a bunch of unnecessary allocations.
  6. Using hard-coded magical constants instead of relying on block size defined for the AES cipher types.

If it's anything more than a learning exercise, I would strongly advice you to first learn a bit more about cryptography and modern algorithms before attempting to use them.

4 Likes

Thank you very much for your reply! I've just started experimenting with encryption. Your answer helps me a lot.

In addition to the problems pointed out by others, note that an Aes256 key must be exactly 32 bytes,
so while I don't know how secret.password is create,

will be a problem.

(I should note that I have been struggling with GenericArray myself, so I don't have a specific recommendation that that among other things you need to make sure that that slice is exactly 32 bytes.