12 个稳定版本
1.8.1 | 2023年12月8日 |
---|---|
1.8.0 | 2023年11月16日 |
1.6.0 | 2023年9月19日 |
1.5.0 | 2023年8月16日 |
1.0.0 | 2021年4月13日 |
#54 in 身份验证
95 个月下载
用于 7 个 crates(3 个直接)
90KB
2K SLoC
Cryptex
用于访问各种密钥链或安全区域的命令行 API。
问题
如今,应用程序使用多个凭证来保护本地数据和传输数据。然而,在保护这些凭证时,会养成一些坏习惯。例如,在为亚马逊 AWS 创建 API 令牌时,亚马逊代表用户生成一个密钥,并将其下载到 CSV 文件中。程序员不知道如何最佳地确保这些下载的凭证,因为它们必须用于程序中,以进行 API 调用。他们不知道以下哪个选项是最佳选择
- 将这些凭证直接放入程序中,像大多数人那样作为常量变量,但这是一个糟糕的选择,因为攻击者可以分析代码并提取它。
- 使用环境变量。如果是这样,应该将其在命令级别传递还是放入全局变量注册表中?两者都容易受到嗅探内存或进程信息的影响。
- 读取包含凭证的配置文件,但必须依赖于操作系统的安全性来管理访问控制。
- 使用安全区域存储凭证,但这只是将问题转移到另一个问题上,因为安全区域依赖于另一组凭证来确保应用程序具有正确的授权。这些凭证作为硬件安全模块(HSM)或可信执行环境(TEE)提供。
- 需要与用户或组交互以提供每个使用的凭证,或将其缓存一段时间。这通常使用密码、PIN、网络安全令牌和生物识别技术来完成。
应用程序或人员直接使用的凭证放置位置被称为顶级凭证问题。
有像 LeakLooker 这样的服务,它在互联网上浏览以查找可刮取的凭证,遗憾的是,但经常 成功。一些项目已记录如何测试凭证以查看它们是否已被泄露。请参阅 keyhacks。
这些文档旨在提供指导,并帮助采用最佳实践和开发代码来解决顶级凭证问题——保护所有其他凭证的凭证——进入王国的钥匙——或程序直接使用的秘密,如果泄露将产生灾难性的后果。
解决方案
Cryptex 是一个设计为命令行工具或 API 库的层,用于存储机密信息,并努力使其难以出错。默认情况下,使用操作系统密钥链。目标是增强 Cryptex 以支持许多不同类型的区域,这些区域对于存储像 YubiKey、Intel SGX 或 Arm Trustzone 这样的“王国的钥匙”是最优的。原则上,系统的安全区域应该能够将一些凭证与 root (即,攻击者只要能访问凭证,就可以使用它,但无法提取凭证以持久化)隔离开,并且假设没有其他像 Foreshadow 这样的攻击。
Mac OS X、Linux 和 Android 内置了由操作系统保护的密钥链。iOS 和 Android 带有用于管理密钥链中存储的机密信息的硬件安全区域或可信执行环境。
这个第一版使用 OS 密钥链或等效工具,并通过命令行或 C 可调用的 API 使用。未来的工作可以允许通过 Unix 或 TCP 套接字与作为守护进程运行的 Cryptex 进行通信。
目前,Mac OS X 提供了对 CLI 工具 和 库 的支持,但它们难以理解,并且由于误解而容易误用。 Cryptex 通过选择安全的默认值来简化复杂性,以便开发者可以专注于他们的工作。
Cryptex 用 Rust 编写,除了 Linux 上的 DBus 之外,没有其他外部依赖来完成其工作。
Cryptex 还允许使用 SQLCipher 而不是通过 feature = file
使用密钥环。您可以通过运行函数 allows_file ()
来检查是否启用了 SQLCipher。此方法使用两个输入来创建加密密钥:用户选择的密码和随机系统生成数据。类似于数据库使用连接字符串,此库也使用连接字符串来表示值。连接字符串的语法是 password = <password> salt = <hex encoded salt value>
。此值使用 Argon2id 进行哈希,因此还可以将内存、线程和并行度设置为字符串的一部分 memory = <integer> threads = <integer> parallel = <integer>
。
程序可以从任何操作系统编译,在任意操作系统上运行。Cryptex-CLI 是命令行工具,而 Cryptex 是库。
最终,将添加额外的加密服务,例如基于硬件的 HSM 或 TPM 或 TEE 或软件的,例如
的目标是拥有标准化的安全接口。附加服务的挑战在于每个服务都有不同的威胁模型、期望、要求、假设和操作参数的规范。 Cryptex 致力于成为管理这些服务的主要抽象层。
作为库使用
这个包允许作为 Rust 库运行。
use cryptex::{get_os_keyring, KeyRing};
let mut keyring = get_os_keyring();
keyring.set_secret("test_key", b"secret")?;
// Retrieve secret later
let secret = keyring.get_secret("test_key")?;
// Remove the secret from the keyring
keyring.delete_secret("test_key");
运行程序
基本用法
在 Linux 上需要 dbus 库。
在 ubuntu 上,运行时这是 libdbus-1-3。在 redhat 上,运行时这是 dbus。
Linux 上还必须安装 Gnome-keyring 或 KWallet。
Cryptex 可以通过 cargo run -- <args> 运行,或者如果已经从源代码构建,则使用 ./cryptex。
Cryptex 尝试确定输入是文件还是文本。如果存在与输入文本匹配的文件, Cryptex 将读取其内容。否则,它将提示用户输入秘密的 ID 或输入一个秘密。
Cryptex 根据服务名称和 ID 存储秘密。服务名称是程序或进程的名称,该程序或进程只能使用 ID 访问秘密。秘密可以被检索、存储或删除。
在存储秘密时,应小心不要将其值通过命令行传递,因为它可能被存储在命令行历史记录中。因此,可以将值放在文件中,或者 Cryptex 将从 STDIN 读取它。在 Cryptex 存储秘密后,Cryptex 将安全地从内存中擦除它。
注意事项
一个问题是如何解决提供给 Cryptex 的服务名称。理想情况下, Cryptex 可以计算它,而不是从调用端点提供,因为调用端点可能会提供虚假的名称。我们可以想象一个攻击者想要访问密钥链中的 aws 凭据,只需知道服务名称和秘密的 ID 即可请求它。如果攻击者不知道与密码保险箱类似的密钥链凭据,则操作系统将阻止访问。如果 Cryptex 可以计算服务名称,那么这将使攻击者更难检索目标秘密。然而,这比秘密以纯文本形式存在于代码、配置文件或环境变量中要好。
示例
Cryptex 至少需要两个参数:service_name 和 ID。在存储秘密时,需要额外的参数。如果省略(首选方法),则从 STDIN 读取值。
在使用 SQLCipher 的情况下,服务名称是用于连接的字符串。
存储秘密
cryptex set aws 1qwasdrtyuhjnjyt987yh
prompt> ...<Return>
Success
检索秘密
cryptex get aws 1qwasdrtyuhjnjyt987yh
<Secret Value>
删除秘密
cryptex delete aws 1qwasdrtyuhjnjyt987yh
列出所有秘密
Cryptex 可以读取密钥圈中存储的所有值。列表将仅列出密钥圈中所有值的名称,而不会检索其实际值。
cryptex list
{"application": "cryptex", "id": "apikey", "service": "aws", "username": "mike", "xdg:schema": "org.freedesktop.Secret.Generic"}
{"application": "cryptex", "id": "walletkey", "service": "indy", "username": "mike", "xdg:schema": "org.freedesktop.Secret.Generic"}
查看秘密
Cryptex 可以检索密钥圈中的所有或部分秘密。如果没有提供任何参数进行查看,将提取所有密钥圈名称及其值。由于 Cryptex 在将其存储在密钥圈中之前会加密值,因此这些值将以十六进制值的形式返回,而不是其关联的纯文本。根据操作系统,查看过滤不同。
对于 OSX,过滤基于应读取的 kind。它可以是指定密码的 generic 或 internet。 generic 仅需要 service 和 account 标签。 internet 需要 server、 account、 protocol、 authentication_type 值。过滤器作为以等号分隔的名称值对提供,多个对用逗号分隔。
cryptex peek service=aws,account=apikey
对于 Linux,过滤基于匹配的属性名称值对的子集。例如,如果密钥圈中的属性如下所示
{"application": "cryptex", "id": "apikey", "service": "aws", "username": "mike", "xdg:schema": "org.freedesktop.Secret.Generic"}
{"application": "cryptex", "id": "walletkey", "service": "indy", "username": "mike", "xdg:schema": "org.freedesktop.Secret.Generic"}
要基于 id 过滤,运行
cryptex peek id=apikey
要基于 username 和 service 过滤,运行
cryptex peek username=mike,service=aws
对于 Windows,过滤基于凭据目标名称和通配符。例如,如果 list 返回
{"targetname": "MicrosoftAccount:target=SSO_POP_Device"}
{"targetname": "WindowsLive:target=virtualapp/didlogical"}
{"targetname": "LegacyGeneric:target=IEUser:aws:apikey"}
则过滤搜索 ":target=" 之后的 everything。在这种情况下,如果要查看的值是 IEUser:aws:apikey,则以下将只返回该结果
cryptex.exe peek IE*
cryptex.exe peek IE*apikey
cryptex.exe peek IEUser:aws:apikey
从源代码构建
[build-from-source]: # build-from-source
要生成可分发的可执行文件,请运行以下命令
- 在 Linux 上安装 dbus 库。在基于 Debian 的操作系统上,这是 libdbus-1-dev。在基于 Redhat 的操作系统上,这是 dbus-devel。
- curl https://sh.rustup.rs -sSf | sh -s -- -y - 安装运行时编译器
- cd reference_code/
- cargo build --release - 当这完成时,可执行文件为 target/release/cryptex。
- 对于*nix用户 cp target/release/cryptex /usr/local/lib 和 chmod +x /usr/local/lib/cryptex
- 对于Windows用户,将 target/release/cryptex.exe 复制到一个文件夹中,并将该文件夹添加到您的 %PATH 变量中。
Libcryptex 是可以链接到程序以管理秘密的库。使用满足您需求的基础操作系统库
- libcryptex.dll - Windows
- libcryptex.so - Linux
- libcryptex.dylib - Mac OS X
未来工作
允许使用其他密室,如Hashicorp vault、LastPass、1Password。允许使用图像或Microsoft Office文件等隐写术方法来存储秘密。
依赖关系
~1-20MB
~241K SLoC