当前位置: 首页 > 知识库问答 >
问题:

使用Rust的openssl库加密/解密大型文本

施俊远
2023-03-14

我正在尝试编写一个API来使用Rust的openssl包装库来加密/解密文件。

这是库:https://docs.rs/openssl/0.10.25/openssl/index.html

文档中的所有示例都展示了如何使用填充加密短字符串。我想加密可能很长的文件。

  1. 加载/生成公钥/私钥。
  2. 将要加密的文件加载到VEC (最终为字符串切片)
  3. 使用公钥加密数据
  4. 将此加密数据写入文件
  5. 将具有加密数据的文件加载到VEC
  6. 使用私钥解密
  7. 将解密的数据写入另一个文件。
  8. 比较原始数据与解密数据。

代码在这里(注意-我复制-粘贴的东西到下面的一个块,最初它们是在单独的模块/文件中)我最初生成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
}

编辑:我应该注意,如果我打印输出到终端,我看不到这些字符,但他们肯定存在于文件中。

感谢任何帮助。

共有1个答案

逄岳
2023-03-14

这些字符是nul字节。它们来自代码中的两个领域:

  • 开头的内容来自decrypt_data_with_prikey函数。该功能
    • 使用data_len零初始化其输出向量;
    • 然后将解密的数据附加到该向量。初始的零永远不会被移除或覆盖。如果要为数据预分配内存,请将让mut decrypted_data:vec =vec![0;data_len] 替换为让mut decrypted_data=vec::new()以空向量开始,或者将让mut decrypted_data=vec::with_capacity(data_len)替换为让mut decrypted_data=vec::with_capacity(data_len)

    作为一个有点不相关的注意事项,当使用公钥/私钥对加密数据时,通常建议:

    • 创建随机对称密钥;
    • 使用公钥加密对称密钥;
    • 使用对称密钥加密数据;
    • 在报头中添加加密的对称密钥,以便接收方知道它。

    这种方法有两个优点:

      null

 类似资料:
  • 如果生成RSA密钥和加密文本,如下所示 现在我想在JAVA源代码中解密。有什么办法吗?

  • 我正在尝试用AES加密一个大文件,然后解密,与原件进行比较。 这堂课总结了工作。它适用于.txt文件,但不适用于.mp3、.pdf等文件。 我们将非常感谢你的帮助。

  • 我使用以下命令加密了一个文件 openssl rand 32>test.key openssl enc-aes-256-cbc-iter 10000-pbkdf2-salt-输入test.txt-输出test.txt.enc-通过文件:test.key 我的代码 我得到的错误 我引用了以下链接 尝试使用时,仍然得到错误

  • 我正在使用以下函数通过Qt中的OpenSSL库加密我的数据: “源”在“123456789012345678901234567890123456789012ABC”中。 “密码”为“1HA!DH==SJAH48S8AK!?SKIITFI120XX”。 所以...如果我正确的话,那么EVP_BytesToKey()应该从密码中生成一个密钥,并提供数据以在后面解密字符串。 对base64编码的密钥是:

  • 我有这样的情况,我使用OpenSSL生成了一个公钥/私钥对,供gdcmanon使用,遵循他们网站上列出的说明。具体地说,我使用以下命令为gdcmanon生成密钥 然后,我就能够按照他们的指示,加密一个文件,使用 这在c.init(cipher.decrypt_mode,key)行失败; 我已经为Java6安装了JCE(我正在使用)。我不知道我做错了什么。谁能给我指出正确的方向吗。 谢谢

  • 问题内容: 我必须使用openssl命令行或C api加密xml文件。输出应为Base64。 一个Java程序将用于解密。该程序由客户提供,不能更改(他们正在将这些代码用于旧版应用程序)。正如您在下面的代码中看到的那样,客户提供了一个密码短语,因此将使用SecretKeySpec方法生成密钥。 Java代码: 我已经测试了几个命令,例如: 但是,使用Java无法成功解密给定的输出。为了进行测试,我