6 个版本
0.2.1 | 2024 年 4 月 29 日 |
---|---|
0.2.0 | 2024 年 4 月 23 日 |
0.1.0 | 2024 年 3 月 24 日 |
0.0.3 | 2024 年 3 月 11 日 |
0.0.2 | 2024 年 2 月 28 日 |
#5 in #openpgp-card
112 次每月下载
用于 8 个 crate(3 个直接使用)
30KB
302 行
用于使用 OpenPGP 卡的应用程序的状态共享
此 crate 通过应用程序使用 OpenPGP 卡设备。
特别是,它允许应用程序在不要求用户输入 PIN 的情况下对硬件设备进行操作。相反,应用程序通过此库获取用户 PIN。
graph TB
Application --> CARD["OpenPGP card device <br/> (performs cryptographic operations <br/> after User PIN presentation)"]
Application --> STATE["openpgp-card-state library <br/> (config and PIN storage backend access)"]
STATE --> PINS["PIN storage backend <br/> (makes User PINs available to applications)"]
此 crate 使用两种机制的组合
- 常规配置文件:存储非敏感的卡元数据(例如,卡的可选昵称),并指定默认以及按卡使用的 PIN 存储后端。
- PIN 存储后端:代表应用程序存储 OpenPGP 卡设备的(敏感)用户 PIN。存在不同类型的 PIN 存储后端(见下文)。用户可以根据其用例选择合适的后端。
使用和架构
此 crate 由应用程序用作库。该库简化了对配置文件和 PIN 存储后端的读写访问。一般来说,openpgp-card-state
库不需要长时间运行的过程(但是,某些 PIN 存储后端可能由长时间运行的过程组成)。
从用户的角度来看,openpgp-card-state
通常是应用程序的实现细节。然而,了解机制的工作原理可能会有所帮助,以形成一个良好的心理模型。
在 openpgp-card-state
中,卡片使用 "ident" 格式进行寻址,无论是访问配置文件中的元数据,还是存储和检索用户 PIN。
配置文件
openpgp-card-state
的配置文件存储在特定于平台的默认位置。在 Linux 系统上,通常是 $HOME/.config/openpgp-card-state/config.toml
(配置文件由 directories crate 处理,它使用平台特定的标准位置,遵循 Linux 系统上的 XDG 规范)。
卡片的一个典型配置条目如下所示
[[cards]]
ident = "0000:01234567"
pin_storage = "Keyring"
nickname = "my purple card"
此配置条目指定具有 ident 0000:01234567
的卡片使用 "Keyring" PIN 存储后端来存储用户 PIN。此外,为该卡片定义了昵称 my purple card
。
背景、设计权衡和威胁建模
历史上,OpenPGP 卡设备通常通过 GnuPG 使用。
这个软件包作为非GnuPG应用程序使用OpenPGP卡的基础设施。
然而,为了理解设计空间,我们首先将查看OpenPGP卡使用的一些细节。特别是加密操作的授权。然后我们将概述GnuPG如何与OpenPGP卡交互。最后,我们讨论该软件包的概念和相关威胁建模。
OpenPGP卡和用户PIN
讨论的一个特别有趣的话题是“用户PIN”的处理。为了在卡上授权私钥操作(签名或解密),用户PIN必须提交给卡。
OpenPGP卡规范是OpenPGP卡设备上PIN处理的权威参考。规范文档将用户PIN称为“PW1”,并区分了使用PW1的两种模式:模式“81”用于签名操作,模式“82”用于所有其他用户操作(包括解密和身份验证)。
通常,用户PIN只需要提交给卡一次,然后在整个连接期间有效。作为例外,可以将卡配置为用户PIN提交仅对单个签名操作有效,要求用户每次签名操作都输入用户PIN。我们将这个特殊情况放在一边,以下讨论。
通过主机计算机输入PIN与通过带有PIN键盘的卡读卡器输入PIN
从历史上看,OpenPGP卡设备通常是实际物理智能卡,它们在单独的读卡器设备中使用。
一些读卡器具有物理PIN键盘,用于输入(数字)PIN。这种设置可以保护PIN不受主机计算机的侵害:只有读卡器本身可以看到卡主人在读卡器上输入的PIN。在这种情况下,主机计算机不知道PIN。
另一方面,现代OpenPGP卡设备几乎完全转向了不同的硬件:将作为带有插入OpenPGP卡的智能卡读卡器呈现给主机计算机的USB令牌(例如,在开源硬件设计上运行的免费软件Gnuk,或Nitrokey或Yubico的各种商业设备)。使用此类设备时,无法以主机计算机无法访问的方式向“卡”提交用户PIN。
GnuPG的架构
GnuPG是一个历史悠久的软件套件。其根源可以追溯到1997年。它开创了为终端用户使用智能卡进行私钥操作的做法。
其架构由多个进程组成,这些进程通过“assuan”(一个GnuPG特定的IPC协议)相连。以下图显示了GnuPG的多进程架构以及一些应用程序软件以及它如何访问GnuPG
graph TB
GPGME["GPGME <br/> (GnuPG access library)"] --> GPG
GPG["GnuPG <br/> (CLI tool)"] --> GA["gpg-agent <br/> (long running: private key operations)"]
GA --> SCD["scdaemon <br/> (long running: smart card access)"]
GA --> pinentry["pinentry <br/> (prompts users for PINs and other secrets)"]
GIT[Git] -.-> GPG
SSH["SSH <br/> (can use OpenPGP cards via gpg-agent)"] -.-> GA
TB[Thunderbird] -.-> GPGME
classDef application fill:#404040,stroke-dasharray: 5 5;
class TB,GIT,SSH application;
scdaemon
是处理对OpenPGP卡设备访问的GnuPG子系统。它被设计成与任何OpenPGP卡保持永久和独占的连接[^pcscshared]。
[^pcscshared]:scdaemon的较新版本提供对“共享”连接到OpenPGP卡的可选支持。
这种设计具有有用的特性,尤其是在与带有物理PIN键盘的物理智能卡一起使用时:如果不保持与这些设备的持续连接,用户就需要在读取器的物理PIN键盘上反复重新输入PIN,可能每次操作都要输入一次,这在许多情况下都是不可行的。
在这种情况下,与卡保持永久连接是获得良好用户体验的必要条件。
然而,这种设计的缺点是,除了GnuPG的scdaemon之外,没有其他应用程序可以合理地使用这些卡,因为GnuPG保持它们开启并假定独占访问(用户已经采取了措施来处理这一影响的后果。有些人编写了shell脚本来战略性地kill
scdaemon
进程作为解决方案,以便能够从其他应用程序访问他们的卡)。
使用openpgp-card-state存储用户PIN
相比之下,GnuPG的方法(如上所述)进行了不同的权衡,并追求不同的目标。
我们的主要设计目标是
- 使多个应用程序能够直接使用OpenPGP卡,而无需通过某个长时间运行的过程进行中介。
- 提供流畅的用户体验。
- 简单性。
如今,大多数用户不使用外部PIN键盘。这意味着没有充分的理由保持与卡的永久连接。请注意,现代OpenPGP卡的使用本身就要求向主机计算机披露用户PIN。因此,主机计算机可以始终将用户PIN发送到卡上以授权操作。
有关威胁模型讨论的更多内容,请参阅以下内容。
用户不需要手动输入他们的用户PIN以执行每个操作,因此用户PIN需要以某种方式在主机计算机上可用,以便为应用程序使用。作为用户PIN的保管者是此openpgp-card-state
仓库的核心目标。
威胁模型
如上所述,此仓库主要处理主机计算机可以访问用户PIN(至少间歇性)的设置。
这意味着用户PIN不需要对主机计算机具有巨大保护的威胁模型。处理用户PIN的两种可能的方法类别是
- 在主机计算机上持久化用户PIN。
- 在长时间运行的过程中保持用户PIN可用(对于某些可能有限的持续时间),但不在磁盘上持久化。
持久化用户PIN
此仓库允许用户选择处理用户PIN的不同方法。我们将其称为“PIN存储后端”。
我们建议,对于大多数用户来说,通过特定于平台的通用秘密存储机制持久化用户PIN是合理且实用的。我们的默认后端使用“Keyring”用户PIN存储后端(基于https://crates.io/crates/keyring),该后端实现了这种方法。它在Linux上由“secret-service”支持,在Mac上由“keychain”支持,在Windows上由“credential manager”支持。
这种方法并不适用于所有情况。然而,我们认为它在大多数情况下是合适的。用户PIN主要在物理OpenPGP卡设备被盗的情况下提供保护,而没有同时丢失或损坏主机计算机。
另一方面,当针对远程攻击者进行保护时,“触摸确认”对于加密操作是最有用的防御线,使用现代OpenPGP卡设备。在主机计算机远程受侵害的情况下,用户PIN最多只是一种薄弱的防御。
临时用户PIN缓存
对于无法在磁盘上持久化用户PIN且不想为每个操作输入用户PIN的用户,需要某种长时间运行的过程。在我们的架构中,这将是一个作为临时用户PIN存储后端的长运行进程,由用户的各个应用程序共享。
openpgp-card-storage的临时PIN存储后端尚未准备好,但它在我们的路线图上。
PIN存储后端
此仓库的主要目的之一是存储和获取OpenPGP卡设备的用户PIN,特别是为了让用户PIN可用于本地应用程序。
不同的用户可能有不同的用户PIN存储需求或优先级。因此,此仓库支持不同的PIN存储机制,供用户选择。
"Keyring":特定于平台的受保护持久存储
默认情况下,此crate使用“Keyring”PIN存储后端。它基于https://crates.io/crates/keyring crate,并将用户PIN持久保存在平台特定的受保护存储中。
- Linux:secret-service(这需要一个像GNOME Keyring这样的服务来提供secret-service功能)。
- macOS:使用“keychain”子系统。
- Windows:使用“凭据管理器”子系统。
“直接”:在配置文件中存储明文。
某些用户可能不需要由安全意识子系统来处理他们的用户PIN,并且可能更喜欢避免使用此类子系统带来的额外复杂性。在这种情况下,用户PIN可以另存为明文直接存储在配置文件中。
这种模式在不需要保护用户PIN的环境中特别方便,例如CI测试。
将提供更多PIN存储后端
通常请求的功能是一个短暂的PIN存储后端,该后端仅在RAM中保留用户PIN,而不会将它们持久保存在磁盘上。一个额外的短暂PIN存储后端即将推出。
默认用户PIN存储后端
配置文件可以显式定义一个默认PIN存储后端。如果存在此设置,新卡的User PIN将使用指定的default_pin_storage
后端存储。
default_pin_storage = "Direct"
[[cards]]
ident = "0000:01234568"
nickname = "my yellow card"
[cards.pin_storage]
Direct = "123456"
应用开发者使用此库
此库主要面向想要实现OpenPGP卡支持的软件开发者。有关如何使用此库的讨论,请参阅此处。
注意:请注意,此库较新,在稳定之前可能会经历一些迭代。
CLI工具
有关附带CLI工具的描述,该工具主要用于调试目的,请参阅此处。
资金
此项目部分资金来自NGI Assure,该基金由NLnet建立,并获得欧洲委员会下一代互联网计划的财政支持。
依赖关系
~2–12MB
~88K SLoC