Rust OpenPGP加密库sequoia-openpgp的使用,支持端到端加密、密钥管理和安全通信功能

Rust OpenPGP加密库sequoia-openpgp的使用,支持端到端加密、密钥管理和安全通信功能

此crate旨在提供由RFC 9580定义的OpenPGP完整实现,以及由RFC 4880定义的不推荐使用的OpenPGP。OpenPGP是IETF的标准。它源自PGP软件,由Phil Zimmermann于1991年创建。

此crate还包括对无缓冲消息处理的支持。

OpenPGP社区认为已弃用的一些功能(例如,版本3兼容性)已被排除在外。我们还更新了一些OpenPGP默认值以避免陷阱(例如,我们选择了现代算法默认值)。如果缺少某些功能,请提交错误报告。

此crate的非目标是支持任何类型的高级、附加功能。例如,RFC 9580没有定义信任模型,如信任网络、直接信任或TOFU。此crate也不定义。RFC 9580确实提供了一些创建信任模型的机制(特别是用户ID认证),而此crate确实暴露了这些机制。

我们还努力避免规定应如何使用OpenPGP。这并不意味着我们没有关于在许多常见场景中应如何使用OpenPGP的意见(例如,消息验证)。但是,在此crate中,我们避免表达这些意见;我们将在未来暴露一个具有意见的高级接口。为了确定最合适的高级接口,我们查看现有用户。如果您正在使用Sequoia,请联系我们,以便我们可以从您的用例中学习,讨论您的意见,并在未来基于这些经验开发高级接口。

尽管——或者也许因为——其无意见的性质,我们发现基于Sequoia开发有意见的OpenPGP软件很容易。

实验性功能

此crate可能实现标准化工作仍在进行中的扩展。这些实验性功能在文档中标记为如此。我们邀请您尝试它们,但请预期语义甚至可能线路格式会演变。

功能标志

此crate使用功能来启用或禁用可选功能。您可以在Cargo.toml文件中调整功能,如下所示:

sequoia-openpgp = { version = "*", default-features = false, features = ["compression", ...] }

默认情况下,Sequoia使用Nettle作为加密后端构建,并启用所有压缩算法。使用默认功能仅适用于叶crate,请参阅此部分。

请注意,如果您使用default-features = false,您需要显式启用加密后端,并启用压缩功能。

加密后端

Sequoia支持在编译时选择的多个加密库。目前,这些库可用:

  • Nettle加密库。这是默认后端,由默认功能集选择。如果您使用default-features = false,您需要显式包含crypto-nettle功能以启用它。
  • OpenSSL后端。要选择此后端,使用default-features = false,并显式包含crypto-openssl功能以启用它。
  • Botan后端。要选择此后端,使用default-features = false,并显式包含crypto-botan功能以启用它。crypto-botan默认为Botan v3,于2023年4月发布。使用crypto-botan2以使用v2。
  • Windows加密API:下一代(CNG)。要选择此后端,使用default-features = false,并显式包含crypto-cng功能以启用它。目前,CNG后端至少需要Windows 10。
  • RustCrypto crate。要选择此后端,使用default-features = false,并显式包含crypto-rust功能以启用它。截至撰写时,RustCrypto crate不推荐用于一般用途,因为它们无法提供与更成熟的加密库相同的安全保证。

实验性和可变时间加密后端

一些加密后端尚未被认为足够成熟以供一般使用。使用此类后端需要使用功能标志allow-experimental-crypto显式选择加入。

一些加密后端无法保证加密操作需要恒定的时间量。这可能会在某些设置中泄露密钥。使用此类后端需要使用功能标志allow-variable-time-crypto显式选择加入。

如何在crate中选择加密后端

在Rust中,功能是统一的,因此功能应该是可加的,即启用任何功能组合应该是安全的。但是,这不适用于加密后端,因为必须恰好选择一个加密后端才能编译Sequoia。

为了适应这一点,我们提出了以下规则:在使用Sequoia的任何项目中,恰好一个crate可以选择加密后端,并且该crate是叶crate(即二进制或cdylib crate)。任何非叶、库crate必须通过禁用默认功能来避免选择加密后端,包括默认后端。

