使用rust的openssl库加密/解密大文本
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用rust的openssl库加密/解密大文本相关的知识,希望对你有一定的参考价值。
我正在尝试编写一个API以使用rust的openssl包装器库来加密/解密文件。
这是库:https://docs.rs/openssl/0.10.25/openssl/index.html
文档中的所有示例,展示了如何使用Padding加密短字符串。我想加密可能很长的文件。
问题是我最多只能加密密钥的长度(使用Padding::NONE
)。我想加密更长的数据。
因此,为了解决该问题,我将数据分为多个块,对每个块进行加密/解密,然后将加密/解密的块附加到结果向量中。然后,我将其写入文件并从文件读取到矢量,然后再解密。
我的工作概述:
- 加载/生成公用/专用密钥。
- 加载文件以加密为
Vec<u8>
(或最终为字符串切片) - 使用公钥加密数据
- 将该加密数据写入文件
- 将带有加密数据的文件加载到
Vec<u8>
- 使用私钥解密
- 将解密的数据写到另一个文件。
- 比较原始数据和解密数据。
代码在这里(请注意-我将粘贴的内容复制到下面的一个块中,最初它们位于单独的模块/文件中)我最初生成rsa键,如
fn generate_rsa_key_pair() -> utils::Pair<Vec<u8>, Vec<u8>>
let rsa = Rsa::generate(4096).unwrap();
let public_pem = rsa.public_key_to_pem().unwrap();
let private_pem = rsa.private_key_to_pem().unwrap();
Pair::new(public_pem, private_pem) // custom data structure (basically a tuple)
然后将它们写入文件,并使用文件中的密钥进行后续运行。
extern crate openssl;
use openssl::pkey::Private, Public;
use openssl::rsa::Padding, Rsa;
use std::cmp::max;
use std::io::BufWriter, Result, Write;
use std::str;
fn main()
let (public, private) = generate_rsa_from_files();
let data = read_file_into_binary_vec("./resources/example_text.txt").unwrap();
let enc_data = encrypt_data_with_pubkey(data.as_slice(), public).unwrap();
println!(":?", enc_data);
binary_slice_to_file(enc_data.as_slice(), "./resources/example_enc.txt").unwrap();
let dec_data = decrypt_data_with_prikey(enc_data.as_slice(), private).unwrap();
println!("", str::from_utf8(dec_data.as_slice()).unwrap());
binary_slice_to_file(dec_data.as_slice(), "./resources/example_dec.txt").unwrap();
fn generate_rsa_from_files() -> (Vec<u8>, Vec<u8>)
let public = read_file_into_binary_vec("./resources/public_key").unwrap();
let private = read_file_into_binary_vec("./resources/private_key").unwrap();
(public, private)
fn read_file_into_binary_vec(file_path: &str) -> Result<Vec<u8>>
std::fs::read(file_path)
fn binary_slice_to_file(data: &[u8], file_path: &str) -> Result<()>
let file = std::fs::File::create(file_path)?;
let mut buf_writer = BufWriter::new(file);
buf_writer.write_all(data)
fn encrypt_data_with_pubkey(data: &[u8], pub_key: Vec<u8>) -> Result<Vec<u8>>
let data_len = data.len();
let public_rsa: Rsa<Public> = Rsa::public_key_from_pem(pub_key.as_slice())?;
let buf_len = public_rsa.size() as usize;
let mut buffer: Vec<u8> = vec![0; buf_len];
let mut encrypted_data: Vec<u8> = Vec::with_capacity(max(data_len, buf_len));
println!("", public_rsa.size());
for chunk in data.chunks(buf_len)
println!("Encrypting (len = ): :?", chunk.len(), chunk);
let chunk_mod;
if chunk.len() < buf_len
chunk_mod = pad_chunk_to_size(chunk, buf_len);
else
chunk_mod = Vec::from(chunk);
let chunk_mod = chunk_mod.as_slice();
println!("Encrypting (len = ): :?", chunk_mod.len(), chunk_mod);
let enc_len = public_rsa
.public_encrypt(chunk_mod, buffer.as_mut_slice(), Padding::NONE)
.expect("Error Encrypting");
println!("Enc Data Len : ", enc_len);
encrypted_data.extend_from_slice(buffer.as_slice());
Ok(encrypted_data)
fn decrypt_data_with_prikey(enc_data: &[u8], priv_key: Vec<u8>) -> Result<Vec<u8>>
let data_len = enc_data.len();
let private_rsa: Rsa<Private> = Rsa::private_key_from_pem(priv_key.as_slice())?;
let buf_len = private_rsa.size() as usize;
let mut buffer: Vec<u8> = vec![0; buf_len];
let mut decrypted_data: Vec<u8> = vec![0; data_len];
println!("", private_rsa.size());
for chunk in enc_data.chunks(buf_len)
private_rsa.private_decrypt(chunk, &mut buffer, Padding::NONE).expect("Error Decrypting");;
decrypted_data.extend_from_slice(buffer.as_slice());
Ok(decrypted_data)
fn pad_chunk_to_size(chunk: &[u8], desired_size: usize) -> Vec<u8>
let mut resized_vec = Vec::with_capacity(desired_size);
for &element in chunk
resized_vec.push(element);
while resized_vec.len() < desired_size
resized_vec.push(0);
println!(
"Desired Length = , Actual Length = ",
desired_size,
resized_vec.len()
);
resized_vec
我面临的问题是,在文件中,我在decrypted文件的开头和结尾发现了许多奇怪的字符。来自vim的图像如下所示。
我似乎无法弄清楚如何摆脱那些字符(最终会增加文件大小),如果我选择使用填充,我将如何去做同样的事情。
编辑:我应该注意,如果我将输出打印到终端,则看不到那些字符,但是它们肯定存在于文件中。
感谢您的任何帮助。
答案
这些字符是NUL
字节。它们来自您的代码中的两个区域:
- 开始时是来自
decrypt_data_with_prikey
函数。该功能:- 使用
data_len
零初始化其输出矢量; - 然后附加解密的数据到此向量。初始零永远不会被删除或覆盖。将
let mut decrypted_data: Vec<u8> = vec![0; data_len]
替换为let mut decrypted_data = Vec::new()
,以一个空向量开头。
- 使用
- 结尾部分来自您在加密期间添加的填充。您将需要以某种方式传达从加密功能添加到解密功能的填充量,以便可以将解密后的数据截断为适当的长度。
作为一点无关的说明,当使用公共/私有密钥对加密数据时,通常建议:
- 创建随机的对称键;
- 用私钥加密对称密钥;
- 用对称密钥加密数据;
- 在标题中添加加密的对称密钥,以便接收者可以知道它。
此方法有两个优点:
- 由于对称密码比不对称要快[],所以速度提高了。提高了安全性,因为它泄漏了有关非对称密钥对的信息,因此,即使攻击者设法解密消息,她也将无法解密使用相同密钥对的其他消息。
以上是关于使用rust的openssl库加密/解密大文本的主要内容,如果未能解决你的问题,请参考以下文章