134 lines
4.2 KiB
Rust
134 lines
4.2 KiB
Rust
use aes::Aes256;
|
|
use cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
|
|
|
type AesEncryptor = cbc::Encryptor<Aes256>;
|
|
type AesDecryptor = cbc::Decryptor<Aes256>;
|
|
|
|
/// 利用Sha256生成32字节的密钥
|
|
///
|
|
/// - `key` 原始密钥
|
|
fn generate_key<T: AsRef<[u8]>>(key: T) -> [u8; 32] {
|
|
let mut hasher = hmac_sha256::Hash::new();
|
|
hasher.update(key);
|
|
let result = hasher.finalize();
|
|
result
|
|
}
|
|
|
|
/// 利用给定的密钥生成16字节的初始向量
|
|
fn generate_iv(key: &[u8; 32]) -> [u8; 16] {
|
|
let mut result = [0u8; 16];
|
|
for i in 0..16 {
|
|
result[i] = key[i] ^ key[i + 16];
|
|
}
|
|
result
|
|
}
|
|
|
|
/// 使用指定的密钥和填充方式对数据进行加密。
|
|
/// 如果需要字符串形式的密文,可以配合使用`hex`或者`base64`等函数。
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `padding` 填充方式
|
|
/// - `plain_data` 明文数据
|
|
pub fn encrypt<T: AsRef<[u8]>, D: AsRef<[u8]>>(
|
|
key: T,
|
|
padding: super::Padding,
|
|
plain_data: D,
|
|
) -> Vec<u8> {
|
|
let key = generate_key(key);
|
|
let iv = generate_iv(&key);
|
|
let encryptor = AesEncryptor::new(&key.into(), &iv.into());
|
|
let result = match padding {
|
|
super::Padding::NoPadding => encryptor
|
|
.encrypt_padded_vec_mut::<cipher::block_padding::NoPadding>(plain_data.as_ref()),
|
|
super::Padding::ZeroPadding => encryptor
|
|
.encrypt_padded_vec_mut::<cipher::block_padding::ZeroPadding>(plain_data.as_ref()),
|
|
super::Padding::Pkcs7Padding => {
|
|
encryptor.encrypt_padded_vec_mut::<cipher::block_padding::Pkcs7>(plain_data.as_ref())
|
|
}
|
|
};
|
|
result
|
|
}
|
|
|
|
/// 使用指定的密钥和填充方式对数据进行解密。
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `padding` 填充方式
|
|
/// - `cipher_data` 密文数据
|
|
pub fn decrypt<T: AsRef<[u8]>, D: AsRef<[u8]>>(
|
|
key: T,
|
|
padding: super::Padding,
|
|
cipher_data: D,
|
|
) -> Result<Vec<u8>, super::DecryptFailedError> {
|
|
let key = generate_key(key);
|
|
let iv = generate_iv(&key);
|
|
let decryptor = AesDecryptor::new(&key.into(), &iv.into());
|
|
match padding {
|
|
super::Padding::NoPadding => decryptor
|
|
.decrypt_padded_vec_mut::<cipher::block_padding::NoPadding>(cipher_data.as_ref())
|
|
.map_err(|_| super::DecryptFailedError {}),
|
|
super::Padding::ZeroPadding => decryptor
|
|
.decrypt_padded_vec_mut::<cipher::block_padding::ZeroPadding>(cipher_data.as_ref())
|
|
.map_err(|_| super::DecryptFailedError {}),
|
|
super::Padding::Pkcs7Padding => decryptor
|
|
.decrypt_padded_vec_mut::<cipher::block_padding::Pkcs7>(cipher_data.as_ref())
|
|
.map_err(|_| super::DecryptFailedError {}),
|
|
}
|
|
}
|
|
|
|
/// 快捷无填充加密函数
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `plain_data` 明文数据
|
|
pub fn encrypt_no_padding<T: AsRef<[u8]>, D: AsRef<[u8]>>(key: T, plain_data: D) -> Vec<u8> {
|
|
encrypt(key, super::Padding::NoPadding, plain_data)
|
|
}
|
|
|
|
/// 快捷无填充解密函数
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `cipher_data` 密文数据
|
|
pub fn decrypt_no_padding<T: AsRef<[u8]>, D: AsRef<[u8]>>(
|
|
key: T,
|
|
cipher_data: D,
|
|
) -> Result<Vec<u8>, super::DecryptFailedError> {
|
|
decrypt(key, super::Padding::NoPadding, cipher_data)
|
|
}
|
|
|
|
/// 快捷零填充加密函数
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `plain_data` 明文数据
|
|
pub fn encrypt_zero_padding<T: AsRef<[u8]>, D: AsRef<[u8]>>(key: T, plain_data: D) -> Vec<u8> {
|
|
encrypt(key, super::Padding::ZeroPadding, plain_data)
|
|
}
|
|
|
|
/// 快捷零填充解密函数
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `cipher_data` 密文数据
|
|
pub fn decrypt_zero_padding<T: AsRef<[u8]>, D: AsRef<[u8]>>(
|
|
key: T,
|
|
cipher_data: D,
|
|
) -> Result<Vec<u8>, super::DecryptFailedError> {
|
|
decrypt(key, super::Padding::ZeroPadding, cipher_data)
|
|
}
|
|
|
|
/// 快捷Pkcs7填充加密函数
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `plain_data` 明文数据
|
|
pub fn encrypt_pkcs7_padding<T: AsRef<[u8]>, D: AsRef<[u8]>>(key: T, plain_data: D) -> Vec<u8> {
|
|
encrypt(key, super::Padding::Pkcs7Padding, plain_data)
|
|
}
|
|
|
|
/// 快捷Pkcs7填充解密函数
|
|
///
|
|
/// - `key` 密钥
|
|
/// - `cipher_data` 密文数据
|
|
pub fn decrypt_pkcs7_padding<T: AsRef<[u8]>, D: AsRef<[u8]>>(
|
|
key: T,
|
|
cipher_data: D,
|
|
) -> Result<Vec<u8>, super::DecryptFailedError> {
|
|
decrypt(key, super::Padding::Pkcs7Padding, cipher_data)
|
|
}
|