回顾一下,根据您正在开发的crate类型遵循这些规则:

叶crate

叶crate应选择默认后端(您可以推迟Sequoia选择默认后端),但应允许您的下游用户切换后端:

# Cargo.toml
[dependencies]
sequoia-openpgp = { version = "*", default-features = false }
# 如果您需要压缩功能,在此启用:
# sequoia-openpgp = { version = "*", default-features = false, features = ["compression"] }

[features]
# 默认启用加密后端(这里我们推迟Sequoia选择默认):
default = ["sequoia-openpgp/default"]

# ..但也允许其他人选择不同的后端
crypto-nettle = ["sequoia-openpgp/crypto-nettle"]
crypto-openssl = ["sequoia-openpgp/crypto-openssl"]
crypto-botan = ["sequoia-openpgp/crypto-botan"]
crypto-botan2 = ["sequoia-openpgp/crypto-botan2"]
crypto-rust = ["sequoia-openpgp/crypto-rust"]
crypto-cng = ["sequoia-openpgp/crypto-cng"]

# 实验性和可变时间加密后端选择加入
allow-experimental-crypto = ["sequoia-openpgp/allow-experimental-crypto"]
allow-variable-time-crypto = ["sequoia-openpgp/allow-variable-time-crypto"]

中间crate

非叶crate不得选择加密后端,并且必须禁用默认功能。此外,为了使cargo test工作而无需选择加密后端,并使docs.rs能够构建您的文档,请为这些情况选择性地启用加密后端:

# Cargo.toml
[dependencies]
sequoia-openpgp = { version = "*", default-features = false }
# 如果您需要压缩功能,在此启用:
# sequoia-openpgp = { version = "*", default-features = false, features = ["compression"] }

# 为测试启用加密后端:
[target.'cfg(not(windows))'.dev-dependencies]
sequoia-openpgp = { version = "1", default-features = false, features = ["crypto-nettle", "__implicit-crypto-backend-for-tests"]  }

# 为测试启用加密后端:
[target.'cfg(windows)'.dev-dependencies]
sequoia-openpgp = { version = "1", default-features = false, features = ["crypto-cng", "__implicit-crypto-backend-for-tests"] }

# 为docs.rs生成启用加密后端:
[package.metadata.docs.rs]
features = ["sequoia-openpgp/default"]

压缩算法

使用compression标志启用对所有压缩算法的支持,compression-deflate启用DEFLATE和zlib压缩支持,compression-bzip2启用bzip2支持。

编译到WASM

使用正确的功能标志,Sequoia可以编译到WASM。为此,启用RustCrypto后端,并确保不启用bzip2压缩支持:

sequoia-openpgp = { version = "*", default-features = false, features = ["crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto"] }

或者,使用compression-deflate支持:

sequoia-openpgp = { version = "*", default-features = false, features = ["crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto", "compression-deflate"] }

最低支持的Rust版本(MSRV)

sequoia-openpgp需要Rust 1.67。

完整示例代码:

use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::parse::Parse;
use openpgp::serialize::Serialize;
use openpgp::policy::StandardPolicy;

fn main() -> openpgp::Result<()> {
    let p = &StandardPolicy::new();

    // 生成新密钥对
    let (cert, _revocation) = CertBuilder::new()
        .add_userid("Alice <alice@example.com>")
        .generate()?;

    // 序列化证书
    let mut cert_bytes = Vec::new();
    cert.serialize(&mut cert_bytes)?;

    // 解析证书
    let cert = Cert::from_bytes(&cert_bytes)?;

    // 验证证书
    for uid in cert.userids() {
        if let Ok(valid) = uid.with_policy(p, None) {
            println!("User ID: {}", String::from_utf8_lossy(valid.value()));
        }
    }

    Ok(())
}
use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::parse::Parse;
use openpgp::serialize::Serialize;
use openpgp::policy::StandardPolicy;
use openpgp::crypto::SessionKey;
use openpgp::types::SymmetricAlgorithm;

