8 个版本
0.2.6 | 2024 年 7 月 18 日 |
---|---|
0.2.5 | 2024 年 7 月 17 日 |
0.2.4 | 2024 年 4 月 25 日 |
0.2.0 | 2024 年 3 月 16 日 |
0.1.0 | 2024 年 1 月 27 日 |
266 在 Rust 模式 中
每月 111 次下载
65KB
722 行
Secrets Management crate with
- 类型级别和编译时保证,并且
- 每个引用都对应每个只能在一个具有不变生命周期的词法作用域中暴露或揭示的秘密
它与 secrecy
crate 类似,但具有类型级别和编译时保证,即 Secret<T, MEC, EC>
值不会超过 MEC
次数暴露,并且仅在定义良好的词法作用域下暴露。
它使用 typenum
crate 来实现其所有编译时保证。
功能
- 暴露控制:秘密值只能暴露有限次数,防止意外信息泄露。这是在编译时保证的。秘密值在一个具有不变生命周期的词法作用域中暴露和可用。
- 零化:如果配置了 "zeroize" 功能,则在丢弃秘密值时将其零化。
- 可克隆的秘密:使用 "cloneable-secret" 功能,如果底层类型
T
实现了CloneableSecret
特性,则可以克隆Secret
值。 - 调试秘密:使用 "debug-secret" 功能,如果底层类型
T
实现了DebugSecret
特性,则可以调试Secret
值。
使用示例
编译时检查
use sosecrets_rs::{
prelude::*,
traits::ExposeSecret,
};
use typenum::U2;
// Define a secret with a maximum exposure count of 2
let secret = Secret::<_, U2>::new("my_secret_value".to_string());
// Expose the secret and perform some operations with the exposed value; secret has been exposed once: `EC` = 1, `MEC` = 2;
let (next_secret, exposed_value) = secret.expose_secret(|exposed_secret| {
// `exposed_secret` is only 'available' from the next line -------
assert_eq!(&*exposed_secret.as_str(), "my_secret_value"); // ^
// Perform operations with the exposed value |
// ... v
// to this line... -----------------------------------------------
});
// Expose the secret again and perform some operations with the exposed value; secret has been exposed twice: `EC` = 2, `MEC` = 2;
let (next_secret, exposed_value) = next_secret.expose_secret(|exposed_secret| {
assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
// Perform operations with the exposed value
// ...
});
尝试再次公开秘密并使用公开的值执行一些操作;秘密已被公开第三次:EC
= 3,MEC
= 2;以下代码不可编译。
let (next_secret, exposed_value) = next_secret.expose_secret(|exposed_secret| {
assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
// Perform operations with the exposed value
// ...
});
不可能将传递给闭包的值(例如上面示例中的 exposed_secret
)返回到闭包之外。
以下代码不可编译。
let (next_secret, exposed_value) = next_secret.expose_secret(|exposed_secret| {
assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
// Perform operations with the exposed value
// ...
exposed_secret // impossible to return `exposed_secret` here
});
注意:如果 T
是 Copy
,则上述代码可以成功编译,并且 expose_secret(...)
方法将返回公开的 T
的一个 副本。
运行时检查
use sosecrets_rs::{
prelude::*,
// Note, for runtime checks, you have to use the `RTExposeSecret` trait instead.
runtime::traits::RTExposeSecret,
};
use typenum::U2;
// Define a secret with a maximum exposure count of 2
let secret = RTSecret::<_, U2>::new("my_secret_value".to_string());
// Expose the secret and perform some operations with the exposed value; secret has been exposed once: `EC` = 1, `MEC` = 2;
let exposed_value = secret.expose_secret(|exposed_secret| {
// `exposed_secret` is only 'available' from the next line -------
assert_eq!(&*exposed_secret.as_str(), "my_secret_value"); // ^
// Perform operations with the exposed value |
// ... v
// to this line... -----------------------------------------------
});
// Expose the secret again and perform some operations with the exposed value; secret has been exposed twice: `EC` = 2, `MEC` = 2;
let exposed_value = secret.expose_secret(|exposed_secret| {
assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
// Perform operations with the exposed value
// ...
});
尝试再次公开秘密并使用公开的值执行一些操作;秘密已被公开第三次:EC
= 3,MEC
= 2;
.expose_secret(...)
方法将引发 panic
并显示消息
`RTSecret\` has already been exposed for 2 times, the maximum number it is allowed to be exposed for is 2 times."
# use sosecrets_rs::{
# prelude::*,
# // Note, for runtime checks, you have to use the `RTExposeSecret` trait instead.
# runtime::traits::RTExposeSecret,
# };
# use typenum::U2;
#
# // Define a secret with a maximum exposure count of 2
# let secret = RTSecret::<_, U2>::new("my_secret_value".to_string());
#
# // Expose the secret and perform some operations with the exposed value; secret has been exposed once: `EC` = 1, `MEC` = 2;
# let exposed_value = secret.expose_secret(|exposed_secret| {
# // `exposed_secret` is only 'available' from the next line -------
# assert_eq!(&*exposed_secret.as_str(), "my_secret_value"); // ^
# // Perform operations with the exposed value |
# // ... v
# // to this line... -----------------------------------------------
# });
#
# // Expose the secret again and perform some operations with the exposed value; secret has been exposed twice: `EC` = 2, `MEC` = 2;
# let exposed_value = secret.expose_secret(|exposed_secret| {
# assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
# // Perform operations with the exposed value
# // ...
# });
let exposed_value = secret.expose_secret(|exposed_secret| {
assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
// Perform operations with the exposed value
// ...
});
注意:您可以使用方法 expose_secret(...)
的非 panic
变体,该方法的名称为 try_expose_secret(...)
。
try_expose_secret(...)
如果公开次数超过最大允许值,则返回一个 Result::Err
。
不可能将传递给闭包的值(例如上面示例中的 exposed_secret
)返回到闭包之外,除非 T
是 Copy
。以下代码不可编译。
let exposed_value = secret.expose_secret(|exposed_secret| {
assert_eq!(&*exposed_secret.as_str(), "my_secret_value");
// Perform operations with the exposed value
// ...
exposed_secret // impossible to return `exposed_secret` here
});
将 secrecy
包替换为
您可以使用 SecrecySecret
类型作为 Secret<T>
的替代品,该类型位于 secrecy
包中。
use sosecrets_rs::{
prelude::*,
// Note, for runtime checks, you have to use the `RTExposeSecret` trait instead.
runtime::traits::RTExposeSecret,
};
// Define a secret with NO maximum exposure count
let secret = SecrecySecret::new("my_secret_value".to_string());
// Expose the secret and perform some operations with the exposed value as many times as you like.
for _ in 0..=1_000_000 {
let exposed_value = secret.expose_secret(|exposed_secret| {
// `exposed_secret` is only 'available' from the next line -------
assert_eq!(&*exposed_secret.as_str(), "my_secret_value"); // ^
// Perform operations with the exposed value |
// ... v
// to this line... -----------------------------------------------
});
}
更多示例请参阅 示例目录。
功能配置
要启用功能,您可以在您的 Cargo.toml
文件中包含它们
[dependencies]
sosecrets-rs = { version = "x.x.x", features = ["zeroize", "cloneable-secret", "debug-secret"] }
模块
prelude
:用于轻松导入常用项的模块。runtime
:用于RTSecret<T>
、SecrecySecret
和RTExposeSecret
的模块。
特质
ExposeSecret
:编译时具有有限公开计数的安全公开秘密的特质。RTExposeSecret
:运行时具有有限公开计数的安全公开秘密的特质。CloneableSecret
:可克隆秘密的特质。DebugSecret
:可调试秘密的特质。
例如,如果启用了功能 "cloneable-secret"
,那么您就可以“克隆”秘密。
示例
#[cfg(all(feature = "cloneable-secret", feature = "alloc"))]
// Need to enable feature = "alloc" because `String` requires feature = "alloc".
{
use sosecrets_rs::{
prelude::*,
traits::{CloneableSecret, ExposeSecret},
};
use typenum::U2;
// Define a secret with a maximum exposure count of 2
let secret = Secret::<_, U2>::new("my_secret_value".to_string());
// Clone the secret
let secret2 = secret.clone();
// Expose the secret and perform some operations with the exposed value; secret has been exposed once: `EC` = 1, `MEC` = 2;
let (next_secret, exposed_value) = secret.expose_secret(move |exposed_secret| {
// `exposed_secret` is only 'available' from the next line --------------------------^
let (next_secret2, exposed_value2) = secret2.expose_secret(|exposed_secret2| { // |
assert_eq!(&*exposed_secret.as_str(), "my_secret_value"); // |
assert_eq!(&*exposed_secret2.as_str(), "my_secret_value"); // |
assert_eq!(&*exposed_secret2.as_str(), &*exposed_secret.as_str()); // |
// Perform operations with the exposed value |
// ... |
// to this line... ---------------------------------------------------------------v
});
});
}
最低支持的 Rust 版本
该包目前需要 Rust 1.70。我没有意图将此包的编译器版本要求提高超过这个版本。然而,这仅保证在给定的次要版本号内。
测试
运行
bash scripts/tests-all-features.sh
许可证
许可下
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
贡献
除非您明确声明,否则,根据 MIT 许可证,您有意提交的任何贡献,以包含在作品中,没有附加条款或条件。
致谢
CAD97
- 为在
ExposeSecret
的设计和实现中提供实质性帮助,该特性为ExposeSecret
trait 和其 trait 方法expose_secret(...)
[Rust 论坛,Rust 操场]。 - 教授我
invariant
生命周期的概念。
Eric Michael Sumner
- 在 Rust 论坛 上创建宏
impl_choose_int!()
。该宏有助于为typenum
包提供的所有类型级无符号整数实现ChooseMinimallyRepresentableUInt
trait,这些整数在类型级别上可以从 1 位到 64 位表示。
Simon Farnsworth
依赖项
~165KB