dm-crypt/Specialties

来自 ArchWiki

保护未加密的启动分区

即使在加密根目录配置中,/boot 分区和 主引导记录也是磁盘上两个未加密的区域。 它们通常无法加密,因为 启动引导程序 和 BIOS(分别是)无法解锁 dm-crypt 容器以继续启动过程。 GRUB 是一个例外,它获得了解锁 LUKS 加密的 /boot 分区的功能 - 请参阅 dm-crypt/Encrypting an entire system#加密启动分区 (GRUB)

本节介绍可以采取哪些步骤来使启动过程更加安全。

警告: 请注意,保护 /boot 分区和 MBR 可以缓解启动过程中发生的许多攻击,但以这种方式配置的系统仍然可能容易受到 BIOS/UEFI/固件篡改、硬件键盘记录器、冷启动攻击以及超出本文范围的许多其他威胁的攻击。 有关系统信任问题以及这些问题与全盘加密之间关系的概述,请参阅 [1]
注意: 当使用 UEFI 时,如果例如使用 统一内核镜像,则只需要 ESP 保持未加密。 然后,您可以使用 安全启动 来确保启动链没有被篡改,这是一种实现与以下方法相同结果的简便方法。 请参阅 dm-crypt/Encrypting an entire system#在带有 TPM2 和安全启动的分区上使用 LUKS

从可移动设备启动

使用单独的设备来启动系统是一个相当简单的过程,并且可以显著提高针对某些类型攻击的安全性。 采用 加密根文件系统 的系统的两个脆弱部分是

这些必须以未加密的方式存储,系统才能启动。 为了保护这些组件免受篡改,建议将它们存储在可移动介质上,例如 USB 驱动器,并从该驱动器而不是硬盘启动。 只要您始终随身携带该驱动器,就可以确定这些组件没有被篡改,从而在解锁系统时使身份验证更加安全。

假定您已经将系统配置为在 /boot 上挂载专用分区。 如果您没有,请按照 dm-crypt/System configuration#内核参数 中的步骤操作,将您的硬盘替换为可移动驱动器。

注意: 您必须确保您的系统支持从所选介质启动,无论是 USB 驱动器、外部硬盘驱动器、SD 卡还是任何其他设备。

准备可移动驱动器 (/dev/sdx)。

# gdisk /dev/sdx #format if necessary. Alternatively, cgdisk, fdisk, cfdisk, gparted...
# mkfs.ext2 /dev/sdx1 #for BIOS systems
# mkfs.fat -F 32 /dev/sdx1 #for UEFI systems
# mount /dev/sdx1 /mnt

将您现有的 /boot 内容复制到新驱动器。

# cp -ai /boot/* /mnt/

挂载新分区。 不要忘记相应地更新您的 fstab 文件。

# umount /boot
# umount /mnt
# mount /dev/sdx1 /boot
# genfstab -p -U / > /etc/fstab

更新 GRUBgrub-mkconfig 应该会自动检测到新的分区 UUID,但自定义菜单条目可能需要手动更新。

# grub-mkconfig -o /boot/grub/grub.cfg
# grub-install /dev/sdx #install to the removable device, not the hard disk. for BIOS systems
# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub #for UEFI systems

重启并测试新配置。 记住在 BIOS 或 UEFI 中相应地设置您的设备启动顺序。 如果系统无法启动,您仍然应该能够从硬盘启动以纠正问题。

chkboot

警告: chkboot 使 /boot 分区成为防篡改的,而不是防篡改的。 当 chkboot 脚本运行时,您已经将密码输入到可能被入侵的启动引导程序、内核或 initrd 中。 如果您的系统未通过 chkboot 完整性测试,则无法对数据的安全性做出任何假设。

参考 ct-magazine 的一篇文章(2012 年 3 月 12 日第 3 期,第 146 页,[2]),以下脚本检查 /boot 下的文件是否更改了 SHA-1 哈希值、inode 和硬盘上占用的块。 它还会检查 主引导记录。 该脚本无法阻止某些类型的攻击,但使很多攻击变得更加困难。 脚本本身的任何配置都不会存储在未加密的 /boot 中。 对于已锁定/断电的加密系统,这使得某些攻击者更难下手,因为它不明显分区在启动时会进行自动校验和比较。 但是,预料到这些预防措施的攻击者可以操纵固件以在其内核之上运行自己的代码并拦截文件系统访问,例如 boot,并呈现未被篡改的文件。 通常,低于固件级别的任何安全措施都无法保证信任和防篡改证据。

带有安装说明的脚本 可用(作者:Juergen Schmidt,ju at heisec.de;许可证:GPLv2)。 还有软件包 chkbootAUR 用于安装。 建议使用 AUR 软件包,因为它具有其他有用的脚本。

Juergen Schmidt 的脚本

由于 /usr/local/bin/chkboot_user.sh 需要在登录后立即执行,因此您需要将其添加到 自启动 中(例如,在 KDE 下 -> 系统设置 -> 启动和关闭 -> 自启动;GNOME 3:gnome-session-properties)。

对于 Arch Linux,/boot 的更改非常频繁,例如新内核的滚动更新。 因此,在每次完整系统更新时使用脚本可能会有所帮助。 一种方法是这样做

#!/bin/sh
#
# Note: Insert your <user> and execute it with sudo for pacman & chkboot to work automagically
#
echo "Pacman update [1] Quickcheck before updating" &
sudo -u <user> /usr/local/bin/chkboot_user.sh
/usr/local/bin/chkboot.sh
sudo -u <user> /usr/local/bin/chkboot_user.sh
echo "Pacman update [2] Syncing repos for pacman"
pacman -Syu
/usr/local/bin/chkboot.sh
sudo -u <user> /usr/local/bin/chkboot_user.sh
echo "Pacman update [3] All done, let us roll on ..."

AUR 软件包

安装后,启用 chkboot.service

您可能需要将 chkboot 添加到 mkinitcpio hooks 的末尾,以便在 mkinitcpio 重新生成 initramfs 时更新您的 chkboot 哈希值。 您可以通过将 chkboot 添加到 /etc/mkinitcpio.conf 中的 HOOKS 数组的末尾来执行此操作。

AUR 软件包还附带一个 chkboot-desktopalert 脚本,如果检测到 /boot 更改,该脚本将导致弹出一个图形窗口并发出警告。 您可以通过将其添加到图形环境的启动脚本来使用此脚本。

mkinitcpio-chkcryptoboot

警告: 此 hook 加密 GRUB 的核心 (MBR) 代码或 EFI stub,也不防止攻击者能够修改启动引导程序的行为以在运行时危害内核和/或 initramfs 的情况。

