通常加密密钥不要出现在源码中,比如配置文件中的数据库密码等。解决方案通常采用将密钥存放在环境变量中,进程启动时从环境变量获取密钥加载到内存中。
还有一种方案,对密钥进行加密,源码中只包含对密钥加密的根密钥和对密钥加密后的二次密钥,如果不知道加密方式,在编译出来的二进制文件中很难还原出真实的密钥。
安装依赖
bash
cargo add base64
cargo add rust-crypto
AES128加解密算法
rust
use base64::{engine::general_purpose, Engine as _};
use crypto::buffer::{BufferResult, ReadBuffer, WriteBuffer};
use crypto::{aes, blockmodes, buffer, symmetriccipher};
pub fn aes128_cbc_encrypt(
data: &[u8],
key: &[u8],
iv: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
let mut encryptor = aes::cbc_encryptor(
aes::KeySize::KeySize128,
key,
iv,
blockmodes::PkcsPadding,
);
let mut final_result = Vec::<u8>::new();
let mut read_buffer = buffer::RefReadBuffer::new(data);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result =
encryptor.encrypt(&mut read_buffer, &mut write_buffer, true)?;
final_result.extend(
write_buffer
.take_read_buffer()
.take_remaining()
.iter()
.map(|&i| i),
);
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
Ok(final_result)
}
pub fn aes128_cbc_decrypt(
encrypted_data: &[u8],
key: &[u8],
iv: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
let mut decryptor = aes::cbc_decryptor(
aes::KeySize::KeySize128,
key,
iv,
blockmodes::PkcsPadding,
);
let mut final_result = Vec::<u8>::new();
let mut read_buffer = buffer::RefReadBuffer::new(encrypted_data);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result =
decryptor.decrypt(&mut read_buffer, &mut write_buffer, true)?;
final_result.extend(
write_buffer
.take_read_buffer()
.take_remaining()
.iter()
.map(|&i| i),
);
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
Ok(final_result)
}
base64编码得到二次密钥
将加密后的秘钥存放在配置文件中。
rust
pub fn aes128_base64_encrypt(
key: &[u8],
iv: &[u8],
plain_text: &[u8],
) -> String {
let output = aes128_cbc_encrypt(plain_text, &key, &iv).unwrap();
general_purpose::STANDARD.encode(&output)
}
base64解码获得真实的密钥
首先从配置文件中获取二次加密的秘钥,解密获得真实的秘钥,然后再用解密后的秘钥对密文进行解密 或 对明文进行加密。
rust
pub fn aes128_base64_decrypt(
key: &[u8],
iv: &[u8],
cipher_text: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
let data = general_purpose::STANDARD.decode(cipher_text).unwrap();
aes128_cbc_decrypt(&data, &key, &iv)
}
单元测试
rust
#[test]
fn test_aes128_cbc() {
let key = get_random_key16();
let iv = generate_iv();
// 加密
let plain_text = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!".to_string();
let cipher_text = aes128_base64_encrypt(&key, &iv, plain_text.as_bytes());
// 加密
let output =
aes128_base64_decrypt(&key, &iv, cipher_text.as_bytes()).unwrap();
let plain_text_2 = String::from_utf8(output).unwrap();
assert_eq!(plain_text, plain_text_2);
}