使用单个密码在启动时解锁多个加密磁盘

dou*_*lep 37 linux cryptsetup disk-encryption

我的机器有一个 SSD,我在其中安装了系统和一个 HDD,我将其用作大文件和/或不常使用的文件的存储。两者都是加密的,但我选择对它们使用相同的密码。SSD 安装在 at/和 HDD at /usr/hdd(每个用户都有一个目录,可以从主目录中根据需要进行符号链接)。

当系统启动时,它会立即询问 SSD 的密码,几秒钟后为 HDD 询问密码(它是自动安装的)。鉴于两个密码短语相同,有没有办法将系统配置为只询问一次?

seb*_*sth 41

基于 Debian 的发行版:

Debian 和 Ubuntu 提供了一个带有cryptsetup包的密码缓存脚本decrypt_keyctl。

decrypt_keyctl脚本为多个加密的 LUKS 目标提供相同的密码,从而避免您多次输入密码。它可以在crypttab 中使用keyscript=decrypt_keyctl选项启用。相同的密码用于在keyfile 字段中具有相同标识符的目标。每个标识符的启动密码都会被询问一次。

一个示例crypttab:

<target>      <source>         <keyfile>      <options>
part1_crypt   /dev/disk/...    crypt_disks    luks,keyscript=decrypt_keyctl
part2_crypt   /dev/disk/...    crypt_disks    luks,keyscript=decrypt_keyctl
Run Code Online (Sandbox Code Playgroud)

该decrypt_keyctl脚本取决于keyutils包(仅建议使用,因此不一定安装)。

更新cryptab 后,您还必须更新 initramfs 以应用更改。使用update-initramfs -u.

Decrypt_keyctl 的完整自述文件位于 /usr/share/doc/cryptsetup/README.keyctl

不幸的是,由于错误(其他 init 系统应该不受影响),这目前在使用 systemd init 的 Debian 系统上不起作用。由于这个错误,systemd 再次要求您输入密码,因此无法通过 ssh 远程解锁。Debian crypttab 手册页建议作为一种解决方法,initramfs在启动的 initramfs 阶段使用选项强制处理。因此,为了规避此错误,以 Debian 中的 /etc/crypttab 为例

<target>      <source>         <keyfile>      <options>
part1_crypt   /dev/disk/...    crypt_disks    luks,initramfs,keyscript=decrypt_keyctl
part2_crypt   /dev/disk/...    crypt_disks    luks,initramfs,keyscript=decrypt_keyctl
Run Code Online (Sandbox Code Playgroud)

不提供decrypt_keyctl脚本的发行版:

如果您的发行版未提供decrypt_keyctrl,则可以使用加密的根文件系统中的密钥文件来解锁设备。当根文件系统可以在任何其他加密设备之前解锁和安装时。

LUKS 支持多个键槽。这允许您在密钥文件不可用/丢失时使用密码来解锁设备。

  1. 使用随机数据生成密钥并将其权限设置为所有者可读,以避免泄漏。请注意,密钥文件需要位于首先解锁的根分区上。

     dd if=/dev/urandom of=<path to key file> bs=1024 count=1
     chmod u=rw,g=,o= <path to key file>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将密钥添加到您的 LUKS 设备

     cryptsetup luksAddKey <path to encrypted device> <path to key file>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 配置crypttab以使用密钥文件。第一行应该是根设备,因为设备的解锁顺序与crypttab 中列出的顺序相同。对密钥文件使用绝对路径。

     <target>      <source>         <keyfile>                  <options>
     root_crypt    /dev/disk/...    none                       luks
     part1_crypt   /dev/disk/...    <path to key file>         luks
    
    Run Code Online (Sandbox Code Playgroud)

  • 呃,抱歉,现在我更加关注 `update-initramfs` 所说的内容,我注意到了这一点:`E: /usr/share/initramfs-tools/hooks/cryptkeyctl failed with return 1.`。经过一番谷歌搜索,我发现我可能需要`keyutils` 包(确实没有安装)。现在`update-initramfs` 成功并且`lsinitramfs` 确实提到了`decrypt_keytls`。将在下次启动后更新(可能明天)。 (3认同)
  • 要查看 initramfs 包含的内容:`lsinitramfs /boot/initrd.img-$(uname -r)` (2认同)
  • 在 Linux Mint 19(基于 Ubuntu 18.04)中尝试:只需在 `/etc/crypttab` 中为两个设备设置相同的密码就足以让系统在启动时只要求输入一次密码。但是一旦我将第二个设备作为新的 PV 添加到根 LV(使用 LVM),系统开始在启动时要求两次相同的密码(可能是因为在两个设备都解锁之前它无法再读取根分区? )。使用 `decrypt_keyctl` 就可以了,所以必须同时修复提到的 systemd 错误。 (2认同)

Jan*_*nis 5

另一种选择是使用/lib/cryptsetup/scripts/decrypt_derived脚本,它也是 Debian/Ubuntu 中 cryptsetup 的一部分。

您可以使用一个磁盘的卷密钥作为第二个磁盘的附加密码,而不是缓存密钥。这需要向第二个(和第三个等)加密磁盘添加第二个密码,但 LUKS 支持这一点。因此,如果您的多个加密磁盘不使用相同的密码,此解决方案也适用。

将密钥从 sda6crypt 添加到 sda5 的示例:

添加 sda6crypt 的卷密钥作为 sda5 的附加密码:

mkfifo fifo
/lib/cryptsetup/scripts/decrypt_derived sda6crypt > fifo &
cryptsetup luksAddKey /dev/sda5 fifo
rm fifo
Run Code Online (Sandbox Code Playgroud)

配置sda5crypt自动解锁/etc/crypttab

ls -la /dev/disk/by-uuid/ | grep sda5
echo "sda5crypt UUID=<uuid> sda6crypt luks,initramfs,keyscript=/lib/cryptsetup/scripts/decrypt_derived" >> /etc/crypttab
Run Code Online (Sandbox Code Playgroud)

这使用命名管道 ( fifo) 来传递密钥,以避免将卷密钥存储在磁盘上的临时文件中。

该选项仅在由 Debian 原始 cryptsetup 工具处理keyscript时才有效,systemd 重新实现当前不支持它。crypttab如果您的系统使用 systemd(这是大多数系统),则需要initramfs在 systemd 启动之前选择通过 cryptsetup 工具强制在 initrd 中进行处理。

基于https://unix.stackexchange.com/a/32551/50793