mkinitcpio-chkcryptobootAUR 是一个 mkinitcpio hook,它在早期用户空间执行完整性检查,并建议用户在系统似乎已被入侵时不要输入其根分区密码。 安全性是通过 加密启动分区 实现的,该分区使用 GRUBcryptodisk.mod 模块解锁,以及使用与前者不同的密码加密的根文件系统分区。 这样,initramfs内核 受到保护,免受离线篡改,即使在被入侵的机器上输入了 /boot 分区密码,根分区也可以保持安全(前提是 chkcryptoboot hook 检测到入侵,并且它本身在运行时没有被入侵)。

此 hook 需要 grub 版本 >=2.00 才能运行,并且需要专用的 LUKS 加密 /boot 分区及其自己的密码才能安全。

安装

安装 mkinitcpio-chkcryptobootAUR 并编辑 /etc/default/chkcryptoboot.conf。 如果您希望能够检测到您的启动分区是否被绕过,请编辑 CMDLINE_NAMECMDLINE_VALUE 变量,并使用只有您知道的值。 您可以按照安装后建议的建议使用两个哈希值。 此外,请务必对 /etc/default/grub 中的 内核命令行 进行适当的更改。 编辑 /etc/mkinitcpio.conf 中的 HOOKS= 行,并在 encrypt之前插入 chkcryptoboot hook。 完成后,重新生成 initramfs

技术概述

mkinitcpio-chkcryptobootAUR 由 mkinitcpio 的安装 hook 和运行时 hook 组成。 安装 hook 在每次重建 initramfs 时运行,并哈希 GRUB EFI stub ($esp/EFI/grub_uefi/grubx64.efi)(在 UEFI 系统的情况下)或安装 GRUB 的磁盘的前 446 个字节(在 BIOS 系统的情况下),并将该哈希值存储在加密的 /boot 分区内的 initramfs 中。 当系统启动时,GRUB 会提示输入 /boot 密码,然后运行时 hook 执行相同的哈希操作,并在提示输入根分区密码之前比较生成的哈希值。 如果它们不匹配,hook 将打印如下错误

CHKCRYPTOBOOT ALERT!
CHANGES HAVE BEEN DETECTED IN YOUR BOOT LOADER EFISTUB!
YOU ARE STRONGLY ADVISED NOT TO ENTER YOUR ROOT CONTAINER PASSWORD!
Please type uppercase yes to continue:

除了哈希启动引导程序之外,hook 还根据 /etc/default/chkcryptoboot.conf 中配置的参数检查正在运行的内核的参数。 这会在运行时和启动过程完成后进行检查。 这允许 hook 检测 GRUB 的配置是否在运行时被绕过,并在之后检测整个 /boot 分区是否未被绕过。

对于 BIOS 系统,hook 会创建 GRUB 第一阶段启动引导程序(安装到启动设备的前 446 个字节)的哈希值,以便在后续启动过程中进行比较。 不会检查主要的第二阶段 GRUB 启动引导程序 core.img

AIDE

除了上述脚本之外,还可以使用 AIDE 设置哈希检查,可以通过非常灵活的配置文件对其进行自定义。

STARK

虽然这些方法之一应该可以满足大多数用户的目的,但它们并未解决与未加密的 /boot 关联的所有安全问题。 一种努力提供完全身份验证的启动链的方法是使用 POTTS 作为学术论文发布,以实现 STARK 身份验证框架。

POTTS 概念验证使用 Arch Linux 作为基本发行版,并实现了具有以下内容的系统启动链

  • POTTS - 用于一次性身份验证消息提示的启动菜单
  • TrustedGrub - GRUB Legacy 实现,它根据 TPM 芯片 PCR 寄存器验证内核和 initramfs
  • TRESOR - 一个内核补丁,它实现了 AES,但在运行时将主密钥保存在 CPU 寄存器中而不是 RAM 中。

作为论文的一部分,发布了基于 Arch Linux(截至 2013-01 的 ISO)的 安装 说明。 如果您想尝试,请注意这些工具不在标准存储库中,并且维护该解决方案将非常耗时。

使用 GPG、LUKS 或 OpenSSL 加密密钥文件

以下论坛帖子提供了使用双因素身份验证、gpg 或 openssl 加密密钥文件而不是本 wiki 文章中前面描述的纯文本密钥文件的说明 使用 GPG 加密密钥的 LUKS 系统加密

请注意

  • 您可以按照上述说明进行操作,只需两个主分区,一个启动分区(由于加密而需要)和一个主 LVM 分区。 在 LVM 分区中,您可以根据需要拥有任意数量的分区,但最重要的是,它应至少包含根目录、交换分区和 home 逻辑卷分区。 这具有以下额外好处:所有分区只有一个密钥文件,并且能够休眠您的计算机(挂起到磁盘),其中交换分区已加密。 如果您决定这样做,则 /etc/mkinitcpio.conf 中的 hooks 应如下所示
    HOOKS=( ... usb usbinput (etwo or ssldec) encrypt (if using openssl) lvm2 resume ... )
    您应该添加
    resume=/dev/<VolumeGroupName>/<LVNameOfSwap>
    到您的 内核参数
  • 如果您需要临时将未加密的密钥文件存储在某个位置,请不要将其存储在未加密的磁盘上。 更好的是,确保将其存储到 RAM 中,例如 /dev/shm
  • 如果您想使用 GPG 加密密钥文件,则需要使用静态编译的 GnuPG 版本 1.4,或者您可以编辑 hooks 并使用 gnupg1AUR
  • OpenSSL 的更新可能会破坏第二个论坛帖子中提到的自定义 ssldec

远程解锁 root(或其他)分区

想象一下一个系统,其中包含一个或多个 LUKS 加密分区(根分区或其他分区)或卷,您需要在启动期间解锁这些分区/卷。 在这种情况下,您需要能够远程登录并在早期启动阶段提供密码。 这可以通过使用一个或多个 mkinitcpio hook 来实现,这些 hook 配置网络接口并启动某种 SSH 服务器。 下面列出的某些软件包贡献了各种 mkinitcpio 构建 hooks,以简化配置。 以下教程除了现有的本地控制台密码提示之外,还添加了远程解锁方法。