fn encrypt_decrypt_demo() -> openpgp::Result<()> {
    let p = &StandardPolicy::new();

    // 生成发送者和接收者密钥
    let (sender_cert, _) = CertBuilder::new()
        .add_userid("Sender <sender@example.com>")
        .generate()?;
    
    let (recipient_cert, _) = CertBuilder::new()
        .add_userid("Recipient <recipient@example.com>")
        .generate()?;

    // 要加密的消息
    let message = b"Hello, this is a secret message!";

    // 创建加密器
    let mut encryptor = recipient_cert
        .keys()
        .with_policy(p, None)
        .supported()
        .alive()
        .revoked(false)
        .for_transport_encryption()
        .into_iter()
        .next()
        .unwrap()
        .key()
        .encrypt_to_vec();

    // 加密消息
    encryptor.write_all(message)?;
    let encrypted_message = encryptor.finish()?;

    // 解密消息
    let decrypted = recipient_cert
        .decrypt(p, None, &encrypted_message)?
        .next()
        .unwrap()?;

    println!("Decrypted message: {}", String::from_utf8_lossy(&decrypted));

    Ok(())
}

完整示例demo:

use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::parse::Parse;
use openpgp::serialize::Serialize;
use openpgp::policy::StandardPolicy;
use openpgp::crypto::SessionKey;
use openpgp::types::SymmetricAlgorithm;
use std::io::Write;

fn main() -> openpgp::Result<()> {
    // 创建标准策略
    let p = &StandardPolicy::new();

    // 示例1: 密钥生成和管理
    println!("=== 密钥生成示例 ===");
    key_generation_demo(p)?;

    // 示例2: 加密和解密
    println!("\n=== 加密解密示例 ===");
    encryption_demo(p)?;

    Ok(())
}

fn key_generation_demo(p: &StandardPolicy) -> openpgp::Result<()> {
    // 生成新的OpenPGP证书(密钥对)
    let (cert, _revocation) = CertBuilder::new()
        .add_userid("Alice <alice@example.com>")
        .add_userid("Alice Smith <alice.smith@company.com>")
        .generate()?;

    println!("成功生成密钥对");

    // 序列化证书到字节向量
    let mut cert_bytes = Vec::new();
    cert.serialize(&mut cert_bytes)?;
    println!("证书序列化完成,大小: {} 字节", cert_bytes.len());

    // 从字节解析证书
    let parsed_cert = Cert::from_bytes(&cert_bytes)?;
    println!("证书解析成功");

    // 验证证书中的用户ID
    println!("证书中的用户ID:");
    for uid in parsed_cert.userids() {
        if let Ok(valid) = uid.with_policy(p, None) {
            println!("  - {}", String::from_utf8_lossy(valid.value()));
        }
    }

    Ok(())
}

fn encryption_demo(p: &StandardPolicy) -> openpgp::Result<()> {
    // 生成发送者和接收者密钥
    let (sender_cert, _) = CertBuilder::new()
        .add_userid("Sender <sender@example.com>")
        .generate()?;
    
    let (recipient_cert, _) = CertBuilder::new()
        .add_userid("Recipient <recipient@example.com>")
        .generate()?;

    // 要加密的机密消息
    let secret_message = b"This is a highly confidential message that needs to be encrypted!";

    println!("原始消息: {}", String::from_utf8_lossy(secret_message));

    // 加密消息
    let encrypted_data = encrypt_message(p, &recipient_cert, secret_message)?;
    println!("消息加密完成,加密后大小: {} 字节", encrypted_data.len());

    // 解密消息
    let decrypted_data = decrypt_message(p, &recipient_cert, &encrypted_data)?;
    println!("解密后的消息: {}", String::from_utf8_lossy(&decrypted_data));

    Ok(())
}

fn encrypt_message(p: &StandardPolicy, recipient_cert: &openpgp::Cert, message: &[u8]) -> openpgp::Result<Vec<u8>> {
    // 获取适合传输加密的密钥
    let key = recipient_cert
        .keys()
        .with_policy(p, None)
        .supported()
        .alive()
        .revoked(false)
        .for_transport_encryption()
        .next()
        .ok_or(openpgp::Error::InvalidArgument("没有找到合适的加密密钥".into()))?
        .key();

    // 创建加密器
    let mut encryptor = key.encrypt_to_vec();
    
    // 写入要加密的数据
    encryptor.write_all(message)?;
    
    // 完成加密并返回结果
    encryptor.finish()
}

