Rust流密码库stream-cipher的使用:高效实现对称加密算法的加密与解密功能
🚨 已弃用! 🚨
block-cipher
和 stream-cipher
库已经合并到新的 cipher
库中。
block-cipher
或 stream-cipher
将不再发布新版本。
请升级到 cipher
库:
以下是使用 stream-cipher
库实现对称加密的完整示例代码:
use stream_cipher::{
generic_array::GenericArray,
NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek
};
// 使用 ChaCha20 算法示例
type ChaCha20 = chacha20::ChaCha20;
fn main() {
// 密钥和随机数(nonce)
let key = GenericArray::from_slice(b"very long secret key");
let nonce = GenericArray::from_slice(b"unique nonce");
// 创建加密器实例
let mut cipher = ChaCha20::new(key, nonce);
// 要加密的数据
let mut data = *b"hello world!";
// 加密数据
cipher.apply_keystream(&mut data);
println!("密文: {:?}", &data);
// 重置状态到初始位置进行解密
cipher.seek(0);
cipher.apply_keystream(&mut data);
println!("明文: {:?}", &data);
}
代码说明:
- 使用
GenericArray
创建密钥和随机数 - 初始化
ChaCha20
流密码实例 apply_keystream
方法同时用于加密和解密seek(0)
将流密码重置到初始状态进行解密
注意:此代码仅为示例,实际使用时请参考最新的 cipher
库文档,并确保使用安全的密钥管理实践。
以下是使用新版 cipher
库的完整示例代码:
use cipher::{
generic_array::GenericArray,
NewCipher, StreamCipher, StreamCipherSeek
};
// 使用 ChaCha20 算法示例
type ChaCha20 = chacha20::ChaCha20;
fn main() {
// 密钥和随机数(nonce)
let key = GenericArray::from_slice(b"very long secret key");
let nonce = GenericArray::from_slice(b"unique nonce");
// 创建加密器实例
let mut cipher = ChaCha20::new(key, nonce);
// 要加密的数据
let mut data = *b"hello world!";
// 加密数据
cipher.apply_keystream(&mut data);
println!("密文: {:?}", &data);
// 重置状态到初始位置进行解密
cipher.seek(0);
cipher.apply_keystream(&mut data);
println!("明文: {:?}", &data);
}
新版代码主要变化:
- 使用
cipher
crate 替代了原来的stream_cipher
- trait 名称从
NewStreamCipher
改为NewCipher
- trait 名称从
SyncStreamCipher
改为StreamCipher
- trait 名称从
SyncStreamCipherSeek
改为StreamCipherSeek
功能和使用方法与旧版保持兼容,建议尽快迁移到新版本。
1 回复
Rust流密码库stream-cipher使用指南
概述
stream-cipher
是Rust中一个通用的流密码(trait)接口库,提供了对称加密算法的统一抽象接口。它支持多种流密码算法实现,如ChaCha20、Salsa20等。
主要特性
- 统一的流密码trait接口
- 支持多种流行流密码算法
- 零成本抽象
- 符合Rust的加密库安全实践
使用方法
添加依赖
首先在Cargo.toml
中添加依赖:
[dependencies]
stream-cipher = "0.7"
基本加密/解密示例
use stream_cipher::{NewStreamCipher, SyncStreamCipher};
use stream_cipher::generic_array::GenericArray;
// 选择具体的流密码算法(这里以ChaCha20为例)
use chacha20::ChaCha20;
fn main() {
// 密钥和nonce(一次性数字)
let key = GenericArray::from_slice(b"very secret key very secret key");
let nonce = GenericArray::from_slice(b"unique nonce");
// 创建加密器实例
let mut cipher = ChaCha20::new(key, nonce);
// 要加密的数据
let mut data = *b"hello world! this is a secret message";
// 加密数据(原地操作)
cipher.apply_keystream(&mut data);
println!("加密后: {:?}", &data);
// 为了解密,需要重新创建相同参数的加密器
let mut cipher = ChaCha20::new(key, nonce);
// 解密数据
cipher.apply_keystream(&mut data);
println!("解密后: {:?}", std::str::from_utf8(&data).unwrap());
}
使用不同的流密码算法
use salsa20::Salsa20;
use stream_cipher::{NewStreamCipher, SyncStreamCipher};
use stream_cipher::generic_array::GenericArray;
fn salsa_example() {
let key = GenericArray::from_slice(b"an example very very secret key.");
let nonce = GenericArray::from_slice(b"unique nonce");
let mut cipher = Salsa20::new(key, nonce);
let mut data = *b"hello salsa!";
cipher.apply_keystream(&mut data);
println!("Salsa20加密后: {:?}", &data);
// 解密
let mut cipher = Salsa20::new(key, nonce);
cipher.apply_keystream(&mut data);
println!("Salsa20解密后: {}", std::str::from_utf8(&data).unwrap());
}
注意事项
- Nonce安全性:每次加密必须使用唯一的nonce,重复使用nonce会破坏安全性
- 密钥管理:密钥需要安全存储,不要硬编码在源代码中
- 算法选择:根据安全需求选择合适的算法,ChaCha20通常比Salsa20更推荐
高级用法
分段处理数据
对于大文件或流数据,可以分段处理:
use chacha20::ChaCha20;
use stream_cipher::{NewStreamCipher, SyncStreamCipher};
fn process_large_data() {
let key = [0x42; 32];
let nonce = [0x24; 12];
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
let mut chunk1 = [1, 2, 3, 4, 5];
let mut chunk2 = [6, 7, 8, 9, 10];
cipher.apply_keystream(&mut chunk1);
cipher.apply_keystream(&mut chunk2);
// 解密时需要从相同状态继续
}
使用随机nonce
use rand_core::{OsRng, RngCore};
use chacha20::ChaCha20;
fn random_nonce_example() {
let mut key = [0u8; 32];
let mut nonce = [0u8; 12];
OsRng.fill_bytes(&mut key);
OsRng.fill_bytes(&mut nonce);
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());
// ... 其余加密逻辑
}
支持的算法
stream-cipher
作为trait库,需要配合具体算法实现使用,常见的有:
chacha20
: ChaCha20流密码salsa20
: Salsa20流密码aes
: AES-CTR模式(作为流密码使用)
通过统一的trait接口,可以在不同算法间轻松切换,而无需修改核心加密逻辑。
完整示例代码
// 完整示例:使用ChaCha20加密/解密文件内容
use std::fs::File;
use std::io::{Read, Write};
use chacha20::ChaCha20;
use stream_cipher::{NewStreamCipher, SyncStreamCipher};
use stream_cipher::generic_array::GenericArray;
use rand_core::{OsRng, RngCore};
fn main() -> std::io::Result<()> {
// 1. 生成随机密钥和nonce
let mut key = [0u8; 32]; // ChaCha20需要32字节密钥
let mut nonce = [0u8; 12]; // 12字节nonce
OsRng.fill_bytes(&mut key);
OsRng.fill_bytes(&mut nonce);
// 2. 加密文件
encrypt_file("plaintext.txt", "ciphertext.bin", &key, &nonce)?;
// 3. 解密文件
decrypt_file("ciphertext.bin", "decrypted.txt", &key, &nonce)?;
Ok(())
}
fn encrypt_file(
input_path: &str,
output_path: &str,
key: &[u8; 32],
nonce: &[u8; 12]
) -> std::io::Result<()> {
// 读取文件内容
let mut file = File::open(input_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// 创建加密器
let key = GenericArray::from_slice(key);
let nonce = GenericArray::from_slice(nonce);
let mut cipher = ChaCha20::new(key, nonce);
// 原地加密
cipher.apply_keystream(&mut buffer);
// 写入加密后文件
let mut output = File::create(output_path)?;
output.write_all(&buffer)?;
println!("文件加密完成: {}", output_path);
Ok(())
}
fn decrypt_file(
input_path: &str,
output_path: &str,
key: &[u8; 32],
nonce: &[u8; 12]
) -> std::io::Result<()> {
// 读取加密文件
let mut file = File::open(input_path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
// 创建解密器(使用相同密钥和nonce)
let key = GenericArray::from_slice(key);
let nonce = GenericArray::from_slice(nonce);
let mut cipher = ChaCha20::new(key, nonce);
// 原地解密
cipher.apply_keystream(&mut buffer);
// 写入解密后文件
let mut output = File::create(output_path)?;
output.write_all(&buffer)?;
println!("文件解密完成: {}", output_path);
Ok(())
}