60 lines
2.0 KiB
Rust
60 lines
2.0 KiB
Rust
use aes::Aes256;
|
|
use cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
|
use thiserror::Error;
|
|
|
|
type AesEncryptor = cbc::Encryptor<Aes256>;
|
|
type AesDecryptor = cbc::Decryptor<Aes256>;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum SpiralCipherError {
|
|
#[error("Encrypted data corrupted")]
|
|
CorruptedCipherData,
|
|
#[error("Decrypt failed")]
|
|
DecryptFailed,
|
|
}
|
|
|
|
/// 生成一个随机密钥
|
|
fn gen_key(seed: &str) -> [u8; 32] {
|
|
let hash = crate::hash::sha512::hash_hex(seed);
|
|
hash.as_slice()[4..36].try_into().unwrap()
|
|
}
|
|
|
|
/// 对给定的内容进行加密
|
|
///
|
|
/// - `data` 待加密的内容
|
|
pub fn encrypt(data: String) -> String {
|
|
let mut result = String::from("[");
|
|
let rand_key = crate::verifiy_code::random_verify_code(20);
|
|
let key = gen_key(&rand_key);
|
|
let iv: [u8; 16] = key[0..16].try_into().unwrap();
|
|
let encryptor = AesEncryptor::new(&key.into(), &iv.into());
|
|
let encrypted_data =
|
|
encryptor.encrypt_padded_vec_mut::<cipher::block_padding::Pkcs7>(data.as_bytes());
|
|
result.push_str(rand_key.as_ref());
|
|
result.push_str(crate::serialize::to_base64_str(&encrypted_data).as_ref());
|
|
result
|
|
}
|
|
|
|
/// 对给定的内容进行解密
|
|
///
|
|
/// - `data` 待解密的内容
|
|
pub fn decrypt(data: String) -> Result<String, SpiralCipherError> {
|
|
if !data.starts_with("[") || data.len() <= 21 {
|
|
return Ok(data);
|
|
}
|
|
let data = data[1..].to_string();
|
|
let key_seed = data[0..20].to_string();
|
|
let key = gen_key(&key_seed);
|
|
let iv: [u8; 16] = key[0..16].try_into().unwrap();
|
|
let decryptor = AesDecryptor::new(&key.into(), &iv.into());
|
|
let encrypted_data = crate::serialize::from_base64_str(&data[20..])
|
|
.map_err(|_| SpiralCipherError::CorruptedCipherData)?;
|
|
let decrypted_data = decryptor
|
|
.decrypt_padded_vec_mut::<cipher::block_padding::Pkcs7>(encrypted_data.as_slice())
|
|
.map_err(|e| {
|
|
println!("error: {}", e);
|
|
SpiralCipherError::DecryptFailed
|
|
})?;
|
|
Ok(String::from_utf8_lossy(decrypted_data.as_slice()).to_string())
|
|
}
|