10个版本 (3个稳定版)
1.2.0 | 2022年3月26日 |
---|---|
1.1.0 | 2020年7月27日 |
1.0.0 | 2020年3月13日 |
0.12.1 | 2019年7月26日 |
0.9.1 | 2014年12月16日 |
#242 in 加密学
2,502 次每月下载
在 4 个crate中使用 (通过 edcert)
120KB
1.5K SLoC
secrets
secrets
是一个库,帮助Rust程序员在内存中安全地保存加密密钥。
它主要是对libsodium提供的内存保护工具的便捷包装。
在栈上分配的固定大小缓冲区获得以下保护
mlock(2)
被调用来处理底层内存- 当不再使用时,底层内存会被清零
- 它们在其整个生命周期内被借用,因此不能被移动
- 它们在常数时间内进行比较
- 它们被
Debug
阻止打印 - 它们被阻止进行
Clone
操作
固定和可变大小的缓冲区可以在堆上分配,并获得以下保护
- 除非作用域内有活动的借用,否则底层内存通过
mprotect(2)
受保护,以免被读取或写入 mlock(2)
被调用来处理分配的内存- 当不再使用时,底层内存会被清零
- 通过不可访问的守卫页面检测溢出和下溢,导致立即段错误和程序终止
- 当使用canaries释放内存时,检测到写入内存的短下溢,将导致段错误和程序终止
恐慌安全性
此库明确不是恐慌安全的。为了确保保护内存空间的安全,如果此库无法执行其宣传的保证,它将引发恐慌。
同样,如果(并且仅当)该库检测到某些安全违规时,它将导致段错误。例如,如果某个进程尝试直接读取或写入尚未正确解锁的内存内容,或者如果canaries已被覆盖,则可能会发生这种情况。该库已被编写以确保通过良好的Rust代码不可能引起此类违规,因此,这些违规应仅作为安全漏洞的结果而出现。
示例
示例:生成加密密钥
Secret::<[u8; 16]>::random(|s| {
// use `s` as if it were a `&mut [u8; 16]`
//
// the memory is `mlock(2)`ed and will be zeroed when this closure
// exits
});
示例:从磁盘加载主密钥并从中生成子密钥
use std::fs::File;
use std::io::Read;
use libsodium_sys as sodium;
use secrets::SecretBox;
const KEY_LEN : usize = sodium::crypto_kdf_KEYBYTES as _;
const CTX_LEN : usize = sodium::crypto_kdf_CONTEXTBYTES as _;
const CONTEXT : &[u8; CTX_LEN] = b"example\0";
fn derive_subkey(
key: &[u8; KEY_LEN],
context: &[u8; CTX_LEN],
subkey_id: u64,
subkey: &mut [u8],
) {
unsafe {
libsodium_sys::crypto_kdf_derive_from_key(
subkey.as_mut_ptr(),
subkey.len(),
subkey_id,
context.as_ptr().cast(),
key.as_ptr()
);
}
}
let master_key = SecretBox::<[u8; KEY_LEN]>::try_new(|mut s| {
File::open("example/master_key/key")?.read_exact(s)
})?;
let subkey_0 = SecretBox::<[u8; 16]>::new(|mut s| {
derive_subkey(&master_key.borrow(), CONTEXT, 0, s);
});
let subkey_1 = SecretBox::<[u8; 16]>::new(|mut s| {
derive_subkey(&master_key.borrow(), CONTEXT, 1, s);
});
assert_ne!(
subkey_0.borrow(),
subkey_1.borrow(),
);
示例:在内存中安全地存储解密后的密文
use std::fs::File;
use std::io::Read;
use libsodium_sys as sodium;
use secrets::{SecretBox, SecretVec};
const KEY_LEN : usize = sodium::crypto_secretbox_KEYBYTES as _;
const NONCE_LEN : usize = sodium::crypto_secretbox_NONCEBYTES as _;
const MAC_LEN : usize = sodium::crypto_secretbox_MACBYTES as _;
let mut key = SecretBox::<[u8; KEY_LEN]>::zero();
let mut nonce = [0; NONCE_LEN];
let mut ciphertext = Vec::new();
File::open("example/decrypted_ciphertext/key")?
.read_exact(key.borrow_mut().as_mut())?;
File::open("example/decrypted_ciphertext/nonce")?
.read_exact(&mut nonce)?;
File::open("example/decrypted_ciphertext/ciphertext")?
.read_to_end(&mut ciphertext)?;
let plaintext = SecretVec::<u8>::new(ciphertext.len() - MAC_LEN, |mut s| {
if -1 == unsafe {
sodium::crypto_secretbox_open_easy(
s.as_mut_ptr(),
ciphertext.as_ptr(),
ciphertext.len() as _,
nonce.as_ptr(),
key.borrow().as_ptr(),
)
} {
panic!("failed to authenticate ciphertext during decryption");
}
});
assert_eq!(
*b"attack at dawn",
*plaintext.borrow(),
);
许可证
根据您选择之一许可
任选。
依赖项
~0–4.5MB
~21K SLoC