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)
}
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)?;
注意事项
- 妥善保管私钥,建议使用密码保护
- 定期更新密钥和撤销证书
- 验证通信对方的密钥真实性
- 注意处理可能的错误和异常情况
性能建议
- 对于大量数据加密,使用流式处理
- 考虑使用异步操作处理大型文件
- 缓存常用密钥以提高性能
这个库提供了完整的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功能。