Rust加密库fernet的使用,Fernet提供简单安全的对称加密功能,支持消息认证和时间戳验证

Rust加密库fernet的使用

Fernet提供简单安全的对称加密功能,支持消息认证和时间戳验证

什么是Fernet?

Fernet是一个小型库,帮助您加密带有可选过期时间的数据包。它非常适合用于令牌或在两点之间交换小字符串或数据块。Fernet设计为易于使用,结合了密码学原语,使其难以出错,防止篡改,并让您确信令牌是合法的。

典型使用场景

  • URL或授权头中的时间限制认证令牌
  • 使用静态密钥在两个点之间发送小的加密数据块
  • 简单加密秘密以存储到磁盘,稍后可读取
  • 其他需要简单安全加密的场景

基本使用方法

  1. 首先在Cargo.toml中添加依赖:
[dependencies]
fernet = "0.1"
  1. 完整示例代码:
use fernet::Fernet;
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    // 1. 生成Fernet密钥
    let key = Fernet::generate_key();
    let fernet = Fernet::new(&key).unwrap();
    
    // 2. 准备要加密的消息
    let message = "这是需要加密的秘密数据";
    
    // 3. 加密消息
    let encrypted = fernet.encrypt(message.as_bytes());
    println!("加密结果: {}", encrypted);
    
    // 4. 解密消息
    let decrypted = fernet.decrypt(&encrypted).unwrap();
    let decrypted_str = String::from_utf8(decrypted).unwrap();
    println!("解密结果: {}", decrypted_str);
}

高级功能 - 时间控制加密

如果需要测试令牌过期功能,可以使用特定时间加密/解密:

  1. 修改Cargo.toml启用特殊功能:
[dependencies]
fernet = { version = "0.1", features = ["fernet_danger_timestamps"] }
  1. 使用示例:
#[cfg(feature = "fernet_danger_timestamps")]
{
    let current_time = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    
    // 模拟1小时前的加密
    let past_time = current_time - 3600;
    let encrypted_past = fernet.encrypt_at_time(message.as_bytes(), past_time);
    
    match fernet.decrypt_at_time(&encrypted_past, current_time) {
        Ok(decrypted) => println!("解密成功"),
        Err(e) => println!("解密失败: {}", e),
    }
}

注意事项

  1. Fernet适合加密小数据块,不适合大文件加密
  2. 默认情况下令牌有效期是60秒
  3. 使用时间控制功能需要明确启用fernet_danger_timestamps特性
  4. 密钥需要安全保存,泄露密钥会导致加密数据被破解

1 回复

Rust加密库fernet使用指南

Fernet是一个提供简单安全对称加密功能的Rust库,支持消息认证和时间戳验证。它基于AES-128-CBC加密和HMAC-SHA256认证,确保数据的机密性和完整性。

安装方法

在Cargo.toml中添加依赖:

[dependencies]
fernet = "0.2"

基本使用方法

1. 生成密钥

use fernet::Fernet;

let key = Fernet::generate_key();
println!("Generated key: {}", key);

2. 加密数据

use fernet::Fernet;

let key = Fernet::generate_key();
let fernet = Fernet::new(&key).unwrap();

let message = "This is a secret message";
let encrypted = fernet.encrypt(message.as_bytes());

println!("Encrypted: {}", encrypted);

3. 解密数据

use fernet::Fernet;

let key = "your_fernet_key_here";
let fernet = Fernet::new(key).unwrap();

let encrypted = "encrypted_token_here";
let decrypted = fernet.decrypt(encrypted).unwrap();

println!("Decrypted: {}", String::from_utf8(decrypted).unwrap());

高级功能

带TTL验证的解密

use fernet::Fernet;
use std::time::Duration;

let key = Fernet::generate_key();
let fernet = Fernet::new(&key).unwrap();

let message = "Time-sensitive message";
let encrypted = fernet.encrypt(message.as_bytes());

// 解密时验证消息是否在30秒内创建
match fernet.decrypt_with_ttl(&encrypted, Duration::from_secs(30)) {
    Ok(decrypted) => println!("Valid message: {}", String::from_utf8(decrypted).unwrap()),
    Err(e) => println!("Decryption failed: {}", e),
}

加密结构体

use fernet::Fernet;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct UserData {
    id: u64,
    username: String,
    email: String,
}

let key = Fernet::generate_key();
let fernet = Fernet::new(&key).unwrap();

let user = UserData {
    id: 42,
    username: "example".to_string(),
    email: "user@example.com".to_string(),
};

// 序列化并加密
let serialized = serde_json::to_vec(&user).unwrap();
let encrypted = fernet.encrypt(&serialized);

// 解密并反序列化
let decrypted = fernet.decrypt(&encrypted).unwrap();
let user: UserData = serde_json::from_slice(&decrypted).unwrap();

println!("Decrypted user: {} ({})", user.username, user.email);

安全注意事项

  1. 密钥应该安全存储,不要硬编码在代码中
  2. 对于生产环境,考虑使用密钥管理系统
  3. 定期轮换密钥
  4. 对于非常敏感的数据,考虑使用非对称加密

Fernet提供了一种简单但安全的方式来加密数据,特别适合需要消息认证和时间敏感验证的场景。

完整示例

下面是一个完整的示例,展示了Fernet库的主要功能:

use fernet::Fernet;
use serde::{Serialize, Deserialize};
use std::time::Duration;

#[derive(Serialize, Deserialize, Debug)]
struct SecretMessage {
    sender: String,
    content: String,
    timestamp: i64,
}

fn main() {
    // 1. 生成密钥
    let key = Fernet::generate_key();
    println!("Generated key: {}", key);
    
    // 2. 创建Fernet实例
    let fernet = Fernet::new(&key).unwrap();
    
    // 3. 准备要加密的数据
    let secret = SecretMessage {
        sender: "Alice".to_string(),
        content: "Meet me at 5pm".to_string(),
        timestamp: chrono::Utc::now().timestamp(),
    };
    
    // 4. 序列化并加密数据
    let serialized = serde_json::to_vec(&secret).unwrap();
    let encrypted = fernet.encrypt(&serialized);
    println!("Encrypted message: {}", encrypted);
    
    // 5. 解密数据(无TTL验证)
    let decrypted = fernet.decrypt(&encrypted).unwrap();
    let secret: SecretMessage = serde_json::from_slice(&decrypted).unwrap();
    println!("Decrypted message: {:?}", secret);
    
    // 6. 带TTL验证的解密
    match fernet.decrypt_with_ttl(&encrypted, Duration::from_secs(30)) {
        Ok(decrypted) => {
            let secret: SecretMessage = serde_json::from_slice(&decrypted).unwrap();
            println!("Valid message: {:?}", secret);
        }
        Err(e) => println!("Message expired or invalid: {}", e),
    }
}

这个示例展示了:

  1. 密钥生成
  2. 结构体序列化
  3. 数据加密
  4. 基本解密
  5. 带TTL验证的解密

要运行此示例,需要在Cargo.toml中添加以下依赖:

[dependencies]
fernet = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = "0.4"
回到顶部