Rust中AES加密算法的基本使用

最近一直在研究在rust里使用AES以及各种加密模式。然而,rust里目前的第三方库比较多,而且使用起来也并不容易上手。因此,本文记录rust里AES加密算法不同模式的基本实现方式。

AES CTR

Cargo.toml

hex-literal = "0.3.4"
aes = "0.8"
ctr = "0.9"

注意:

  • ctr 是block-modes 下推荐的库:


本小节的代码也是参考ctr文档中的:

use aes::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
use hex_literal::hex;
type Aes128Ctr64LE = ctr::Ctr64LE<aes::Aes128>;

fn main() {
    let key = [0x42; 16];
    let iv = [0x24; 16];
    let plaintext = *b"hello world! this is my plaintext.";
    let ciphertext = hex!("3357121ebb5a29468bd861467596ce3da59bdee42dcc0614dea955368d8a5dc0cad4");

    // encrypt in-place
    let mut buf = plaintext.to_vec();
    let mut cipher = Aes128Ctr64LE::new(&key.into(), &iv.into());
    cipher.apply_keystream(&mut buf); // 完成加密
    assert_eq!(buf[..], ciphertext[..]);
    
    // CTR mode can be used with streaming messages
    let mut cipher = Aes128Ctr64LE::new(&key.into(), &iv.into());
    for chunk in buf.chunks_mut(3) {
        cipher.apply_keystream(chunk);
    }
    assert_eq!(buf[..], plaintext[..]);

    // CTR mode supports seeking. The parameter is zero-based _bytes_ counter (not _blocks_).
    cipher.seek(0u32);

    // encrypt/decrypt from buffer to buffer
    // buffer length must be equal to input length
    let mut buf1 = [0u8; 34];
    cipher.apply_keystream_b2b(&plaintext, &mut buf1).unwrap();
    assert_eq!(buf1[..], ciphertext[..]);

    let mut buf2 = [0u8; 34];
    cipher.seek(0u32);
    cipher.apply_keystream_b2b(&buf1, &mut buf2).unwrap();
    assert_eq!(buf2[..], plaintext[..]);
}

AES ECB

在前面的block-modes中一直没有发现ECB模式,直到在其PR里看到相关的讨论:

直接使用aes::Aes128就是默认的ECB mode,还有一个关键问题就是padding的问题。

上面提到直接在encryption/decryption里指定方法,并且让我们参考cbc文档中的代码:
Rust中AES加密算法的基本使用_第1张图片

可以看到是在这里指定里padding的方式。

现在我们尝试写一个Aes ECB模式的样例代码,经过测试,需要引入如下crate和feature,才能够顺利使用Aes以及padding:

aes = "0.8"
ctr = "0.9"
cipher = {version = "0.4.3", features=["block-padding"]}

必须要指定 features=["block-padding"], 才能在源码里使用 use aes::cipher::block_padding::*;

下面是最基础的一个版本:

use aes::{Aes128, Aes128Enc, Aes128Dec};
use aes::cipher::{
    BlockCipher, BlockEncrypt, BlockDecrypt, KeyInit,
    generic_array::GenericArray,
};
use aes::cipher::{BlockEncryptMut, BlockDecryptMut};
use aes::cipher::block_padding::Pkcs7;

fn main() {

    // 注意key的类型
    let key = GenericArray::from([0u8; 16]);
    let plaintext = *b"hello world! this is my plaintext.";
    let pt_len = plaintext.len();

    let enc_cipher = Aes128Enc::new(&key);
    let dec_cipher = Aes128Dec::new(&key);
    // in-place
    // 注意这里的长度是 ((pt_len + 15)/16) * 16
    // 不然会panic
    let mut ct_buf = [0u8; 48]; 
    enc_cipher.encrypt_padded_b2b_mut::<Pkcs7>(&plaintext, &mut ct_buf).unwrap();

    let mut dec_buf = [0u8; 48];
    dec_cipher.decrypt_padded_b2b_mut::<Pkcs7>(&ct_buf,  &mut dec_buf).unwrap();


    assert_eq!(plaintext, dec_buf[..pt_len]);

}

你可能感兴趣的:(rust)