Rust数据加密插件库age的使用:安全高效的加密与解密工具

Rust数据加密插件库age的使用:安全高效的加密与解密工具

age logo

age是一个简单、现代且安全的文件加密库,具有小型显式密钥、无配置选项和UNIX风格的组合性特点。

安装

在您的Cargo.toml中添加:

age = "0.11"

特性标志

  • armor:启用ASCII装甲的age文件支持
  • async:启用异步API进行加密和解密
  • cli-common:为构建age CLI工具提供常用辅助函数
  • ssh:允许重用现有的SSH密钥文件进行age加密
  • web-sys:在WebAssembly目标上使用Performance计时器计算密码加密的工作因子
  • unstable:启用开发中的功能(无稳定性保证)

示例代码

以下是使用age进行加密和解密的完整示例:

use age::secrecy::Secret;
use age::{Encryptor, Decryptor};
use std::io::{Read, Write};

fn main() -> Result<(), age::AgeError> {
    // 要加密的明文
    let plaintext = "Hello, age!".as_bytes();
    
    // 生成X25519密钥对
    let key = age::x25519::Identity::generate();
    let pubkey = key.to_public();
    
    // 加密
    let encryptor = Encryptor::with_recipients(vec![Box::new(pubkey)])
        .expect("we provided a recipient");
    
    let mut encrypted = vec![];
    {
        let mut writer = encryptor.wrap_output(&mut encrypted)?;
        writer.write_all(plaintext)?;
        writer.finish()?;
    }
    
    // 解密
    let decryptor = match Decryptor::new(&encrypted[..])? {
        Decryptor::Recipients(d) => d,
        _ => unreachable!(),
    };
    
    let mut decrypted = vec![];
    {
        let mut reader = decryptor.decrypt(Secret::new(key))?;
        reader.read_to_end(&mut decrypted)?;
    }
    
    assert_eq!(plaintext, decrypted.as_slice());
    println!("Decrypted: {}", String::from_utf8_lossy(&decrypted));
    
    Ok(())
}

完整示例demo

以下是一个更完整的示例,展示了如何使用age加密文件并保存到磁盘,然后再解密:

use age::secrecy::Secret;
use age::{Encryptor, Decryptor};
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;

fn main() -> Result<(), age::AgeError> {
    // 生成X25519密钥对
    let key = age::x25519::Identity::generate();
    let pubkey = key.to_public();
    
    // 要加密的文件路径
    let plaintext_path = Path::new("plaintext.txt");
    let encrypted_path = Path::new("encrypted.age");
    let decrypted_path = Path::new("decrypted.txt");
    
    // 创建测试文件
    File::create(&plaintext_path)?.write_all(b"This is a secret message!")?;
    
    // 加密文件
    encrypt_file(&plaintext_path, &encrypted_path, &pubkey)?;
    
    // 解密文件
    decrypt_file(&encrypted_path, &decrypted_path, &key)?;
    
    println!("File encryption and decryption completed successfully!");
    Ok(())
}

fn encrypt_file(
    input_path: &Path,
    output_path: &Path,
    pubkey: &age::x25519::Recipient,
) -> Result<(), age::AgeError> {
    // 读取要加密的文件内容
    let plaintext = std::fs::read(input_path)?;
    
    // 创建加密器
    let encryptor = Encryptor::with_recipients(vec![Box::new(pubkey.clone())])
        .expect("we provided a recipient");
    
    // 创建输出文件并加密内容
    let mut encrypted = vec![];
    {
        let mut writer = encryptor.wrap_output(&mut encrypted)?;
        writer.write_all(&plaintext)?;
        writer.finish()?;
    }
    
    // 将加密数据写入文件
    std::fs::write(output_path, encrypted)?;
    
    Ok(())
}

fn decrypt_file(
    input_path: &Path,
    output_path: &Path,
    key: &age::x25519::Identity,
) -> Result<(), age::AgeError> {
    // 读取加密文件内容
    let encrypted = std::fs::read(input_path)?;
    
    // 创建解密器
    let decryptor = match Decryptor::new(&encrypted[..])? {
        Decryptor::Recipients(d) => d,
        _ => unreachable!(),
    };
    
    // 解密内容
    let mut decrypted = vec![];
    {
        let mut reader = decryptor.decrypt(Secret::new(key.clone()))?;
        reader.read_to_end(&mut decrypted)?;
    }
    
    // 将解密数据写入文件
    std::fs::write(output_path, decrypted)?;
    
    Ok(())
}

许可证

age采用双重许可证:

  • Apache License 2.0
  • MIT license

贡献

除非您明确声明,否则任何贡献都将按上述双重许可证提交。


1 回复

Rust数据加密插件库age的使用:安全高效的加密与解密工具

介绍

