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(())
}
注意事项
- 密钥安全性:确保使用强密钥,不要使用示例中的全零密钥
- 调整值(Tweak):可以增加安全性,应确保唯一性
- 性能考虑:对于大量数据,考虑分批处理
- 字母表选择:自定义字母表时确保字符唯一且有序
实际应用场景
- 加密数据库中的格式化数据(如身份证号、电话号码)
- 令牌化系统
- 需要保持数据格式的安全传输
- 测试数据生成
通过fpe
库,Rust开发者可以方便地在应用中实现格式保留加密,保护敏感数据的同时保持系统兼容性。