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算法

Docs MSRV

这个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(())
    }
}

注意事项

  1. 妥善保管加密密钥
  2. 每次加密使用不同的随机数(nonce)
  3. 验证关联数据的完整性
  4. 定期轮换加密密钥

性能建议

  • 对于大量数据,考虑使用流式加密
  • 选择合适的算法(AES-GCM通常性能较好)
  • 重用AEAD实例以避免重复初始化开销

这个库提供了企业级的加密解决方案,适合需要高安全性保障的应用场景。

回到顶部