Clevis 是一个用于自动解密的可插入框架。它可用于提供数据的自动解密,甚至 LUKS 卷的自动解锁。
这看起来像什么?好吧,第一步是加密一些数据。我们用一个简单的命令来做到这一点:
$ clevis encrypt PIN CONFIG < PLAINTEXT > CIPHERTEXT.jwe
此命令在标准输入上获取纯文本,并在标准输出上生成加密的 JWE 对象。除了明文之外,我们还需要指定两个额外的输入参数。
首先是引脚。在U形夹术语中,引脚是实现自动解密的插件。我们在这里简单地传递一个引脚的名称。
其次,是配置。配置是一个 JSON 对象,将直接传递到 pin。它包含执行加密和设置自动解密所需的所有配置。
要解密我们的 JWE,我们只需执行以下操作:
$ clevis decrypt < CIPHERTEXT.jwe > PLAINTEXT
请注意,解密命令不需要额外的输入或交互。让我们看一些更具体的例子。
Tang 是一种服务器实现,无需托管即可提供加密绑定服务。克莱维斯全力支持唐。以下是如何将 U 形夹与 Tang 一起使用的示例:
$ echo hi | clevis encrypt tang ' {"url": "http://tang.local"} ' > hi.jwe
The advertisement is signed with the following keys:
kWwirxc5PhkFIH0yE28nc-EvjDY
Do you wish to trust the advertisement ? [yN] y
在此示例中,我们使用 Tang pin 加密消息“hi”。在这种情况下,唯一需要的参数是 Tang 服务器的 URL。在加密过程中,Tang pin 会向服务器请求密钥通告,并要求您信任密钥。这与 SSH 的工作原理类似。
或者,您可以使用adv
参数手动加载广告。此参数采用引用存储广告的文件的字符串,或广告本身的 JSON 内容。当像这样手动指定广告时,Clevis 假定该广告是可信的。
Clevis 支持对可信平台模块 2.0 (TPM2) 芯片中的密钥进行加密。用于加密的加密强度高的随机密钥使用 TPM2 芯片进行加密,并在解密时使用 TPM2 进行解密,以允许 U 形夹解密存储在 JWE 中的秘密。
例如:
$ echo hi | clevis encrypt tpm2 ' {} ' > hi.jwe
Clevis 将加密密钥的公钥和私钥存储在 JWE 对象中,因此可以在解密时获取这些密钥以解封使用 TPM2 加密的密钥。
U 形夹可以执行 PKCS#11 应用程序的角色,如 RFC 7512:PKCS#11 URI 方案中所述。
PKCS#11 协议确定必须将 PIN(个人身份号码)配置到硬件设备中,以便解锁过程成功。 U形夹将允许用户解锁特定的加密磁盘,并将提供一种获取PIN码的方法。会有两种可能:
1 - 在启动时提供 PIN:在第一种情况下,Clevis 将检测 PKCS#11 设备并提示输入其 PIN。如果 PIN 码错误,Clevis 将再次提示输入 PIN 码。用户有责任了解在 PIN 未知的情况下设备可能被锁定/变砖的情况。
2 - 在 U 形夹配置时提供 PIN:在第二种情况下,U 形夹将使用 PIN 值进行配置。
最初,RFC7512 定义了一种机制来指定一种特殊类型的 URI( pkcs11
URI),该机制允许识别设备以及解锁设备所需的信息。值得特别注意的是参数pin-value
,它允许分别指定 PIN 的值或 PIN 的位置。 U形夹最初会理解“引脚值”参数。您可以在下面找到使用先前参数的 PKCS#11 URI 的示例:
pin-value
的 PKCS#11 URI: pkcs11:token=Software%20PKCS%2311%20softtoken;manufacturer=Snake%20Oil,%20Inc.?pin-value=the-pin
下一节将提供 U 形夹配置示例,以便阐明将 PKCS#11 设备绑定到加密磁盘的不同选项。
U 形夹将为用户提供一种将特定 PKCS#11 设备绑定到加密设备的机制。 U形夹的新引脚名称为pkcs11
,配置方式与当前使用的方式相同:
$ clevis luks bind -h
Usage: clevis luks bind [-y] [-f] [-s SLT] [-k KEY] [-t TOKEN_ID] [-e EXISTING_TOKEN_ID] -d DEV PIN CFG
作为第一个示例,用户可以通过向 Clevis 指定设备的 URI 来提供设备的信息:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;
serial=0a35ba26b062b9c5;token=clevis;id=%02;object=Encryption%20Key"}'
另一个选项是为 Clevis 提供配置,以便绑定 Clevis 找到的第一个 PKCS#11 设备。为此,可以提供一个空 URI,如下所示:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:"}'
与前一个相同的更短的配置命令如下所示:
$ clevis luks bind -d /dev/sda1 pkcs11 '{}'
在这种情况下,Clevis将负责检测设备,如果没有找到设备,则负责转储相应的错误。
必须澄清的是,提供空 URI 将使 Clevis 提示选择与令牌匹配的可用密钥之一,以避免意外使用不需要的密钥进行加密。
可以向 Clevis 提供模块路径,以便它使用该模块来访问设备。仅当该卡不受底层 Clevis 软件 (OpenSC) 支持时才需要这样做。因此,模块路径字段是完全可选的。要提供模块位置,用户可以向“uri”U 形夹配置提供“模块路径”:
$ clevis-luks-bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;
serial=0a35ba26b062b9c5;token=clevis;id=%02;object=Encryption%20Key?
module-path=/usr/local/lib64/libmypkcs11.so"}'
与其他设备一样,可以使用clevis luks list
命令检查已绑定到 PKCS#11 设备的加密磁盘:
$ clevis luks list -d /dev/sda1
1: pkcs11 '{"uri": "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;
serial=0a35ba26b062b9c5;token=clevis;id=%02;object=Encryption%20Key?
module-path=/usr/local/lib64/libmypkcs11.so"}'
在开发的第一阶段,Clevis 将在 OpenSC 之上使用以提供 PKCS#11 功能。 OpenSC,特别是pkcs11-tool
,提供了一个选项来指示用于解密的机制。出于测试目的,某些库(例如 SoftHSM)不支持默认的pkcs11-tool
机制,因此需要提供特定的机制来使用。因此,可以为 Clevis 提供一种使用机制,以防默认机制RSA-PKCS-OAEP
无效:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:", "mechanism":"RSA-PKCS"}'
为了检查特定令牌的可用机制,可以使用命令pkcs11-tool -M
:
$ pkcs11-tool -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
SHA-1, digest
...
SHA512, digest
MD5, digest
...
RSA-PKCS-KEY-PAIR-GEN, keySize={2048,4096}, generate_key_pair
目前,Clevis 仅支持 RSA 机制。由于其余算法的限制,没有其他非对称密码算法可以轻松地进行加密。 ECC 仅支持签名和密钥派生,但不支持加密。加密操作可以通过密钥派生以某种方式构建,但这不是一个简单的操作。
必须强调的是,RSA-PKCS 机制(PKCS#1.5 加密填充)被认为是不安全的,它主要是为了兼容性而提供的,但不建议在生产中使用它。
U 形夹将允许通过提供给 URI 的参数来指定 PKCS#11 设备所在的插槽:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:slot-id=0"}'
必须澄清的是,仅提供槽信息将使 Clevis 猜测与所选槽中的令牌匹配的可用密钥之一,这可能会导致意外地使用不需要的密钥进行加密。不建议使用 slot 作为设备选择器,因为 slot id 是一个不能保证在 PKCS#11 模块初始化过程中保持稳定的数字。但是,某些库和模块提供稳定的插槽标识符,因此它可以用于这些特殊情况。
有两个更好的选项可以区分不同的 PKCS#11 设备:
1 - 使用公钥对象的多设备配置(推荐):
从OpenSC
的最新版本(从 OpenSC 0.26.0 版本开始)开始,Clevis 使用pkcs11-tool
来处理大多数 PKCS#11 命令,PKCS#11 URI 会针对令牌和对象进行转储。特定令牌:
$ pkcs11-tool -L | grep uri
uri : pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=42facd1f749ece7f;token=clevis
uri : pkcs11:model=PKCS%2315%20emulated;manufacturer=OpenPGP%20project;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29
$ pkcs11-tool -O --slot-index 1 --type pubkey | grep uri
ising slot 0 with a present token (0x0)
uri: pkcs11:model=PKCS%2315%20emulated;manufacturer=OpenPGP%20project;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29;id=%03;object=Authentication%20key;type=public
在这种特殊情况下,当存在多个 PKCS#11 设备时,选择特定设备的公钥并将其绑定到 U 形夹:
$ clevis luks bind -d /dev/sda pkcs11 '{"uri":"pkcs11:model=PKCS%2315%20emulated;manufacturer=OpenPGP%20project;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29;id=%03;object=Authentication%20key;type=public"}'
如果您使用模块路径,则必须使用提供 --module 选项时返回的路径:
$ pkcs11-tool --module /usr/lib64/libykcs11.so -O --type pubkey | grep uri
/usr/local/bin/pkcs11-tool.manual --module /usr/lib64/libykcs11.so -O --type pubkey | grep uri
Using slot 0 with a present token (0x0)
uri: pkcs11:model=YubiKey%20YK5;manufacturer=Yubico%20%28www.yubico.com%29;serial=28083311;token=YubiKey%20PIV%20%2328083311;id=%03;object=Public%20key%20for%20Key%20Management;type=public
uri: pkcs11:model=YubiKey%20YK5;manufacturer=Yubico%20%28www.yubico.com%29;serial=28083311;token=YubiKey%20PIV%20%2328083311;id=%19;object=Public%20key%20for%20PIV%20Attestation;type=public
$ clevis luks bind -d /dev/sda pkcs11 '{"uri":"pkcs11:model=YubiKey%20YK5;manufacturer=Yubico%20%28www.yubico.com%29;serial=28083311;token=YubiKey%20PIV%20%2328083311;id=%03;object=Public%20key%20for%20Key%20Management;type=public;module-path=/usr/lib64/libykcs11.so"}'
2 - 具有串行+令牌规范的多设备配置:
对于pkcs11-tool
不转储令牌/对象的 URI 的版本,U 形夹将使用设备serial
+ token label
对“尝试”特定标识。在这种类型的场景中,可以使用这两个参数执行识别,但也应提供model
以便在询问 PIN 时方便 U 形夹告知设备:
# pkcs11-tool -L | grep "token label|serial"
token label : OpenPGP card (User PIN)
serial num : 42facd1f749ece7f
$ clevis luks bind -d /dev/sda pkcs11 '{"uri":"pkcs11:model=PKCS%2315%20emulated;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29"}'
请记住,特殊字符必须以百分比模式定义,如 RFC 7512:PKCS#11 URI 方案中所定义。
要安装和配置 U 形夹 PKCS#11 功能,必须遵循以下步骤:
1 - 安装 Clevis 所需的依赖项,包括 PKCS#11 依赖项:
$ sudo dnf install -y opensc pcsc-lite openssl socat
2 - PKCS11 设备必须可通过“pkcs11-tool”访问:
$ pkcs11-tool -L
pkcs11-tool -L
Available slots:
Slot 0 (0x0): Yubico YubiKey OTP+CCID 00 00
token label : clevis
...
uri : pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=42facd1f749ece7f;token=clevis
3 - 配置设备以与 U 形夹绑定:
$ sudo clevis luks bind -d /dev/sda5 pkcs11 '{"uri":"pkcs11:"}'
如果需要提供要使用的模块,可以通过module-path
URI 参数来完成:
$ sudo clevis luks bind -d /dev/sda5 pkcs11 '{"uri":"pkcs11:module-path=/usr/lib64/libykcs11.so.2"}'
4 - 启用 clevis-luks-pkcs11-askpass.socket 单元:
$ sudo systemctl enable --now clevis-luks-pkcs11-askpass.socket
5 - /etc/crypttab 配置:
为了使 PKCS#11 功能正常工作,必须配置/etc/crypttab
文件,以便 systemd 使用 AF_UNIX 套接字等待解锁磁盘的关键短语,而不是通过控制台提示它。
Clevis PKCS#11 单元文件将在路径/run/systemd/clevis-pkcs11.sock
中配置一个套接字来发送和接收有关磁盘解锁的信息。对于将通过 PKCS#11 U 形销解锁的磁盘,必须将该套接字文件配置为密钥文件。因此,必须在/etc/crypttab
中引入下一个更改才能进行解锁:
$ sudo diff -Nuar /etc/crypttab.ori /etc/crypttab
--- /etc/crypttab.ori 2024-07-04 10:46:16.295073739 +0200
+++ /etc/crypttab 2024-07-03 17:14:27.764743860 +0200
@@ -1 +1,2 @@
-luks-6e38d5e1-7f83-43cc-819a-7416bcbf9f84 UUID=6e38d5e1-7f83-43cc-819a-7416bcbf9f84 - -
+luks-6e38d5e1-7f83-43cc-819a-7416bcbf9f84 UUID=6e38d5e1-7f83-43cc-819a-7416bcbf9f84 /run/systemd/clevis-pkcs11.sock keyfile-timeout=30s
强烈建议设置keyfile-timeout
选项来配置失败机制,以防发生某些解锁错误并且需要通过控制台手动输入密码。
6 - 重新启动并测试:
系统应启动并询问 PKCS#11 设备 PIN,只有在 PIN 正确的情况下才解密相应配置的加密磁盘。
7 - 如果不需要测试启动过程,请使用下一个命令进行加密和解密(请注意,必须提供 PIN 值才能正常工作),并检查是否可以使用此单行代码执行字符串的加密/解密,并且不会发生错误:
$ echo "top secret" | clevis encrypt pkcs11 '{"uri":"pkcs11:module-path=/usr/lib64/libykcs11.so.2?pin-value=123456"}' | clevis decrypt
应返回top secret
字符串
U 形夹提供了一种将引脚混合在一起以提供复杂的解锁策略的方法。这是通过使用称为 Shamir 秘密共享 (SSS) 的算法来完成的。
SSS 是一种阈值方案。它创建一个密钥并将其分成多个部分。每个部分都使用另一个密码进行加密(甚至可能递归地使用 SSS)。此外,您还定义阈值t
。如果至少可以解密t
块,则可以恢复加密密钥并且解密可以成功。
以下是我们将 SSS 引脚与 Tang 和 TPM2 引脚一起使用的示例:
$ echo hi | clevis encrypt sss
' {"t": 2, "pins": {"tpm2": {"pcr_ids": "0"}, "tang": {"url": "http://tang.local"}}} '
> hi.jwe
在上面的示例中,我们定义了两个子引脚,阈值为 2。这意味着在解密过程中,两个子引脚都必须成功,SSS 本身才能成功。
这是我们仅使用唐针的另一个示例:
$ echo hi | clevis encrypt sss
' {"t": 1, "pins": {"tang": [{"url": "http://server1.local/key"}, {"url": "http://server2.local/key"}]}} '
> hi.jwe
在此示例中,我们定义了 Tang 引脚的两个子实例 - 每个实例都有自己的配置。由于我们的阈值为 1,因此如果任何一个Tang pin 实例在解密过程中成功,SSS 就会成功。
U 形夹可用于使用引脚绑定 LUKS 卷,以便它可以自动解锁。
它的工作原理相当简单。我们生成一个新的、加密强度高的密钥。此密钥作为附加密码添加到 LUKS。然后,我们使用 U 形夹加密该密钥,并使用 LUKSMeta 将输出 JWE 存储在 LUKS 标头内。
以下是我们使用 Tang 引脚绑定/dev/sda1
的示例:
$ sudo clevis luks bind -d /dev/sda1 tang ' {"url": "http://tang.local"} '
The advertisement is signed with the following keys:
kWwirxc5PhkFIH0yE28nc-EvjDY
Do you wish to trust the advertisement ? [yN] y
Enter existing LUKS password:
成功完成此绑定过程后,可以使用提供的解锁器之一解锁磁盘。
如果您想使用基于网络的解锁,则需要指定rd.neednet=1
作为内核参数,或者在使用 dracut 创建时使用--hostonly-cmdline
。
如果您使用带有 TLS 的Tang (例如: '{"url": "https://tang.remote"}'
),文件夹/etc/ssl
应包含在 initramfs 映像中, --include /etc/ssl /etc/ssl --force
使用 dracut 创建时强制。
Dracut 解锁程序尝试在早期启动期间自动解锁卷。这允许自动根卷加密。启用 Dracut 解锁器非常简单。安装 Clevis 后只需重建 initramfs:
$ sudo dracut -f
重新启动后,系统将提示您使用密码解锁卷。在后台,U 形夹将尝试自动解锁该卷。如果成功,密码提示将被取消,引导将继续。
当将 Clevis 与 initramfs-tools 一起使用时,为了重建 initramfs,您需要运行:
sudo update-initramfs -u -k ' all '
重新启动后,它的行为就像使用 Dracut 一样。
我们的 UDisks2 解锁器在您的桌面会话中运行。您不需要手动启用它;只需安装 Clevis UDisks2 解锁器并重新启动桌面会话即可。解锁器应该自动启动。
该解锁器的工作原理与 Dracut 解锁器几乎完全相同。如果您插入已与 U 型夹绑定的可移动存储设备,我们将在桌面密码提示的同时尝试自动解锁它。如果自动解锁成功,密码提示将消失,无需用户干预。
绑定到 U 形夹策略的 LUKS 设备也可以使用 clevis luks 解锁命令解锁。
$ sudo clevis luks unlock -d /dev/sda1
可以使用 clevis luks unbind 命令取消绑定 LUKS 卷。例如:
$ sudo clevis luks unbind -d /dev/sda1 -s 1
可以使用 clevis luks list 命令列出绑定到给定 LUKS 卷的引脚。例如:
$ sudo clevis luks list -d /dev/sda1
请不要直接安装U形夹。相反,请使用您首选发行版的软件包。
此命令分别安装核心 U 形夹命令、Dracut 解锁器和 UDisks2 解锁器。
$ sudo dnf install clevis clevis-dracut clevis-udisks2
正如上一节所述,建议不要直接安装U形夹。但是,如果您的 Linux 发行版不存在 Clevis 软件包,则手动编译和安装 Clevis 的步骤如下:
$ wget https://github.com/latchset/clevis/releases/download/v21/clevis-21.tar.xz
$ tar Jxvf clevis-21.tar.xz
$ cd clevis-21
$ mkdir build
$ cd build
meson
来设置编译: $ meson setup ..
ninja
命令编译: $ ninja
ninja install
命令安装(您需要 root 权限): $ sudo ninja install