Aes算法是现在使用普遍的对称性加密的算法。对于一个字符串,或相关的文件,它是如何加密,如何解密的,通过代码,可以进行很好的复现,也便于增进对加密与解密的了解。
一、从一个字符串说起
extern crate crypto;
extern crate rand;
use crypto::buffer::{BufferResult, ReadBuffer, WriteBuffer};
use crypto::{aes, blockmodes, buffer, symmetriccipher};
use std::{thread, time};
use rand::RngCore;
use rand::{OsRng, Rng};
use std::str;
fn encrypt(
data: &[u8],
key: &[u8],
iv: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
let mut encryptor =
aes::cbc_encryptor(aes::KeySize::KeySize256, 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 = try!(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)
}
fn decrypt(
encrypted_data: &[u8],
key: &[u8],
iv: &[u8],
) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
let mut decryptor =
aes::cbc_decryptor(aes::KeySize::KeySize256, 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 = try!(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)
}
fn main() {
let sleep_seconds = time::Duration::from_secs(1000);
let message = "I love Rust,Julia & Python, they are so cool! ";
let mut key: [u8; 32] = [0; 32];
let mut iv: [u8; 16] = [0; 16];
let mut rng = OsRng::new().ok().unwrap();
rng.fill_bytes(&mut key);
rng.fill_bytes(&mut iv);
println!("key:{:?}", key);
println!("iv:{:?}", iv);
let encrypted_data = encrypt(message.as_bytes(), &key, &iv).ok().unwrap();
let message_bytes = message.as_bytes();
println!(
"message->as_bytes:{:?}, byte_len:{}",
message_bytes,
message_bytes.len()
);
println!(
"message->encrypted:{:?} byte_len:{}",
encrypted_data,
encrypted_data.len()
);
let decrypted_data = decrypt(&encrypted_data[..], &key, &iv).ok().unwrap();
let the_string = str::from_utf8(&decrypted_data).expect("not UTF-8");
assert!(message_bytes == &decrypted_data[..]);
assert!(message == the_string);
println!("the_string:{:?}", the_string);
thread::sleep(sleep_seconds);
}
输出结果:
可以看到,不管是解密的字节数组还是字符串比对,解密都是正确的。
二、加密及解密的过程
从上面我们看出,加密的过程,比如,字符串首先是转化是字节向量(数组),然后,加密成新的字节向量(数组),加密后的向量的长度与原字节向量是大概率是不相同的。另外,也无法解析成另一个字符串。
如果是一个文件,或一个文件夹呢,或压缩的文件,原理也是一样。