age是一个简单、现代且安全的文件加密工具和库,由Filippo Valsorda开发。它专注于提供简单易用的API,同时保持高安全性。age的设计目标是成为GPG的现代替代品,具有以下特点:

  • 基于现代加密标准(X25519, ChaCha20-Poly1305等)
  • 极简的API设计
  • 无主密钥概念,每个密钥对独立工作
  • 支持基于密码的加密
  • 小巧高效,适合嵌入到其他应用中

安装方法

在Cargo.toml中添加依赖:

[dependencies]
age = "0.9"

完整示例代码

use age::{Encryptor, Decryptor, Recipient};
use age::x25519::{Identity, Recipient as X25519Recipient};
use age::secrecy::Secret;
use std::fs::File;
use std::io::{Read, Write};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1: 生成密钥对
    let identity = Identity::generate();
    let recipient = identity.to_public();
    println!("Generated private key: {}", identity.to_string());
    println!("Generated public key: {}", recipient.to_string());

    // 示例2: 使用公钥加密数据
    let encryptor = Encryptor::with_recipients(vec![Box::new(recipient.clone())])
        .expect("failed to create encryptor");

    let mut encrypted = vec![];
    {
        let mut writer = encryptor.wrap_output(&mut encrypted)?;
        writer.write_all(b"Hello, age! This is a secret message.")?;
        writer.finish()?;
    }

    // 示例3: 使用私钥解密数据
    let decryptor = match Decryptor::new(&encrypted[..])? {
        Decryptor::Recipients(d) => d,
        _ => panic!("not recipients encrypted"),
    };

    let mut decrypted = vec![];
    {
        let mut reader = decryptor.decrypt(std::iter::once(&identity as &dyn age::Identity))?;
        reader.read_to_end(&mut decrypted)?;
    }
    println!("Decrypted: {}", String::from_utf8(decrypted)?);

    // 示例4: 使用密码加密
    let password = Secret::new("my-super-secret-password".to_owned());
    let mut passphrase_encrypted = vec![];
    {
        let encryptor = Encryptor::with_user_passphrase(password.clone());
        let mut writer = encryptor.wrap_output(&mut passphrase_encrypted)?;
        writer.write_all(b"Message encrypted with password")?;
        writer.finish()?;
    }

    // 示例5: 使用密码解密
    let decryptor = match Decryptor::new(&passphrase_encrypted[..])? {
        Decryptor::Passphrase(d) => d,
        _ => panic!("not passphrase encrypted"),
    };
    let mut passphrase_decrypted = vec![];
    {
        let mut reader = decryptor.decrypt(&password, None)?;
        reader.read_to_end(&mut passphrase_decrypted)?;
    }
    println!("Passphrase decrypted: {}", String::from_utf8(passphrase_decrypted)?);

    // 示例6: 加密文件
    {
        // 创建测试文件
        let mut test_file = File::create("test_plain.txt")?;
        test_file.write_all(b"This is a test file content")?;

        let input_file = File::open("test_plain.txt")?;
        let output_file = File::create("test_encrypted.age")?;

        let encryptor = Encryptor::with_recipients(vec![Box::new(recipient)])
            .expect("failed to create file encryptor");

        let mut writer = encryptor.wrap_output(output_file)?;
        let mut buffer = [0; 1024];
        loop {
            let bytes_read = input_file.read(&mut buffer)?;
            if bytes_read == 0 {
                break;
            }
            writer.write_all(&buffer[..bytes_read])?;
        }
        writer.finish()?;
    }

    // 示例7: 解密文件
    {
        let input_file = File::open("test_encrypted.age")?;
        let output_file = File::create("test_decrypted.txt")?;

        let decryptor = match Decryptor::new(input_file)? {
            Decryptor::Recipients(d) => d,
            _ => panic!("not recipients encrypted file"),
        };

        let mut reader = decryptor.decrypt(std::iter::once(&identity as &dyn age::Identity))?;
        let mut buffer = [0; 1024];
        loop {
            let bytes_read = reader.read(&mut buffer)?;
            if bytes_read == 0 {
                break;
            }
            output_file.write_all(&buffer[..bytes_read])?;
        }
    }

    Ok(())
}

代码说明

  1. 首先生成了X25519密钥对,包含公钥和私钥
  2. 使用公钥加密了一段文本数据
  3. 使用对应的私钥解密数据并验证
  4. 演示了基于密码的加密和解密过程
  5. 展示了如何加密和解密整个文件

注意事项

  1. 私钥需要妥善保管,一旦丢失将无法解密数据
  2. 使用密码加密时,密码强度直接影响安全性
  3. 生产环境中建议结合age的CLI工具进行密钥管理
  4. 该库不适合需要密钥撤销或轮换的场景

age提供了简单而强大的加密功能,非常适合需要轻量级加密解决方案的Rust应用程序。

回到顶部