5 个不稳定版本
0.3.2 | 2022年8月13日 |
---|---|
0.3.1 | 2020年3月7日 |
0.3.0 | 2019年12月14日 |
0.2.0 | 2019年12月12日 |
0.1.0 | 2018年9月3日 |
#505 in 加密学
32 每月下载
在 3 crates 中使用
48KB
789 行
Rust Cryptostream 库
cryptostream
提供了与 .NET Cryptostream 类的 Rust 等价物,为现有 Read
或 Write
资源的即时加密或解密提供了一个高效且易于使用的解决方案。加密是通过 rust-openssl 提供的,并且可以完全配置。
什么是 Cryptostream?
简而言之,Cryptostream 是一个围绕流(在 Rust 术语中,是 Read
或 Write
类型)的包装器,它可以透明地加密或解密底层内容。在指定了加密算法、密钥和 IV 之后创建了一个 Cryptostream
实例,写入或读取到 Cryptostream 的字节与包装的 Read
或 Write
流相同,只是额外地进行了加密或解密。这使得处理加密源或目标变得非常简单,几乎不需要更改现有的管道 - 它就像任何其他的 Read
或 Write
一样。
库设计
由于 Rust(无论是好是坏)缺少 Stream
类型,cryptostream
已在加密和解密模式下分别实现了两次,一次作为 Read
实现,一次作为 Write
实现(设计灵感来自 flate2
库),为了万无一失还添加了 BufRead
实现。这意味着对于任何可用的 [密文|明文] 和所需的 [读取|写入] 应用组合,cryptostream
实现之一应该符合您的用例。应创建一个与您希望消费的资源类型相匹配的 cryptostream
(如果源数据是 Read
实现),或者与您希望创建的资源类型相匹配的 cryptostream
(如果目标是 Write
实现)。
实现已按特性分组到命名空间中,并且具有传达其应用的名字
cryptostream::read::Encryptor
cryptostream::read::Decryptor
cryptostream::write::Encryptor
cryptostream::write::Decryptor
Read
与 Write
加密流
cryptostream
的 Read
和 Write
变体之间的区别,或许通过示例最能说明。在以下两个示例中,我们都会进行解密,然而在一个情况下我们需要使用 read::Decryptor
,而在另一个情况下使用 write::Decryptor
。
在第一种情况下,我们有一个 Read
源,其中包含我们需要解密的字节,并且我们希望在内存中获得等效的明文,以便稍后对其进行解码状态的操作
// This is the cipher text, base64-encoded to avoid any whitespace munging. In this
// contrived example, we are using a binary `Vec<u8>` as the `Read` source containing
// the encrypted data; in practice it could be a binary file, a network stream, or
// anything else.
let src: Vec<u8> = decode(concat!(
"vuU+0SXFWQLu8vl/o1WzmPCmf7x/O6ToGQ162Aq2CHxcnc/ax/Q8nTbRlNn0OSPrFuE3yDdO",
"VC35RmwtUIlxKIkWbnxJpRF5yRJvVByQgWX1qLW8DfMjRp7gVaFNv4qr7G65M6hbSx6hGJXv",
"Q6s1GiFwi91q0V17DI79yVrINHCXdBnUOqeLGfJ05Edu+39EQNYn4dky7VdgTP2VYZE7Vw==",
))
.unwrap();
let key: Vec<_> = decode("kjtbxCPw3XPFThb3mKmzfg==").unwrap();
let iv: Vec<_> = decode("dB0Ej+7zWZWTS5JUCldWMg==").unwrap();
// The source can be anything implementing `Read`. In this case, a simple &[u8] slice.
let mut decryptor =
read::Decryptor::new(src.as_slice(), Cipher::aes_128_cbc(), &key, &iv).unwrap();
let mut decrypted = [0u8; 1024]; // a buffer to decrypt into
let mut bytes_decrypted = 0;
loop {
// Just read from the `Decryptor` as if it were any other `Read` impl,
// the decryption takes place automatically.
let read_count = decryptor.read(&mut decrypted[bytes_decrypted..]).unwrap();
bytes_decrypted += read_count;
if read_count == 0 {
break;
}
}
println!("{}", String::from_utf8_lossy(&decrypted));
那么,如果你想要将解密的内容 写入 而不是 读取,但仍想进行解密,怎么办呢?
// Starting again with the same encrypted bytestream, encoded as base64:
let src: Vec<u8> = decode(concat!(
"vuU+0SXFWQLu8vl/o1WzmPCmf7x/O6ToGQ162Aq2CHxcnc/ax/Q8nTbRlNn0OSPrFuE3yDdO",
"VC35RmwtUIlxKIkWbnxJpRF5yRJvVByQgWX1qLW8DfMjRp7gVaFNv4qr7G65M6hbSx6hGJXv",
"Q6s1GiFwi91q0V17DI79yVrINHCXdBnUOqeLGfJ05Edu+39EQNYn4dky7VdgTP2VYZE7Vw=="
))
.unwrap();
let key: Vec<_> = decode("kjtbxCPw3XPFThb3mKmzfg==").unwrap();
let iv: Vec<_> = decode("dB0Ej+7zWZWTS5JUCldWMg==").unwrap();
// The destination can be any object implementing `Write`: in this case, a `Vec<u8>`.
let mut decrypted = Vec::new();
// When a `cryptostream` is dropped, all buffers are flushed and it is automatically
// finalized. We can either call `drop()` on the cryptostream or put its usage in a
// separate scope.
{
let mut decryptor =
write::Decryptor::new(&mut decrypted, Cipher::aes_128_cbc(), &key, &iv).unwrap();
let mut bytes_decrypted = 0;
while bytes_decrypted != src.len() {
// Just write encrypted ciphertext to the `Decryptor` instance as if it were any
// other `Write` impl. Decryption takes place automatically.
let write_count = decryptor.write(&src[bytes_decrypted..]).unwrap();
bytes_decrypted += write_count;
}
}
// The underlying `Write` instance is only guaranteed to contain the complete and
// finalized contents after the cryptostream is either explicitly finalized with a
// call to `Cryptostream::finish()` or when it's dropped (either at the end of a scope
// or via an explicit call to `drop()`, whichever you prefer).
println!("{}", String::from_utf8_lossy(&decrypted));
依赖项
~1.8–3MB
~70K SLoC