Rust格式保留加密库fpe的使用,fpe提供高性能格式保留加密算法实现

Rust格式保留加密库fpe的使用

fpe是一个纯Rust实现的格式保留加密算法库,提供了高性能的格式保留加密功能实现。

当前实现的算法

  • FF1算法(基于NIST Special Publication 800-38G标准)

系统要求

需要Rust 1.56或更高版本。

示例代码

use fpe::ff1::{FF1, Cipher};

fn main() {
    // 定义密钥和调整值(tweak)
    let key = b"my-secret-key-123";
    let tweak = b"my-tweak-value";
    
    // 定义要加密的字母表(数字0-9)
    let radix = 10u32;
    
    // 创建FF1加密器实例
    let cipher = FF1::new(key, tweak, radix).unwrap();
    
    // 原始数据
    let plaintext = "123456789";
    
    // 加密
    let ciphertext = cipher.encrypt(plaintext).unwrap();
    println!("加密结果: {}", ciphertext);
    
    // 解密
    let decrypted = cipher.decrypt(&ciphertext).unwrap();
    println!("解密结果: {}", decrypted);
    
    // 验证加解密一致性
    assert_eq!(plaintext, decrypted);
}

完整示例Demo

use fpe::ff1::{FF1, Cipher};

fn main() {
    // 示例1: 加密数字
    encrypt_numbers();
    
    // 示例2: 加密字母
    encrypt_letters();
}

fn encrypt_numbers() {
    println!("=== 数字加密示例 ===");
    
    let key = b"2B7E151628AED2A6ABF7158809CF4F3C";
    let tweak = b"";
    let radix = 10;
    
    let cipher = FF1::new(key, tweak, radix).unwrap();
    
    let plaintext = "0123456789";
    println!("原始数据: {}", plaintext);
    
    let ciphertext = cipher.encrypt(plaintext).unwrap();
    println!("加密结果: {}", ciphertext);
    
    let decrypted = cipher.decrypt(&ciphertext).unwrap();
    println!("解密结果: {}", decrypted);
    
    assert_eq!(plaintext, decrypted);
    println!("验证通过");
    println!();
}

fn encrypt_letters() {
    println!("=== 字母加密示例 ===");
    
    // 定义字母表(a-z)
    let alphabet: Vec<char> = ('a'..='z').collect();
    let radix = alphabet.len() as u32;
    
    let key = b"2B7E151628AED2A6ABF7158809CF4F3C";
    let tweak = b"example-tweak";
    
    let cipher = FF1::new(key, tweak, radix).unwrap();
    
    let plaintext = "helloworld";
    println!("原始数据: {}", plaintext);
    
    // 将字母转换为数字索引
    let plaintext_indices: Vec<u32> = plaintext.chars()
        .map(|c| alphabet.iter().position(|&a| a == c).unwrap() as u32)
        .collect();
    
    // 加密
    let ciphertext_indices = cipher.encrypt_indices(&plaintext_indices).unwrap();
    
    // 将数字索引转换回字母
    let ciphertext: String = ciphertext_indices.iter()
        .map(|&i| alphabet[i as usize])
        .collect();
    println!("加密结果: {}", ciphertext);
    
    // 解密
    let decrypted_indices = cipher.decrypt_indices(&ciphertext_indices).unwrap();
    let decrypted: String = decrypted_indices.iter()
        .map(|&i| alphabet[i as usize])
        .collect();
    println!("解密结果: {}", decrypted);
    
    assert_eq!(plaintext, decrypted);
    println!("验证通过");
}

许可证

可选择以下任一许可证:

  • Apache License, Version 2.0
  • MIT license

贡献

除非您明确声明,否则您提交的任何贡献都将按上述双重许可,不附加任何额外条款或条件。


1 回复

Rust格式保留加密库fpe使用指南

什么是格式保留加密(FPE)

格式保留加密(Format-Preserving Encryption)是一种特殊的加密方式,它在加密数据的同时保持数据的格式和长度不变。例如,加密信用卡号后仍然得到一个看起来像信用卡号的数字串。

fpe库简介

fpe是Rust实现的一个高性能格式保留加密库,支持多种加密算法和格式保留功能。

安装

在Cargo.toml中添加依赖:

[dependencies]
fpe = "0.4"

基本使用方法

1. 加密数字

use fpe::ff1::{FF1, FF1Error};
use fpe::num::Num;

fn main() -> Result<(), FF1Error> {
    // 使用16字节全零密钥(实际应用中应使用强密钥)
    let key = [0u8; 16];
    // 调整值增加安全性
    let tweak = b"unique tweak";
    
    // 创建FF1实例: 基数10, 最小长度2, 最大长度10
    let ff = FF1::new(&key, 10, 2, 10, tweak)?;
    
    // 加密数字
    let plaintext = Num::from(12345u32);
    let ciphertext = ff.encrypt(&plaintext)?;
    println!("密文: {}", ciphertext);
    
    // 解密
    let decrypted = ff.decrypt(&ciphertext)?;
    println!("解密结果: {}", decrypted);
    
    Ok(())
}