注意
  • 请记住对网络接口使用内核设备名称(例如 eth0)而不是 udev 的名称(例如 enp1s0),因为这些名称将不起作用。
  • 默认情况下,可预测网络接口名称已激活,并在后期启动期间更改内核设备名称。 使用 dmesg 并查找您的网络内核模块的作用,以查找原始名称(例如 eth0
  • 可能需要将您的 以太网无线 网卡的模块添加到 MODULES 数组中。

基于 Busybox 的 initramfs(使用 mkinitcpio 构建)

对于基于 busybox 的 initramfs,软件包 mkinitcpio-netconf 和/或 mkinitcpio-pppAUR 提供网络连接。 作为 SSH 服务器,您可以选择使用 mkinitcpio-dropbearmkinitcpio-tinyssh。 这些 hooks 不安装任何 shell,因此您还需要 安装 mkinitcpio-utils 软件包。 以下说明可用于上述软件包的任何组合。 当有不同的路径时,将会注明。

  1. 如果您还没有 SSH 密钥对,请在客户端系统(将用于解锁远程计算机的系统)上生成一个
    注意
    • tinyssh 仅支持没有密码的 Ed25519ECDSA 密钥类型。 如果您选择使用 mkinitcpio-tinyssh,则需要创建/使用其中一种。
    • 版本 0.0.3-5 中的 mkinitcpio-dropbear 与当前的 dropbear 实现不兼容,后者移除了 dss。 请参阅 Github 了解详细信息和修复方法。
  2. 将您的 SSH 公钥(即您通常放在主机上的公钥,以便您可以在没有密码的情况下 ssh 登录,或者您刚刚创建的以 .pub 结尾的公钥)插入到远程计算机的 /etc/dropbear/root_key/etc/tinyssh/root_key 文件中。
    提示: 此方法稍后可用于根据需要添加其他 SSH 公钥; 如果只是复制远程计算机的 ~/.ssh/authorized_keys 的内容,请务必验证它是否仅包含您打算用于解锁远程计算机的密钥。 添加其他密钥时,也请使用 mkinitcpio 重新生成您的 initrd。 另请参阅 OpenSSH#保护
  3. /etc/mkinitcpio.conf 中的 "HOOKS" 数组中的 filesystems 之前,添加所有三个 <netconf 和/或 ppp> <dropbear 或 tinyssh> encryptssh hooksencryptssh 替换 encrypt hook)。 然后 重新生成 initramfs
    注意: 不需要 mkinitcpio-nfs-utils 提供的 net hook。
  4. 配置所需的 cryptdevice= 参数,并将 ip= 内核命令参数 添加到您的启动引导程序配置中,并带有适当的参数。 例如,如果您希望 IP 地址由 DHCP 分配,则可以使用以下参数
    ip=dhcp
    如果您的 DHCP 服务器配置为始终为此主机分配相同的 IP,这将非常有用,否则通过 SSH 访问系统将会很困难。 在这种情况下,您可以使用静态 IP
    ip=192.168.1.1:::::eth0:none
    或者,您还可以指定网络所需的子网掩码和网关
    ip=192.168.1.1::192.168.1.254:255.255.255.0::eth0:none
    注意:mkinitcpio-netconf 的 0.0.4 版本开始,您可以嵌套多个 ip= 参数以配置多个接口。 您不能将其与单独的 ip=dhcp (ip=:::::eth0:dhcp) 混合使用。 需要指定接口。
    ip=ip=192.168.1.1:::::eth0:none:ip=172.16.1.1:::::eth1:none
    如果使用 DHCP,请考虑添加 netconf_timeout= 内核参数,以防止 netconf 永远尝试获取 IP。 有关 ip= 参数的详细说明,请查看 相应的 mkinitcpio 部分。 完成后,更新您的 启动引导程序 的配置。
  5. 最后,重新启动远程系统并尝试 ssh 登录明确声明 "root" 用户名(即使 root 帐户在计算机上被禁用,此 root 用户也仅在 initrd 中用于解锁远程系统)。 如果您使用的是 mkinitcpio-dropbear 软件包,并且您还安装了 openssh 软件包,那么您在登录前可能不会收到任何警告,因为它会转换并使用 openssh 使用的相同主机密钥(Ed25519 密钥除外,因为 dropbear 不支持它们)。 如果您使用的是 mkinitcpio-tinyssh,则捆绑了一个脚本 tinyssh-convert,因此您可以使用与 openssh 安装相同的密钥(目前仅限 Ed25519 密钥)。 可能需要通过 tinyssh-convert 手动将主机密钥复制到 /etc/tinyssh/sshkeydir。 在任何一种情况下,您都应该至少运行一次 ssh 守护程序,使用提供的 systemd 单元,以便首先生成密钥。 重新启动计算机并通过 ssh 连接后,系统应提示您输入密码以解锁设备,之后系统将完成其启动过程,然后您可以 像往常一样 ssh 登录(使用您选择的远程用户)。

启用 Wi-Fi

netconf hook 通常与以太网连接一起使用。 如果您想设置一台仅使用无线的计算机,并通过 Wi-Fi 解锁它,则可以使用预定义的 hook 或创建自定义 hook 以在运行 netconf hook 之前连接到 Wi-Fi 网络。

预定义 hook

您可以根据本 wiki 中的 hook 安装预定义的 hook

  1. 安装 mkinitcpio-wifiAUR
  2. 通过使用您的网络属性创建 wpa_supplicant 配置来配置您的 Wi-Fi 连接
    wpa_passphrase "ESSID" "passphrase" > /etc/wpa_supplicant/initcpio.conf
  3. 在您的 /etc/mkinitcpio.conf 中,在 netconf 之前添加 wifi hook。 您的 Wi-Fi 相关模块应自动检测到,如果未检测到:将其添加到 MODULES 部分。
  4. ip=:::::wlan0:dhcp 添加到 内核参数
  5. 重新生成 initramfs.
  6. 更新您的 启动引导程序 的配置。
自定义 hook