fn decrypt_message(p: &StandardPolicy, recipient_cert: &openpgp::Cert, encrypted_data: &[u8]) -> openpgp::Result<Vec<u8>> {
    // 解密消息
    let decrypted = recipient_cert
        .decrypt(p, None, encrypted_data)?
        .next()
        .ok_or(openpgp::Error::InvalidArgument("解密失败".into()))??;

    Ok(decrypted)
}

1 回复

Rust OpenPGP加密库:sequoia-openpgp使用指南

概述

sequoia-openpgp是一个功能完整的Rust OpenPGP实现库,提供端到端加密、密钥管理和安全通信功能。该库遵循RFC 4880标准,支持生成密钥对、加密/解密数据、签名/验证消息等核心操作。

主要功能

  • 端到端加密通信
  • PGP密钥生成与管理
  • 数据签名与验证
  • 证书处理与验证
  • 与现有OpenPGP工具兼容

基本使用方法

添加依赖

在Cargo.toml中添加:

[dependencies]
sequoia-openpgp = "1.0"

生成密钥对示例

use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::types::{KeyFlags, KeyAlgorithm};

async fn generate_key() -> openpgp::Result<()> {
    let (cert, _revocation) = CertBuilder::new()
        .add_userid("Alice <alice@example.com>")
        .add_signing_subkey()
        .add_transport_encryption_subkey()
        .generate()?;
    
    // 保存密钥
    let mut key_file = std::fs::File::create("alice.key")?;
    cert.armored().to_writer(&mut key_file)?;
    
    Ok(())
}

加密数据示例

use sequoia_openpgp as openpgp;
use openpgp::serialize::stream::{Message, LiteralWriter};
use openpgp::parse::Parse;

async fn encrypt_message() -> openpgp::Result<()> {
    // 加载接收者公钥
    let cert = openpgp::Cert::from_file("bob.pub")?;
    
    // 创建加密消息
    let message = Message::new(&mut std::io::stdout());
    let message = LiteralWriter::new(message).build()?;
    let message = openpgp::encrypt::Encryptor::for_recipients(message, cert.keys())
        .build()?;
    
    // 写入要加密的数据
    message.write_all(b"Secret message")?;
    message.finalize()?;
    
    Ok(())
}

解密数据示例

use sequoia_openpgp as openpgp;
use openpgp::parse::Parse;

async fn decrypt_message() -> openpgp::Result<()> {
    // 加载私钥
    let cert = openpgp::Cert::from_file("alice.key")?;
    let key = cert.keys().secret().next().unwrap().key().clone();
    
    // 解析并解密消息
    let message = openpgp::parse::Parse::from_file("encrypted.pgp")?;
    let decrypted = message.decrypt(&key, &[])?;
    
    println!("Decrypted: {:?}", String::from_utf8_lossy(&decrypted));
    
    Ok(())
}

高级功能

密钥管理

// 列出密钥中的所有用户ID
for userid in cert.userids() {
    println!("User ID: {}", userid);
}

// 检查密钥能力
for key in cert.keys() {
    println!("Key can encrypt: {}", key.for_encryption());
    println!("Key can sign: {}", key.for_signing());
}

消息签名与验证

// 创建签名
let signer = cert.keys().secret().next().unwrap().key().clone();
let signature = openpgp::sign::Signer::new(signer).sign_detached(b"Message")?;

// 验证签名
let verifier = cert.keys().next().unwrap().key();
verifier.verify_detached(b"Message", &signature)?;

注意事项

  1. 妥善保管私钥,建议使用密码保护
  2. 定期更新密钥和撤销证书
  3. 验证通信对方的密钥真实性
  4. 注意处理可能的错误和异常情况

性能建议

  • 对于大量数据加密,使用流式处理
  • 考虑使用异步操作处理大型文件
  • 缓存常用密钥以提高性能

这个库提供了完整的OpenPGP功能实现,可以用于构建安全的通信应用程序。

完整示例demo

use sequoia_openpgp as openpgp;
use openpgp::cert::prelude::*;
use openpgp::serialize::stream::{Message, LiteralWriter};
use openpgp::parse::Parse;
use std::io::Write;