2. 加密字母字符串

use fpe::ff1::{FF1, FF1Error};

fn main() -> Result<(), FF1Error> {
    // 密钥和调整值
    let key = [0u8; 16];
    let tweak = b"";
    
    // 26个字母(基数26), 固定长度5
    let ff = FF1::new(&key, 26, 5, 5, tweak)?;
    
    let plaintext = "HELLO";
    // 加密字符
    let ciphertext = ff.encrypt_chars(plaintext.chars())?;
    let ciphertext_str: String = ciphertext.collect();
    println!("密文: {}", ciphertext_str);
    
    // 解密
    let decrypted = ff.decrypt_chars(ciphertext_str.chars())?;
    let decrypted_str: String = decrypted.collect();
    println!("解密结果: {}", decrypted_str);
    
    Ok(())
}

3. 自定义字母表

use fpe::ff1::{FF1, FF1Error};

fn main() -> Result<(), FF1Error> {
    let key = [0u8; 16];
    let tweak = b"my tweak";
    
    // 自定义字母表: A-Z + 0-9
    let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".chars().collect::<Vec<_>>();
    let radix = alphabet.len() as u32;
    
    // 使用自定义字母表
    let ff = FF1::new(&key, radix, 6, 6, tweak)?;
    
    let plaintext = "ABC123";
    // 使用自定义字母表加密
    let ciphertext = ff.encrypt_custom(plaintext.chars(), &alphabet)?;
    let ciphertext_str: String = ciphertext.collect();
    println!("密文: {}", ciphertext_str);
    
    Ok(())
}

高级特性

1. 使用不同的加密算法

use fpe::ff1::{FF1, FF1Error};
use aes::Aes128;

fn main() -> Result<(), FF1Error> {
    let key = [0u8; 16];
    let tweak = b"";
    
    // 使用AES128作为底层加密算法
    let ff = FF1::<Aes128>::new(&key, 10, 5, 5, tweak)?;
    
    // 加密解密操作与之前示例相同
    let num = fpe::num::Num::from(12345u32);
    let ciphertext = ff.encrypt(&num)?;
    println!("加密结果: {}", ciphertext);
    
    Ok(())
}

2. 处理不同长度的数据

use fpe::ff1::{FF1, FF1Error};

fn main() -> Result<(), FF1Error> {
    let key = [0u8; 16];
    let tweak = b"";
    
    // 支持4-10位数字
    let ff = FF1::new(&key, 10, 4, 10, tweak)?;
    
    let short_num = "1234";
    let long_num = "1234567890";
    
    // 加密不同长度数据
    let cipher_short = ff.encrypt_chars(short_num.chars())?;
    let cipher_long = ff.encrypt_chars(long_num.chars())?;
    
    println!("短数字加密: {:?}", cipher_short.collect::<String>());
    println!("长数字加密: {:?}", cipher_long.collect::<String>());
    
    Ok(())
}

完整示例DEMO

下面是一个综合示例,展示如何使用fpe库加密信用卡号:

use fpe::ff1::{FF1, FF1Error};
use rand::Rng;

fn main() -> Result<(), FF1Error> {
    // 生成随机密钥(实际应用中应从安全来源获取)
    let mut key = [0u8; 16];
    rand::thread_rng().fill(&mut key);
    
    // 使用信用卡号作为调整值
    let tweak = b"credit_card_encryption";
    
    // 信用卡号是16位数字,基数10
    let ff = FF1::new(&key, 10, 16, 16, tweak)?;
    
    let credit_card = "4532015112830366";
    println!("原始卡号: {}", credit_card);
    
    // 加密
    let encrypted = ff.encrypt_chars(credit_card.chars())?;
    let encrypted_str: String = encrypted.collect();
    println!("加密卡号: {}", encrypted_str);
    
    // 解密
    let decrypted = ff.decrypt_chars(encrypted_str.chars())?;
    let decrypted_str: String = decrypted.collect();
    println!("解密卡号: {}", decrypted_str);
    
    Ok(())
}

注意事项

  1. 密钥安全性:确保使用强密钥,不要使用示例中的全零密钥
  2. 调整值(Tweak):可以增加安全性,应确保唯一性
  3. 性能考虑:对于大量数据,考虑分批处理
  4. 字母表选择:自定义字母表时确保字符唯一且有序

实际应用场景

  1. 加密数据库中的格式化数据(如身份证号、电话号码)
  2. 令牌化系统
  3. 需要保持数据格式的安全传输
  4. 测试数据生成

通过fpe库,Rust开发者可以方便地在应用中实现格式保留加密,保护敏感数据的同时保持系统兼容性。

回到顶部