以下示例显示了使用 USB Wi-Fi 适配器,连接到受 WPA2-PSK 保护的 Wi-Fi 网络的设置。 如果您使用例如 WEP 或其他 initramfs 生成器,则可能需要进行相应调整。

  1. 修改 /etc/mkinitcpio.conf
    • 为您的特定 Wi-Fi 适配器添加所需的内核模块。
    • 包含 wpa_passphrasewpa_supplicant 二进制文件。
    • net hook 之前添加一个 hook wifi(或您选择的名称,这将是创建的自定义 hook)。
      MODULES=(module)
      BINARIES=(wpa_passphrase wpa_supplicant)
      HOOKS=(base udev autodetect ... wifi net ... dropbear encryptssh ...)
  2. /etc/initcpio/hooks/wifi 中创建 wifi hook
    run_hook ()
    {
    # Sleep a couple of seconds so wlan0 is setup by kernel
    sleep 5

    # Set wlan0 to up
    ip link set wlan0 up

    # Associate with Wi-Fi network
    # 1. Save temp config file
    wpa_passphrase "network ESSID" "pass phrase" > /tmp/wifi

    # 2. Associate
    wpa_supplicant -B -D nl80211,wext -i wlan0 -c /tmp/wifi

    # Sleep a couple of seconds so that wpa_supplicant finishes connecting
    sleep 5

    # wlan0 should now be connected and ready to be assigned an ip by the net hook
    }

    run_cleanuphook ()
    {
    # Kill wpa_supplicant running in the background
    killall wpa_supplicant

    # Set wlan0 link down
    ip link set wlan0 down

    # wlan0 should now be fully disconnected from the Wi-Fi network
    }
  3. /etc/initcpio/install/wifi 中创建 hook 安装文件
    build ()
    {
    add_runscript
    }
    help ()
    {
    cat<<HELPEOF
    Enables Wi-Fi on boot, for dropbear ssh unlocking of disk.
    HELPEOF
    }
  4. ip=:::::wlan0:dhcp 添加到 内核参数。 删除 ip=:::::eth0:dhcp,以免冲突。
  5. 可以选择使用内核参数 ip=:::::eth0:dhcp 创建一个额外的启动条目。
  6. 重新生成 initramfs.
  7. 更新您的 启动引导程序 的配置。

记住设置 Wi-Fi,以便您能够在系统完全启动后登录。 如果您无法连接到 Wi-Fi 网络,请尝试稍微增加睡眠时间。

基于 systemd 的 initramfs(使用 mkinitcpio 构建)

对于基于 systemd 的 initramfs,AUR 软件包 mkinitcpio-systemd-extrasAUR 提供了一系列构建 hooks(又名安装 hooks),以在早期启动期间实现网络连接和 SSH 登录。 根据具体设置,这要么让您可以通过 busybox 的 dash 访问 initramfs 环境,要么只是密码提示。

最小设置

/etc/mkinitcpio.conf
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole sd-network block sd-tinyssh sd-encrypt filesystems fsck)
SD_TINYSSH_COMMAND="systemd-tty-ask-password-agent --query --watch"

当使用 mkinitcpio 构建 initramfs 时,此设置会复制主系统中已有的 systemd-networkd 配置,并尝试复制/转换现有 TinySSH 或 OpenSSH 安装中的现有 SSH 服务器密钥。 需要在主系统上安装 tinyssh(但不必启用)。 如果主系统未使用 systemd-networkd,则有其他配置参数。 有关更多详细信息,请参阅 mkinitcpio-systemd-extrasAUR文档

注意
  • 可预测的网络接口名称(例如 enp2s0)默认情况下在 initramfs 阶段不存在,因此许多 systemd-networkd 配置文件在 initramfs 阶段将无法工作。 请参阅 mkinitcpio-systemd-extras wiki 了解解决方法。
  • 本节过去曾提及 mkinitcpio-systemd-tool 作为实现早期启动期间远程登录和 LUKS 解锁的另一种替代方案。 该方法完全不同,因为它只需要一个额外的 hook systemd-tool,所有进一步的设置都在 systemd 服务文件的特殊 [X-SystemdTool] 部分中完成。 遗憾的是,关于此方法以及如何使用该工具本身的文档非常有限。

基于 systemd 的 initramfs(使用 dracut 构建)

如果你正在使用 dracut 而不是 mkinitcpio,你可能需要查看 dracut-sshd 作为上述选项的替代方案。

一次性免密码重启

另一种可用于重启远程、无头或以其他方式无法访问的系统的方法,而无需在终端输入加密的根驱动器密码,是使用临时的 密钥文件。这需要放置在内核在启动时可以访问的位置,需要 cryptkey 启动参数,并且需要通过 "cryptsetup luksAddKey" 命令将该特定密钥文件注册为有效密钥。

这可以使用 passless-bootAUR 方便地完成。在 该脚本的 readme 文件 中描述的设置该工具的步骤,也可以作为设置自制解决方案的模板。请务必查看 安全考量 部分的讨论。

固态硬盘 (SSD) 的 Discard/TRIM 支持

固态硬盘 用户应该意识到,默认情况下,设备映射器未启用 TRIM 命令,即挂载块设备时,除非您覆盖默认设置,否则不会使用 discard 选项。

设备映射器维护者已明确表示,由于潜在的安全隐患,永远不会默认在 dm-crypt 设备上启用 TRIM 支持。[3][4] 启用 TRIM 的设备可能会发生以释放的块信息形式存在的少量数据泄漏,这可能足以确定正在使用的文件系统。cryptsetup 开发人员的 博客 中提供了激活 TRIM 引起的问题的说明和讨论。如果您担心这些因素,请记住威胁可能会累积:例如,如果您的设备仍然使用之前的(cryptsetup <1.6.0)默认密码 --cipher aes-cbc-essiv 加密,则从修剪扇区观察到的信息泄漏可能比当前的 默认 更多。

以下情况可以区分

  • 设备使用默认 dm-crypt LUKS 模式加密
    • 默认情况下,LUKS 标头存储在设备的开头,使用 TRIM 有助于保护标头修改。例如,如果泄露的 LUKS 密码被撤销,在没有 TRIM 的情况下,旧标头通常仍然可以读取,直到被另一个操作覆盖;如果在此期间驱动器被盗,攻击者理论上可以找到一种方法来定位旧标头并使用它以及泄露的密码来解密内容。参见 cryptsetup FAQ,第 5.19 节,关于 SSD、闪存和混合驱动器?固态硬盘上的全盘加密
    • 如果本节顶部所述的安全问题被认为比上述要点更糟糕的威胁,则可以禁用 TRIM。
另请参阅 安全擦除磁盘#闪存
  • 设备使用 dm-crypt plain 模式加密,或者 LUKS 标头 单独存储
    • 如果需要可否认性,则绝不应使用 TRIM,因为本节顶部有相关考虑,否则会泄露加密的使用。
    • 如果不需要可否认性,则可以使用 TRIM 以获得性能提升,前提是本节顶部描述的安全风险不受关注。
警告: 在驱动器上启用 TRIM 之前,请确保设备完全支持 TRIM 命令,否则可能会发生数据丢失。请参阅 固态硬盘#TRIM

除了在 dm-crypt 中启用 discard 支持外,还需要定期运行 fstrim(8),或者在 /etc/fstab 中使用 discard 选项挂载文件系统(例如,本例中的 /dev/mapper/root)。有关详细信息,请参阅 TRIM 页面。

