Rust加密库tink-aead的使用:高效实现认证加密与解密功能,支持多种AEAD算法
use std::error::Error;
use tink_aead;
use tink_core;
fn main() -> Result<(), Box<dyn Error>> {
// 初始化tink-aead库
tink_aead::init();
// 创建AES256-GCM密钥句柄
let kh = tink_core::keyset::Handle::new(&tink_aead::aes256_gcm_key_template())?;
// 创建AEAD实例
let aead = tink_aead::new(&kh)?;
// 待加密的明文数据
let plaintext = b"this data needs to be encrypted";
// 附加认证数据(不加密但需要认证)
let additional_data = b"this data needs to be authenticated, but not encrypted";
// 加密数据
let ciphertext = aead.encrypt(plaintext, additional_data)?;
println!("'{}' => {}", String::from_utf8_lossy(plaintext), hex::encode(&ciphertext));
// 解密数据
let decrypted_text = aead.decrypt(&ciphertext, additional_data)?;
// 验证解密结果与原始明文一致
assert_eq!(&plaintext[..], decrypted_text);
Ok(())
}
Rust加密库tink-aead的使用:高效实现认证加密与解密功能,支持多种AEAD算法
这个crate提供了带附加数据的认证加密(AEAD)功能,如上游Tink文档中所述。
用法
use std::error::Error;
use tink_aead;
use tink_core;
fn main() -> Result<(), Box<dyn Error>> {
// 初始化tink-aead库
tink_aead::init();
// 创建AES256-GCM密钥句柄
let kh = tink_core::keyset::Handle::new(&tink_aead::aes256_gcm_key_template())?;
// 创建AEAD实例
let aead = tink_aead::new(&kh)?;
// 待加密的明文数据
let plaintext = b"this data needs to be encrypted";
// 附加认证数据(不加密但需要认证)
let additional_data = b"this data needs to be authenticated, but not encrypted";
// 加密数据
let ciphertext = aead.encrypt(plaintext, additional_data)?;
println!("'{}' => {}", String::from_utf8_lossy(plaintext), hex::encode(&ciphertext));
// 解密数据
let decrypted_text = aead.decrypt(&ciphertext, additional_data)?;
// 验证解密结果与原始明文一致
assert_eq!(&plaintext[..], decrypted_text);
Ok(())
}
许可证
Apache License, Version 2.0
已知问题
- 在0.2.4版本之前,AES-CTR-HMAC-AEAD密钥和subtle::EncryptThenAuthenticate实现可能容易受到选择密文攻击。攻击者可以生成绕过HMAC验证的密文,当且仅当以下所有条件都成立时:
- Tink在使用32位整数的系统上使用。这通常在32位机器上是这种情况。
- 攻击者可以指定长(>= 2^29字节 ~ 536MB)的关联数据
免责声明
这不是官方支持的Google产品。
1 回复
Rust加密库tink-aead使用指南
概述
tink-aead是Google Tink加密库的Rust实现,提供认证加密与解密(AEAD)功能。该库支持多种AEAD算法,包括AES-GCM、AES-EAX和ChaCha20Poly1305,能够确保数据的机密性、完整性和真实性。
主要特性
- 支持多种AEAD算法
- 简单的API设计
- 密钥管理和轮换支持
- 抵抗时序攻击
安装方法
在Cargo.toml中添加依赖:
[dependencies]
tink-aead = "0.4"
基本用法
1. 加密数据
use tink_aead::{Aead, new};
fn encrypt_data() -> Result<Vec<u8>, Box<dyn std::error::Error>> {
// 创建AEAD实例(使用AES256-GCM)
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
// 生成密钥
let key = aead.new_key()?;
// 关联数据(可选)
let associated_data = b"additional context";
// 加密明文
let ciphertext = aead.encrypt(&key, b"secret message", associated_data)?;
Ok(ciphertext)
}
2. 解密数据
use tink_aead::{Aead, new};
fn decrypt_data(ciphertext: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
let key = aead.new_key()?;
let associated_data = b"additional context";
// 解密密文
let plaintext = aead.decrypt(&key, ciphertext, associated_data)?;
Ok(plaintext)
}
3. 使用不同算法
use tink_aead::{Aead, new};
// 使用ChaCha20Poly1305算法
fn use_chacha20() -> Result<(), Box<dyn std::error::Error>> {
let aead = new(&tink_aead::ChaCha20Poly1305KeyManager::new())?;
let key = aead.new_key()?;
let ciphertext = aead.encrypt(&key, b"message", b"")?;
let plaintext = aead.decrypt(&key, &ciphertext, b"")?;
assert_eq!(plaintext, b"message");
Ok(())
}
高级用法
密钥序列化
use tink_aead::{Aead, new};
fn key_management() -> Result<(), Box<dyn std::error::Error>> {
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
let key = aead.new_key()?;
// 序列化密钥
let serialized_key = key.to_bytes();
// 反序列化密钥
let deserialized_key = aead.key_from_bytes(&serialized_key)?;
Ok(())
}
错误处理
use tink_aead::{Aead, new};
fn handle_errors() -> Result<(), Box<dyn std::error::Error>> {
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
let key = aead.new_key()?;
match aead.decrypt(&key, b"invalid ciphertext", b"") {
Ok(plaintext) => println!("解密成功: {:?}", plaintext),
Err(e) => eprintln!("解密失败: {}", e),
}
Ok(())
}
完整示例demo
use tink_aead::{Aead, new};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
// 示例1: 使用AES256-GCM算法加密和解密
println!("=== AES256-GCM 示例 ===");
// 创建AEAD实例
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
// 生成密钥
let key = aead.new_key()?;
// 关联数据(用于验证完整性)
let associated_data = b"transaction_123";
// 原始消息
let plaintext = b"这是一条需要加密的敏感信息";
// 加密数据
let ciphertext = aead.encrypt(&key, plaintext, associated_data)?;
println!("加密成功,密文长度: {} 字节", ciphertext.len());
// 解密数据
let decrypted = aead.decrypt(&key, &ciphertext, associated_data)?;
println!("解密成功: {}", String::from_utf8_lossy(&decrypted));
// 示例2: 使用ChaCha20Poly1305算法
println!("\n=== ChaCha20Poly1305 示例 ===");
let chacha_aead = new(&tink_aead::ChaCha20Poly1305KeyManager::new())?;
let chacha_key = chacha_aead.new_key()?;
let chacha_ciphertext = chacha_aead.encrypt(&chacha_key, b"测试消息", b"")?;
let chacha_plaintext = chacha_aead.decrypt(&chacha_key, &chacha_ciphertext, b"")?;
assert_eq!(chacha_plaintext, b"测试消息");
println!("ChaCha20Poly1305 测试通过");
// 示例3: 密钥序列化和反序列化
println!("\n=== 密钥管理示例 ===");
// 序列化密钥
let serialized_key = key.to_bytes();
println!("密钥序列化成功,长度: {} 字节", serialized_key.len());
// 反序列化密钥
let deserialized_key = aead.key_from_bytes(&serialized_key)?;
println!("密钥反序列化成功");
// 使用反序列化的密钥进行加密解密测试
let test_ciphertext = aead.encrypt(&deserialized_key, b"test", associated_data)?;
let test_plaintext = aead.decrypt(&deserialized_key, &test_ciphertext, associated_data)?;
assert_eq!(test_plaintext, b"test");
println!("密钥序列化/反序列化测试通过");
// 示例4: 错误处理
println!("\n=== 错误处理示例 ===");
match aead.decrypt(&key, b"无效的密文数据", associated_data) {
Ok(data) => println!("意外解密成功: {:?}", data),
Err(e) => println!("预期中的解密失败: {}", e),
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aes_gcm_encryption() -> Result<(), Box<dyn Error>> {
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
let key = aead.new_key()?;
let ciphertext = aead.encrypt(&key, b"test message", b"context")?;
let plaintext = aead.decrypt(&key, &ciphertext, b"context")?;
assert_eq!(plaintext, b"test message");
Ok(())
}
#[test]
fn test_wrong_associated_data() -> Result<(), Box<dyn Error>> {
let aead = new(&tink_aead::Aes256GcmKeyManager::new())?;
let key = aead.new_key()?;
let ciphertext = aead.encrypt(&key, b"secret", b"correct_context")?;
// 使用错误的关联数据应该解密失败
assert!(aead.decrypt(&key, &ciphertext, b"wrong_context").is_err());
Ok(())
}
}
注意事项
- 妥善保管加密密钥
- 每次加密使用不同的随机数(nonce)
- 验证关联数据的完整性
- 定期轮换加密密钥
性能建议
- 对于大量数据,考虑使用流式加密
- 选择合适的算法(AES-GCM通常性能较好)
- 重用AEAD实例以避免重复初始化开销
这个库提供了企业级的加密解决方案,适合需要高安全性保障的应用场景。