// 生成密钥对函数
async fn generate_key_pair() -> openpgp::Result<()> {
    // 创建新的证书构建器
    let (cert, _revocation) = CertBuilder::new()
        .add_userid("Alice <alice@example.com>")  // 添加用户ID
        .add_signing_subkey()                     // 添加签名子密钥
        .add_transport_encryption_subkey()        // 添加加密子密钥
        .generate()?;                             // 生成密钥对
    
    // 保存私钥到文件
    let mut private_key_file = std::fs::File::create("alice_private.key")?;
    cert.armored().to_writer(&mut private_key_file)?;
    
    // 保存公钥到文件
    let mut public_key_file = std::fs::File::create("alice_public.pub")?;
    cert.armored().to_writer(&mut public_key_file)?;
    
    println!("密钥对生成成功!");
    Ok(())
}

// 加密消息函数
async fn encrypt_message(recipient_public_key_path: &str, message: &[u8]) -> openpgp::Result<Vec<u8>> {
    // 加载接收者公钥
    let cert = openpgp::Cert::from_file(recipient_public_key_path)?;
    
    // 创建内存缓冲区来存储加密数据
    let mut encrypted_data = Vec::new();
    
    // 创建加密消息
    let message = Message::new(&mut encrypted_data);
    let message = LiteralWriter::new(message).build()?;
    let mut message = openpgp::encrypt::Encryptor::for_recipients(message, cert.keys())
        .build()?;
    
    // 写入要加密的数据
    message.write_all(message)?;
    message.finalize()?;
    
    Ok(encrypted_data)
}

// 解密消息函数
async fn decrypt_message(private_key_path: &str, encrypted_data: &[u8]) -> openpgp::Result<Vec<u8>> {
    // 加载私钥
    let cert = openpgp::Cert::from_file(private_key_path)?;
    let key = cert.keys().secret().next().unwrap().key().clone();
    
    // 解析加密消息
    let message = openpgp::parse::Parse::from_bytes(encrypted_data)?;
    
    // 解密消息
    let decrypted = message.decrypt(&key, &[])?;
    
    Ok(decrypted)
}

// 签名消息函数
async fn sign_message(private_key_path: &str, message: &[u8]) -> openpgp::Result<Vec<u8>> {
    // 加载私钥
    let cert = openpgp::Cert::from_file(private_key_path)?;
    let signer = cert.keys().secret().next().unwrap().key().clone();
    
    // 创建签名
    let signature = openpgp::sign::Signer::new(signer).sign_detached(message)?;
    
    Ok(signature.to_vec())
}

// 验证签名函数
async fn verify_signature(public_key_path: &str, message: &[u8], signature: &[u8]) -> openpgp::Result<()> {
    // 加载公钥
    let cert = openpgp::Cert::from_file(public_key_path)?;
    let verifier = cert.keys().next().unwrap().key();
    
    // 解析签名
    let signature = openpgp::parse::Parse::from_bytes(signature)?.into_signature()?;
    
    // 验证签名
    verifier.verify_detached(message, &signature)?;
    
    println!("签名验证成功!");
    Ok(())
}

#[tokio::main]
async fn main() -> openpgp::Result<()> {
    // 1. 生成密钥对
    generate_key_pair().await?;
    
    // 2. 准备要加密的消息
    let original_message = b"这是一个秘密消息!";
    
    // 3. 加密消息
    let encrypted_data = encrypt_message("alice_public.pub", original_message).await?;
    println!("消息加密成功!");
    
    // 4. 解密消息
    let decrypted_data = decrypt_message("alice_private.key", &encrypted_data).await?;
    println!("解密后的消息: {}", String::from_utf8_lossy(&decrypted_data));
    
    // 5. 签名消息
    let signature = sign_message("alice_private.key", original_message).await?;
    println!("消息签名成功!");
    
    // 6. 验证签名
    verify_signature("alice_public.pub", original_message, &signature).await?;
    
    Ok(())
}

这个完整的示例演示了如何使用sequoia-openpgp库进行密钥生成、加密、解密、签名和验证操作。示例包含了完整的错误处理和异步操作,可以直接运行测试OpenPGP功能。

回到顶部