LUKS2

对于 LUKS2 设备,可以在打开设备时使用 --allow-discards --persistent 选项启用 TRIM 支持。allow-discards 标志将被写入 LUKS2 标头,并且每当打开 LUKS2 设备时,该选项将自动使用。

注意
  • 通过 cryptsetup --persistent 设置新的持久标志会将旧标志替换为新标志,而不是在已设置的标志中添加新标志。这意味着如果您也想启用其他标志,则必须一次性设置所有标志。
  • 当使用不带 dm-crypt 的 OPAL 加密(cryptsetup-luksFormat(8) 选项 --hw-opal-only)时,不需要启用 discard 支持,因为文件系统和磁盘之间没有 dm-crypt 层。映射的设备将始终传递 discard 请求。
# cryptsetup --allow-discards --persistent open /dev/sdaX root

如果设备已打开,则 open 操作将引发错误,在这种情况下,请改用 cryptsetup-refresh(8) 命令。

# cryptsetup --allow-discards --persistent refresh root

您可以通过查看 cryptsetup luksDump 输出确认该标志是否已持久设置在 LUKS2 标头中。

# cryptsetup luksDump /dev/sdaX | grep Flags
Flags:          allow-discards

LUKS1 和 plain dm-crypt

对于 LUKS1 和 plain dm-crypt,需要在打开设备时显式启用 TRIM 支持。

要在启动期间启用 TRIM 支持,请设置以下 内核参数

如果使用 encrypt 钩子

cryptdevice=/dev/sdaX:root:allow-discards

如果使用带有基于 systemd 的 initramfs 的 sd-encrypt 钩子

rd.luks.options=discard
注意: rd.luks.options=discard 内核选项对 initramfs 镜像的 /etc/crypttab 文件(实际根目录上的 /etc/crypttab.initramfs)中包含的设备没有任何影响。您必须在 /etc/crypttab.initramfs 中指定选项 discard

对于通过 /etc/crypttab 解锁的设备,请使用选项 discard,例如

/etc/crypttab
luks-123abcdef-etc UUID=123abcdef-etc none discard

在控制台上手动解锁设备时,请使用 --allow-discards

例如,您可以使用 --allow-discards 选项打开设备以执行手动 fstrim 命令。

# cryptsetup --allow-discards open /dev/sdaX root

在任何情况下,您都可以通过检查 dmsetup table 输出,来验证设备是否实际上已使用 discards 选项打开。

# dmsetup table
luks-123abcdef-etc: 0 1234567 crypt aes-xts-plain64 000etc000 0 8:2 4096 1 allow_discards

禁用 workqueue 以提高固态硬盘 (SSD) 性能

固态硬盘 用户应该意识到,默认情况下,设备映射器未启用丢弃内部读写 workqueue 命令,即挂载块设备时,除非您覆盖默认设置,否则不会使用 no_read_workqueueno_write_workqueue 选项。

no_read_workqueueno_write_workqueue 标志是由 Cloudflare 内部研究 加速 Linux 磁盘加密 引入的,该研究是在调查整体加密性能时进行的。结论之一是,内部 dm-crypt 读写队列降低了 SSD 驱动器的性能。虽然排队磁盘操作对于机械硬盘有意义,但绕过队列并同步写入数据使吞吐量翻倍,并将 SSD 驱动器的 IO 等待操作延迟缩减了一半。这些补丁已向上游提交,并且自 linux 5.9 及更高版本起可用 [5]

提示: linux-zen 默认禁用 dm-crypt workqueue

要为通过 crypttab 解锁的 LUKS 设备禁用 workqueue,请使用一个或多个所需的 no-read-workqueueno-write-workqueue 选项。例如

/etc/crypttab
luks-123abcdef-etc UUID=123abcdef-etc none no-read-workqueue

要禁用读写 workqueue,请添加这两个标志

/etc/crypttab
luks-123abcdef-etc UUID=123abcdef-etc none no-read-workqueue,no-write-workqueue

对于 LUKS2,您可以通过使用 --persistent 选项打开设备一次,将 --perf-no_read_workqueue--perf-no_write_workqueue 设置为设备的默认标志。例如

# cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue --persistent open /dev/sdaX root

当设备已打开时,open 操作将引发错误。在这些情况下,您可以使用 refresh 选项,例如

# cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue --persistent refresh root

您可以通过查看 cryptsetup luksDump 输出确认哪些标志持久设置在 LUKS2 标头中。

# cryptsetup luksDump /dev/sdaX | grep Flags
Flags:          no-read-workqueue

在任何情况下,您都可以通过检查 dmsetup table 输出,来验证设备是否实际上已使用这些标志打开。

# dmsetup table
luks-123abcdef-etc: 0 1234567 crypt aes-xts-plain64 000etc000 0 8:2 4096 1 no_read_workqueue
注意: 通过 cryptsetup --persistent 设置新的持久标志会将旧标志替换为新标志,而不是在已设置的标志中添加新标志。这意味着如果您想同时启用 --perf-no_read_workqueue--perf-no_write_workqueue(或更多),则必须一次性设置所有标志。

使用 cryptsetup 设置 no_read_workqueueno_write_workqueue 的示例

# cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue --persistent refresh root

您可以通过检查 LUKS2 cryptsetup luksDump 输出确认这两个标志都已设置。

# cryptsetup luksDump /dev/sdaX | grep Flags
Flags:          no-read-workqueue no-write-workqueue

encrypt 钩子和多个磁盘

注意: 本节仅涉及在早期用户空间(initramfs 阶段)中解锁。对于在后期用户空间(切换根目录后)中解锁设备,请参阅 dm-crypt/系统配置#在后期用户空间中解锁
提示: sd-encrypt 钩子支持解锁多个设备。它们可以在内核命令行或 /etc/crypttab.initramfs 中指定。请参阅 dm-crypt/系统配置#使用 systemd-cryptsetup-generator

