Does any Rust create or standart lib provide possibility to encrypt/decrypt with AES256 in ECB mode with no padding?

Hi everyone.
I know that AES in ECB mode with no padding not pretty secure but to keep backward compatibility I need to make encryption/description functionality. But when I tried to find any crate where I can just call encrypt/decrypt without any additional codding I've failed. Currently I'm using openssl crate for AES but looks like it doesn't provide possibility to set padding and after encryption (even if data length doesn't need padding) it adds addition 16 bytes of padding (assuming that PKCS5 is used by default). This is a reason I'm truncating final result vector. Here is my code

use openssl::symm::{Cipher, decrypt, encrypt};

//here I'm defining if I need to truncate result in the future and what length output vector should be 
let padded_size: usize = if data.len() % cipher.block_size() != 0 { 
                    cipher.block_size() - (data.len() % cipher.block_size()) + data.len()
                } else {
                    data.len()
                };

//This part is to manually make encryption with out padding 
let mut data_padded = vec![0u8; data.len()];
data_padded.copy_from_slice(data);
data_padded.resize(padded_size, 0u8);

let mut res = encrypt(cipher, key, None, &data_padded).expect("Encryption failed");
res.truncate(padded_size);
//use result of encryption

My question - is there any crate to make encryption/decryption simpler with out all of this manual padding and other things (like in Java)?

Thanks in advance.

The aes crate should be sufficient for your needs. After enabling the block-padding feature for the cipher crate (this crate defines a set trais implemented by cipher implementations), you can use BlockEncrypt::encrypt_padded/BlockDecrypt::decrypt_padded methods with NoPadding struct in the place of generic parameter P.

2 Likes

Thanks for explanation, but I can't understand how to use this function

cipher::BlockEncrypt::encrypt_padded::<cipher::block_padding::NoPadding>(&self, buf: &'a mut [u8], msg_len: usize);

What is self in this case? Where to put key and plain data?

BlockEncrypt is a trait implemented by types defined in the aes crate. You first need to initialize a cipher instance using the KeyInit trait, then you will be able to use encrypt_padded method on it (assuming you have not forgot to import BlockEncrypt).

Code can look roughly like this (not checked):

use aes::{
    Aes128,
    cipher::{BlockEncrypt, KeyInit, block_padding::NoPadding},
};
let cipher = Aes128::new_from_slice(key).unwrap();
let mut buf = [0u8; 64];
cipher.encrypt_padded::<NoPadding>(&mut buf).unwrap();
2 Likes

Thanks, looks like I've made working code

let cipher = Aes256::new_from_slice(key).unwrap();
let size = data.len();
cipher.encrypt_padded::<block_padding::NoPadding>(data, size);

But when I'm trying to decrypt result in Java I'm getting Input length not multiple of 16 bytes exception which obvious because encrypted data is doesn't multiply 16. So I assume that before encryption data should be manually padded that leads me to my first solution

P.S. I never saw that output array i produced from original, I'm getting result in data

NoPadding assumes that your data is multiple of block size and will panic otherwise. Your code above implements padding by zeros, so you probably should use block_padding::ZeroPadding, at least for encryption.

Paddings are not just for more security. As a block cipher, the AES can't represent/understand messages whose size is not a multiple of its block size. You can use the ChaCha20 instead of the AES which is a stream cipher.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.