本文提供了一种基于AES128算法的图片加解密的方案。可以把图片看作二进制的文本,以文本的方式加解密即可。
添加依赖
cargo add rust-crypto
cargo add windows
位图加密
use std::mem;
use windows::Win32::Graphics::Gdi::{BITMAPFILEHEADER, BITMAPINFOHEADER};
// 计算位图的文件头长度和位图信息头长度
const FILE_HEADER_LEN: usize = mem::size_of::<BITMAPFILEHEADER>();
const INFO_HEADER_LEN: usize = mem::size_of::<BITMAPINFOHEADER>();
pub fn aes128_encrypt_bmp(
key: &[u8],
iv: &[u8],
bmp_buffer: Vec<u8>,
) -> Vec<u8> {
// 计算位图头长度
let header_len = FILE_HEADER_LEN + INFO_HEADER_LEN;
// 获得位图的像素数据
let header = &bmp_buffer[..header_len];
let pixel_data = &bmp_buffer[header_len..];
// 只加密像素部分,保留头部不变
let encrypt_pixel_data =
aes128_cbc_encrypt(pixel_data, &key, &iv).unwrap();
// 生成新的位图
let mut encrypt_bmp_buffer = Vec::new();
encrypt_bmp_buffer.extend_from_slice(header);
encrypt_bmp_buffer.extend_from_slice(&encrypt_pixel_data);
encrypt_bmp_buffer
}
位图解密
pub fn aes128_decrypt_bmp(
key: &[u8],
iv: &[u8],
bmp_buffer: Vec<u8>,
) -> Vec<u8> {
let header_len = FILE_HEADER_LEN + INFO_HEADER_LEN;
let header = &bmp_buffer[..header_len];
let pixel_data = &bmp_buffer[header_len..];
// 解密像素部分
let decrypt_pixel_data =
aes128_cbc_decrypt(pixel_data, &key, &iv).unwrap();
// 生成原位图
let mut decrypt_bmp_buffer = Vec::new();
decrypt_bmp_buffer.extend_from_slice(header);
decrypt_bmp_buffer.extend_from_slice(&decrypt_pixel_data);
decrypt_bmp_buffer
}
单元测试
#[test]
fn test_aes128_encrypt_bmp() {
let key = get_random_key16();
let iv = generate_iv();
// 加密
let path = env::current_dir().unwrap().join("tests/test-image.bmp");
let bmp_buffer = fs::read(path).unwrap();
let encrypt_bmp_buffer = aes128_encrypt_bmp(&key, &iv, bmp_buffer);
let encrypt_path =
env::current_dir().unwrap().join("tests/encrypted-test-image.bmp");
fs::write(encrypt_path.as_path(), encrypt_bmp_buffer).unwrap();
// 解密
let bmp_buffer = fs::read(encrypt_path).unwrap();
let decrypt_bmp_buffer = aes128_decrypt_bmp(&key, &iv, bmp_buffer);
let encrypt_path =
env::current_dir().unwrap().join("tests/decrypted-test-image.bmp");
fs::write(encrypt_path, decrypt_bmp_buffer).unwrap();
}