encrypt 钩子仅允许单个 cryptdevice= 条目 (archlinux/mkinitcpio/mkinitcpio#231)。在具有多个驱动器的系统设置中,这可能会受到限制,因为 dm-crypt 没有超出物理设备的功能。例如,以“LVM on LUKS”为例:整个 LVM 存在于 LUKS 映射器内部。这对于单驱动器系统来说是完全可以的,因为只有一个设备需要解密。但是,当您想要增加 LVM 的大小时会发生什么?您不能,至少在不修改 encrypt 钩子的情况下不能。

以下各节简要介绍了克服此限制的替代方案。第一个是关于如何将 LUKS on LVM 设置扩展到新磁盘。第二个是关于修改 encrypt 钩子以在没有 LVM 的 LUKS 设置中解锁多个磁盘。

在多个磁盘上扩展 LVM

多个磁盘的管理是 LVM 的基本功能,也是其分区灵活性的主要原因。它也可以与 dm-crypt 一起使用,但前提是 LVM 用作第一个映射器。在这样的 LUKS on LVM 设置中,加密设备在逻辑卷内部创建(每个卷都有单独的密码/密钥)。以下内容涵盖了将该设置扩展到另一个磁盘的步骤。

警告: 备份!虽然调整文件系统大小可能是标准操作,但请记住操作可能会出错,并且以下内容可能不适用于特定设置。通常,将文件系统扩展到可用磁盘空间比缩小文件系统的问题更少。这尤其适用于使用堆叠映射器的情况,如下例所示。

添加新驱动器

首先,可能需要根据 dm-crypt/驱动器准备 准备新磁盘。其次,将其分区为 LVM,例如,将所有空间分配给分区类型为 8E00 (Linux LVM) 的 /dev/sdY1。第三,将新磁盘/分区附加到现有的 LVM 卷组,例如

# pvcreate /dev/sdY1
# vgextend MyStorage /dev/sdY1

扩展逻辑卷

对于下一步,即新磁盘空间的最终分配,必须卸载要扩展的逻辑卷。它可以对 cryptdevice 根分区执行,但在这种情况下,必须从 Arch 安装 ISO 执行该过程。

在此示例中,假设将使用新的磁盘空间扩展 /home 的逻辑卷(lv-name homevol)。

# umount /home
# fsck /dev/mapper/home
# cryptsetup close /dev/mapper/home
# lvextend -l +100%FREE MyStorage/homevol

现在逻辑卷已扩展,接下来是 LUKS 容器。

# cryptsetup open /dev/MyStorage/homevol home
# umount /home      # as a safety, in case it was automatically remounted
# cryptsetup --verbose resize home

最后,文件系统本身会被调整大小。

# e2fsck -f /dev/mapper/home
# resize2fs /dev/mapper/home

完成!如果按计划进行,则可以重新挂载 /home,并且现在包括到新磁盘的跨度。

# mount /dev/mapper/home /home

请注意,cryptsetup resize 操作不会影响加密密钥,并且这些密钥没有更改。

修改 encrypt 钩子以支持多个分区

请注意,sd-encrypt 开箱即用地支持多个分区。如果以这种方式打开的多个(或所有)分区共享相同的密码,则 sd-encrypt 将为每个分区尝试一次,而不会多次询问。这可能是以下内容的更简单的替代方案。

根文件系统跨越多个分区

可以修改 encrypt 钩子以允许在启动时解密多个硬盘驱动器根目录 (/)。一种方法

# cp /usr/lib/initcpio/install/encrypt /etc/initcpio/install/encrypt2
# cp /usr/lib/initcpio/hooks/encrypt  /etc/initcpio/hooks/encrypt2
# sed -i "s/cryptdevice/cryptdevice2/" /etc/initcpio/hooks/encrypt2
# sed -i "s/cryptkey/cryptkey2/" /etc/initcpio/hooks/encrypt2

cryptdevice2= 添加到您的启动选项(如果需要,还添加 cryptkey2=),并在重建之前将 encrypt2 钩子添加到您的 mkinitcpio.conf 中。请参阅 dm-crypt/系统配置

多个非根分区

也许您需要对非根分区使用 encrypt 钩子。Arch 不开箱即用地支持此功能,但是,您可以轻松更改 /lib/initcpio/hooks/encrypt 中的 cryptdevcryptname 值(第一个值指向您的 /dev/sd* 分区,第二个值指向您想要归属的名称)。这应该就足够了。

最大的优势是您可以实现一切自动化,而使用外部密钥文件(即密钥文件不在任何内部硬盘分区上)设置 /etc/crypttab 可能会很麻烦 - 您需要确保在加密分区之前挂载 USB/FireWire/... 设备,这意味着您必须更改 /etc/fstab 的顺序(至少)。

当然,如果 cryptsetup 软件包升级,您将不得不再次更改此脚本。与 /etc/crypttab 不同,仅支持一个分区,但是通过一些进一步的修改,应该可以解锁多个分区。

此文章或章节的真实准确性存在争议。

原因: 为什么不直接使用受支持的 Grub2?另请参阅 mkinitcpio#使用 RAID(在 Talk:Dm-crypt/Specialties 中讨论)

如果您想在软件 RAID 分区上执行此操作,则还需要做一件事。仅在 /lib/initcpio/hooks/encrypt 中设置 /dev/mdX 设备是不够的;encrypt 钩子由于某种原因将无法找到密钥,也不会提示输入密码。看起来 RAID 设备直到 encrypt 钩子运行后才启动。您可以通过将 RAID 阵列放在 /boot/grub/menu.lst 中来解决此问题,例如

kernel /boot/vmlinuz-linux md=1,/dev/hda5,/dev/hdb5

如果您将根分区设置为 RAID,您会注意到与该设置的相似之处。GRUB 可以很好地处理多个阵列定义。

kernel /boot/vmlinuz-linux root=/dev/md0 ro md=0,/dev/sda1,/dev/sdb1 md=1,/dev/sda5,/dev/sdb5,/dev/sdc5

使用分离的 LUKS 标头的加密系统

本示例遵循与 dm-crypt/加密整个系统#Plain dm-crypt 中相同的设置,在遵循本指南之前应首先阅读该部分。

通过使用分离的标头,加密的块设备本身仅携带加密数据,只要攻击者不知道标头的存在,就可以实现 可否认加密。它类似于使用 plain dm-crypt,但具有 LUKS 的优势,例如主密钥和密钥派生的多个密码。此外,使用分离的标头提供了一种形式的双因素身份验证,其设置比 使用 GPG 或 OpenSSL 加密密钥文件 更容易,同时仍然具有用于多次重试的内置密码提示。有关更多信息,请参阅 静态数据加密#加密元数据

在执行设置加密系统分区的第一个步骤并创建要与 cryptsetup 一起使用的标头文件之前,请参阅 dm-crypt/设备加密#LUKS 模式的加密选项 以获取加密选项。

# dd if=/dev/zero of=header.img bs=16M count=1
# cryptsetup luksFormat --offset 32768 --header header.img /dev/sdX
提示: --offset 选项允许指定设备上加密数据的开始位置。通过在设备开头保留空间,您可以选择稍后 重新附加 LUKS 标头。该值以 512 字节扇区指定,有关更多详细信息,请参阅 cryptsetup-luksFormat(8)

打开容器

# cryptsetup open --header header.img /dev/sdX enc

现在按照您的要求进行 LVM on LUKS 设置。这同样适用于在可移动设备上 准备引导分区(因为如果没有引导分区,则为解锁加密磁盘而单独设置标头文件就没有任何意义)。接下来将 header.img 移动到其上。

# mv header.img /mnt/boot

按照安装步骤进行到 mkinitcpio 步骤(您现在应该在加密系统内 arch-chroot)。

提示: 您会注意到,由于系统分区仅具有“随机”数据,因此它没有分区表,也没有 UUID 或 LABEL。但是,您仍然可以使用 持久块设备命名#by-id 和 by-path 进行一致的映射。例如,使用来自 /dev/disk/by-id/ 的磁盘 ID。

initramfs 有两个选项来支持分离的 LUKS 标头。

使用 systemd 钩子

设置以下 内核参数

rd.luks.name=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=enc rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=header=/header.img:UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ rd.luks.data=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=/dev/disk/by-id/your-disk_id
  • XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 替换为 LUKS 超级块 UUID。可以使用 cryptsetup luksDump header.imgblkid -s UUID -o value header.img 获取它。
  • UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ 替换为标头文件所在的卷的块设备。

或者,除了使用 rd.luks 内核参数外,还可以在 /etc/crypttab.initramfs 文件中指定选项。

/etc/crypttab.initramfs
enc	/dev/disk/by-id/your-disk_id	none	header=/header.img:UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ

接下来,修改 /etc/mkinitcpio.conf 以使用 systemd,并包含标头所在的卷的 文件系统 模块。例如,如果它是 FAT

/etc/mkinitcpio.conf
...
MODULES=(vfat)
...
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)
...

