#api-key #prefixed #key-prefix

prefixed-api-key

Rust模块,用于生成带前缀的API Key

5个不稳定版本

新版本 0.3.0 2024年8月21日
0.2.0 2024年4月6日
0.1.0 2023年4月24日
0.1.0-beta.12022年8月29日
0.1.0-beta.02022年8月28日

#283 in 加密

Download history 203/week @ 2024-05-02 172/week @ 2024-05-09 224/week @ 2024-05-16 141/week @ 2024-05-23 131/week @ 2024-05-30 157/week @ 2024-06-06 233/week @ 2024-06-13 109/week @ 2024-06-20 84/week @ 2024-06-27 84/week @ 2024-07-04 84/week @ 2024-07-11 60/week @ 2024-07-18 147/week @ 2024-07-25 66/week @ 2024-08-01 99/week @ 2024-08-08 212/week @ 2024-08-15

541 每月下载量
2 crates 中使用

MIT 协议

45KB
773

带前缀的API Key的Rust实现

这个库是Prefixed API Key TypeScript库的Rust实现。尽管其接口与TypeScript版本略有不同,但这个库提供了与TypeScript版本相同的特性和功能。

带前缀的API Key (Seam风格)

示例密钥: mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG

请参见Hacker News上的讨论

Seam风格的API Key具有许多优点

  • 双击API密钥可选中整个API密钥
  • 由于base58 RFC及其在加密货币中的应用,字母表在语言间是标准的
  • 它们比十六进制和base32 API密钥更短
  • 它们有前缀,允许GitHub进行秘密扫描
  • 它们有一个散列组件,因此服务器不需要存储API密钥(减少攻击面)
  • 它们有未散列的短令牌,服务器和密钥持有者/客户可以互相使用来识别API密钥
  • 它们的熵位数与UUIDv4大致相同

格式

Seam风格的API密钥看起来像这样

mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG

让我们分析API密钥的每个组件...

mycompany ..._...  BRTRKFsL ..._...  51FwqftsmMDHHbJAMEXXHCgG
^                  ^                 ^
Prefix             Short Token       Long Token
  • 前缀用于标识创建API密钥的公司或服务。这在秘密扫描中非常有用。
  • 短令牌由服务器和密钥持有者/客户存储,可以用于在日志中识别API密钥或在客户的仪表板上显示。可以通过其短令牌将令牌列入黑名单。
  • 长令牌用于验证此密钥。长令牌永远不会存储在服务器上,但它的散列值会存储在服务器上。当我们收到一个传入请求时,我们在数据库中搜索short_tokenhash(long_token)

入门指南

带前缀的API Key的原始TypeScript实现中包含了一些硬编码的技术决策,但这个crate旨在提供对所使用的哈希算法和随机数生成器的完全控制。然而,这增加了比可能期望的更多复杂性,因此提供了助手来使配置相对容易。

通过安装带有 sha2 功能标志的crate,您可以使用 seam_defaults 函数创建一个几乎完全配置的 PrefixedApiKeyController 实例,该函数以与Seam的Typescript实现相同的方式配置控制器。

use prefixed_api_key::PrefixedApiKeyController;

fn main() {
    // A controller using `rand::rng::OsRng` as the RNG source, and
    // `sha2::Sha256` as the hashing algorithm.
    let builder_result = PrefixedApiKeyController::configure()
        .prefix("mycompany".to_owned())
        .seam_defaults()
        .finalize();

    assert!(builder_result.is_ok());

    let controller = builder_result.unwrap();

    // Generate a new PrefixedApiKey
    let (pak, hash) = controller.try_generate_key_and_hash().unwrap();

    // Assert that the returned key matches the hash
    assert!(controller.check_hash(&pak, &hash));

    // Stringify the key to be sent to the user. This creates a string from the
    // PrefixedApiKey which follows the `<prefix>_<short token>_<long token>` convention
    let pak_string = pak.to_string();
}

使用带有 seam_defaults() 函数和 sha2 功能标志等价于在不使用 sha2 功能的情况下执行以下操作

use sha2::Sha256;
use prefixed_api_key::PrefixedApiKeyController;

fn main() {
    let controller = PrefixedApiKeyController::<_, Sha256>::configure()
        .prefix("mycompany".to_owned())
        .rng_osrng()
        .short_token_length(8)
        .long_token_length(24)
        .finalize();
}

测试

库测试

cargo test --all-features

验证最小支持的Rust版本(MSRV)

cargo install cargo-msrv
cargo msrv verify

测试代码卫生需要 clippyrustfmt 组件

cargo fmt --all -- --check
cargo clippy -- -D warnings

库和卫生测试也将运行在所有示例上

依赖关系

~770KB
~15K SLoC