重新生成 initramfs,您就完成了。

注意
  • 当使用 /etc/crypttab.initramfs 时,无需将 cryptsetup 参数传递给内核命令行,因为 /etc/crypttab.initramfs 将作为 /etc/crypttab 添加到 initramfs 中。
  • 避免将 rd.luks 内核参数与 /etc/crypttab.initramfs 一起使用,因为它可能会导致冲突。有关详细信息,请参阅 dm-crypt/系统配置#使用 systemd-cryptsetup-generator 中的警告。

修改 encrypt 钩子

此方法展示了如何修改 encrypt 钩子以使用分离的 LUKS 标头。现在必须修改 encrypt 钩子以使 cryptsetup 使用单独的标头 (archlinux/mkinitcpio/mkinitcpio#234;这些更改的基本来源和想法 发布在 BBS 上)。制作一个副本,这样它就不会在 mkinitcpio 更新时被覆盖。

# cp /usr/lib/initcpio/hooks/encrypt /etc/initcpio/hooks/encrypt2
# cp /usr/lib/initcpio/install/encrypt /etc/initcpio/install/encrypt2
/etc/initcpio/hooks/encrypt2 (around line 52)
warn_deprecated() {
    echo "The syntax 'root=${root}' where '${root}' is an encrypted volume is deprecated"
    echo "Use 'cryptdevice=${root}:root root=/dev/mapper/root' instead."
}

local headerFlag=false
for cryptopt in ${cryptoptions//,/ }; do
    case ${cryptopt} in
        allow-discards)
            cryptargs="${cryptargs} --allow-discards"
            ;;
        header)
            cryptargs="${cryptargs} --header /boot/header.img"
            headerFlag=true
            ;;
        *)
            echo "Encryption option '${cryptopt}' not known, ignoring." >&2
            ;;
    esac
done

if resolved=$(resolve_device "${cryptdev}" ${rootdelay}); then
    if $headerFlag || cryptsetup isLuks ${resolved} >/dev/null 2>&1; then
        [ ${DEPRECATED_CRYPT} -eq 1 ] && warn_deprecated
        dopassphrase=1

现在编辑 mkinitcpio.conf 以添加 encrypt2lvm2 钩子,将 header.img 添加到 FILES,将 loop 添加到 MODULES,以及系统需要的其他配置。

/etc/mkinitcpio.conf
...
MODULES=(loop)
...
FILES=(/boot/header.img)
...
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt2 lvm2 filesystems fsck)
...

这是必需的,以便 LUKS 标头在启动时可用,从而允许解密系统,使我们免于设置更复杂的配置来挂载另一个单独的 USB 设备以访问标头。完成此设置后,将创建 initramfs。

接下来,配置引导加载程序以指定 cryptdevice=,并为此设置传递新的 header 选项。

cryptdevice=/dev/disk/by-id/your-disk_id:enc:header

最后,对于 USB 存储介质上的 /boot 分区,遵循 dm-crypt/加密整个系统#安装后配置 特别有用。

加密的 /boot 和 USB 上的分离的 LUKS 标头

此文章或章节正在考虑删除。

原因: 此方案基于 [6],其结构随后在 [7] 中进行了更改。(在 Talk:Dm-crypt/Specialties#加密的 /boot 和 USB 上的分离的 LUKS 标头 中讨论)

此设置不是将 header.img 和密钥文件嵌入到 initramfs 镜像中,而是使您的系统完全依赖 USB 密钥,而不仅仅是镜像来启动,并依赖于加密引导分区内部的加密密钥文件。由于标头和密钥文件未包含在 initramfs 镜像中,并且自定义 encrypt 钩子专门用于 USB 的 by-id,因此您实际上需要 USB 密钥才能启动。

对于 USB 驱动器,由于您要加密驱动器和内部的密钥文件,因此最好级联密码,以免两次使用同一个密码。中间人攻击是否真的可行尚有争议。您可以执行 twofish-serpent 或 serpent-twofish。

准备磁盘设备

假设 sdb 是 USB 驱动器,sda 是主硬盘驱动器。

根据 dm-crypt/驱动器准备 准备设备。

准备 USB 密钥

使用 gdisk 根据 此处所示 的布局对磁盘进行分区,但应仅包含前两个分区。如下所示

# gdisk /dev/sdb
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00  EFI System
   2         1050624         1460223   200.0 MiB   8300  Linux filesystem

在运行 cryptsetup 之前,请先查看 LUKS 模式的加密选项密码和操作模式,以选择您所需的设置。

准备引导分区,但暂不挂载任何分区,并 格式化 EFI 系统分区

# mount /dev/mapper/cryptboot /mnt
# dd if=/dev/urandom of=/mnt/key.img bs=filesize count=1 iflag=fullblock
# cryptsetup luksFormat /mnt/key.img
# cryptsetup open /mnt/key.img lukskey

filesize 以字节为单位,但可以后跟诸如 M 之类的后缀。文件太小会导致出现令人讨厌的 Requested offset is beyond real size of device /dev/loop0 错误。作为粗略的参考,创建 4M 文件将成功加密它。您应该使文件大于所需的空间,因为加密的环回设备将比文件的大小略小。

对于大文件,您可以使用 --keyfile-offset=offset--keyfile-size=size 导航到正确的位置(请参阅 Gentoo:Custom Initramfs#加密密钥文件)。

现在您应该已在环回设备(/dev/loop1 下)中打开 lukskey,并映射为 /dev/mapper/lukskey

主驱动器

# truncate -s 16M /mnt/header.img
# cryptsetup --key-file=/dev/mapper/lukskey --keyfile-offset=offset --keyfile-size=size luksFormat /dev/sda --offset 32768 --header /mnt/header.img

选择以字节为单位的 offsetsize(8192 KiB 是 cryptsetup 的最大密钥文件大小)。

# cryptsetup open --header /mnt/header.img --key-file=/dev/mapper/lukskey --keyfile-offset=offset --keyfile-size=size /dev/sda enc
# cryptsetup close lukskey
# umount /mnt

按照 准备逻辑卷 设置 LVM on LUKS。

有关分区大小的建议,请参阅 分区#离散分区

一旦您的根分区被挂载,将您的加密引导分区挂载为 /mnt/boot,并将您的 EFI 系统分区挂载为 /mnt/efi

安装步骤和自定义 encrypt 钩子

按照 安装指南 进行到 mkinitcpio 步骤,但暂不执行,并跳过分区、格式化和挂载步骤,因为这些步骤已经完成。

为了使加密设置生效,你需要构建你自己的钩子(hook),幸运的是这很容易做到,以下是你需要的代码。你将需要遵循持久块设备命名#by-id 和 by-path来找出你的 usb 和主硬盘的 by-id 值(它们被链接 -> 到 sdasdb)。

你应该使用 by-id 而不是仅仅使用 sdasdb,因为 sdX 可能会改变,而这可以确保它是正确的设备。

你可以将 customencrypthook 命名为你想要的任何名称,并且自定义构建钩子可以放置在 /etc/initcpiohooksinstall 文件夹中。保留这两个文件(在创建备份后,将它们 cp/home 分区或你用户的 /home 目录)的备份。 /usr/bin/ash 不是笔误。

/etc/initcpio/hooks/customencrypthook
#!/usr/bin/ash

run_hook() {
    modprobe -a -q dm-crypt >/dev/null 2>&1
    modprobe loop
    [ "${quiet}" = "y" ] && CSQUIET=">/dev/null"

    while [ ! -L '/dev/disk/by-id/usbdrive-part2' ]; do
     echo 'Waiting for USB'
     sleep 1
    done

    cryptsetup open /dev/disk/by-id/usbdrive-part2 cryptboot
    mount --mkdir /dev/mapper/cryptboot /mnt
    cryptsetup open /mnt/key.img lukskey
    cryptsetup --header /mnt/header.img --key-file=/dev/mapper/lukskey --keyfile-offset=''offset'' --keyfile-size=''size'' open /dev/disk/by-id/harddrive enc
    cryptsetup close lukskey
    umount /mnt
}

usbdrive 是你的 USB 驱动器 by-id,而 harddrive 是你的主硬盘 by-id

提示: 你也可以使用 cryptsetup close 关闭 cryptboot,但是保持它打开可以更轻松地使用 Pacman 进行系统更新,并使用 mkinitcpio 重新生成 initramfs。/boot 分区必须挂载才能进行影响 kernelInitramfs 的更新,并且在这些更新之后 initramfs 将会自动重新生成。
# cp /usr/lib/initcpio/install/encrypt /etc/initcpio/install/customencrypthook

现在编辑复制的文件并删除 help() 部分,因为它不是必需的。

/etc/mkinitcpio.conf (edit this only do not replace it, these are just excerpts of the necessary parts)
MODULES=(loop)
...
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block customencrypthook lvm2 filesystems fsck)

files=()binaries=() 数组是空的,你不应该完全替换 HOOKS=(...) 数组,只需在 block 之后和 filesystems 之前编辑添加 customencrypthook lvm2,并确保删除 systemdencrypt

引导加载程序

完成 安装指南mkinitcpio 步骤之后的内容。要启动,你需要 GRUBefibootmgr。请注意,你可以使用 GRUB 通过 配置引导加载程序 来支持加密磁盘,但是对于此设置,编辑 GRUB_CMDLINE_LINUX 不是必需的。

或者使用直接 UEFI 安全启动,通过使用 cryptbootAUR 生成密钥,然后使用 sbupdate-gitAUR 签署 initramfs 和内核,并为你的 EFI 系统分区创建一个可启动的 .efi 文件。在使用 cryptboot 或 sbupdate 之前,请注意来自 安全启动#使用你自己的密钥 的这段摘录

提示: 请注意 cryptbootAUR 要求在运行之前在 /etc/crypttab 中指定加密的启动分区,并且如果你将其与 sbupdate-gitAUR 结合使用,sbupdate 期望由 cryptboot 创建的 /boot/efikeys/db.* 文件被大写,例如 DB.*,除非在 /etc/default/sbupdate 中另有配置。不使用 systemd 处理加密的用户可能在其 /etc/crypttab 文件中没有任何内容,并且需要创建一个条目。
# efibootmgr --create --disk /dev/device --part partition_number --label "Arch Linux Signed" --loader "EFI\Arch\linux-signed.efi" --unicode

请参阅 efibootmgr(8) 以获得选项的说明。

确保启动顺序将 Arch Linux Signed 放在首位。如果不是,请使用 efibootmgr --bootorder XXXX,YYYY,ZZZZ --unicode 更改它。

更改 LUKS 密钥文件

本文或章节候选合并到 dm-crypt/设备加密#密钥文件

注意: 在此设置中,更改密钥文件不是必需的操作。(在 Talk:Dm-crypt/Specialties 中讨论)
# cryptsetup --header /boot/header.img --key-file=/dev/mapper/lukskey --keyfile-offset=offset --keyfile-size=size luksChangeKey /dev/mapper/enc /dev/mapper/lukskey2 --new-keyfile-size=newsize --new-keyfile-offset=newoffset

之后,cryptsetup close lukskey 并使用 shreddd 用随机数据覆盖旧的密钥文件,然后再删除它,然后确保新的密钥文件被重命名为旧文件的相同名称:key.img 或其他名称。