加密方案介绍
我的系统盘文件系统是 Btrfs
。这是个很棒的文件系统,功能强大,但不具备加密功能。
ArchWiki1 介绍了两种加密分区的思路。在现有的文件系统上加密和使用 LUKS
。
LUKS 的花样2繁多,大致有这几种:
LUKS on Partition
最常用的方法。在新分区上创建 LUKS 加密空间,解密后再创建文件系统,即先加密后分区。
不明白分区和文件系统区别的小伙伴建议先百度了解!
优点是配置方便,可以自由添加和更换加密密钥。
缺点是不灵活,必须预先分配要加密的磁盘空间。 可以但很麻烦,而且需求很少。
Plain dm-crypt
纯加密,没有 LUKS 加密头,对 SSD 最友好,但局限很大。
使用这种方式需要记住所有加密参数,并保管好密钥。因为一旦加密完成,你就不能更改密钥了。
其他方式
比如 LUKS on RAID
的软 RAID 加密,LUKS on LVM
和 LVM on LUKS
的套娃加密。普通用户需求较少,就不介绍了。
这里选择 LUKS on Partition
作为加密方案。
准备阶段
驱动器安全擦除
建立加密分区前需要对硬盘进行安全擦除。常规方法是建立分区前擦除3,也可以建立加密后擦除4。
这里采用一种适用于 NVMe 驱动器的方法。
删除所有的分区
用什么都行。
擦除驱动器。
擦除 NVMe 驱动器的方法有两种,
format
和sanitize
。后者是更完全的擦除,对硬盘寿命会有损耗。这里选择前者。假设硬盘块文件为
/dev/nvme0n1
,执行nvme format /dev/nvme0 -ses 1 -n 1
nvme0
表示是 NVMe 字符设备 NVMe character device 。
nvme0n1
表示是 NVMe 命名空间块设备 namespace block device ,输入错误系统会报错并给出提示。
后面的 -n 1
参数指定了 NVMe 命名空间为 1 。
分区
常规的分区操作。UEFI 启动需要划分至少两个分区(系统分区和 ESP)。
过程不赘述。
建立加密头
cryptsetup luksFormat /dev/nvme0n1p2
/dev/nvme0n1p2
即准备加密的分区的块路径。
也可以设置其他参数5。比如指定 LUKS 版本:
cryptsetup --type luks1 luksFormat /dev/nvme0n1p2
默认参数
如果不指定参数会采用默认参数,相当于:
cryptsetup --type luks2 --cipher aes-xts-plain64 --hash sha256 --iter-time 2000 --key-size 256 --pbkdf argon2i --sector-size 512 --use-urandom --verify-passphrase luksFormat device
多数情况下默认参数完全够用,除非使用 LUKS1 或者需要更强的安全性能。
密钥
- 密码
创建时如果没有指定其他参数,系统会要求输入密码来加密分区。
密码可以后期修改,而且这个密码(包括密钥文件)可以设置多个,并不唯一。
- 密钥文件
如果不想使用密码加密,可以使用密钥文件6加密分区。需要使用这样的指令:
cryptsetup luksFormat /dev/nvme0n1p2 /path/to/keyfile
创建时不会提示输入密码。
一个创建随机密钥文件的方法,需要用 ROOT
权限执行:
dd bs=512 count=4 if=/dev/random of=/path/to/keyfile iflag=fullblock
chmod 000 /path/to/keyfile
妥善保管好自己的密钥,做好备份!
安装系统
解密分区
安装系统前需要解锁分区
cryptsetup open /dev/nvme0n1p2 dm_name
解密后的分区会被映射到 /dev/mapper/dm_name
。dm_name
可以修改为其他名称。
如果使用了密钥文件加密,解密时需要指定密钥路径
cryptsetup open /dev/nvme0n1p2 dm_name --key-file /etc/mykeyfile
然后就可以在解密后的分区上创建文件系统了。以 btrfs
为例,假设设定的dm_name为 Root_
mkfs.btrfs /dev/mapper/Root_
mount /dev/mapper/Root_ /mnt
接下来就可以正常安装操作系统了。
如果要加密 BOOT 分区请参考 BOOT 分区加密的方法安装 GRUB 引导。(不推荐)
BOOT 分区加密
不推荐加密 BOOT 分区。
GRUB 仅支持解密 LUKS1 分区,对 LUKS2 分区的支持尚未完全。
这并不影响系统盘使用 LUKS2 加密。
打开 /etc/default/grub
,修改这一项:
GRUB_ENABLE_CRYPTODISK=y
修改后重新安装 GRUB 引导:
grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB --recheck
--recheck
用于防止重复添加启动项。
如果没有修改 GRUB 配置文件就安装引导,系统会报错并提示你修改。
配置开机解密
配置 initramfs HOOK
修改
/etc/mkinitcpio.conf
,添加 LUKS 需要的 HOOKArch Linux 提供了两套方案,可以使用
udev
或者systemd
的 HOOK。推荐后者,因为支持更多的功能,开机更快。
添加 systemd HOOK:
HOOKS=(base **systemd** autodetect keyboard **sd-vconsole** modconf block **sd-encrypt** filesystems fsck)
需要在对应位置添加星号标记的条目。
添加密钥文件路径,不需要引号
FILES=(/path/to/keyfile)
使用 ROOT 执行
mkinitcpio -p 内核名称
生成内核文件,如果创建失败请检查是否安装了btrfs-progs
包。
配置 Bootloader 内核参数
此项与下条二选一。
修改 Bootloader 的内核参数。在已有的参数前添加参数:
rd.luks.name=device-UUID=cryptroot
指定加密盘的位置。这里使用 UUID[^Persistent_block_device_naming_(简体中文) - ArchWiki] 定位分区。UUID 可以使用指令查看 lsblk -o name,uuid
。注意需填入被加密物理分区的 UUID ,而不是解密后映射分区的 UUID 。
cryptroot
是解密后映射分区的名称,注意要与下方设置的 dm_name
一致。
rd.luks.options
设置解密参数,主要是 LUKS 加密等参数,一般不需要额外设置。如果是 SSD ,可添加 discard
参数启用 TRIM 。
rd.luks.key=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=/path/to/keyfile
指定加密文件的位置,需要填入被加密物理分区的 UUID 以及文件路径(文件包含在 initramfs
中)。
root=/dev/mapper/cryptroot
映射的系统盘位置。
以 GRUB 为例:
GRUB_CMDLINE_LINUX_DEFAULT="rd.luks.name=6120c3ba-7811-4692-a9c0-b0319a8effa4=root_ rd.luks.options=timeout=10s,discard,cipher=aes-xts-plain64:sha256,size=512 rd.luks.key=6120c3ba-7817-4692-a9c0-b0314a679ea4=/etc/cryptluks.key root=/dev/mapper/root_ loglevel=3 quiet"
执行生成 grub.cfg :
grub-mkconfig -o /boot/grub/grub.cfg
配置 crypttab
此项与上条二选一。
新建 /etc/crypttab.initramfs
。这个文件会在 mkinitcpio
时自动添加入 initramfs
中。每次修改完密钥文件都需要执行 mkinitcpio
操作。
格式与 /etc/crypttab 相同。
在文件后添加如下条目:
block_ UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - discard,cipher=aes-xts-plain64:sha256,size=512
条目一共分为四列:
- 第一列:映射分区的名称,即
rd.luks.name=device-UUID=cryptroot
中的cryptroot
。 - 第二列:被加密物理分区的位置,即
rd.luks.name=device-UUID=cryptroot
的device-UUID
。需要加上前缀UUID=
。 - 第三列:密钥文件的路径。没有的话填
none
或-
。 - 第四列:解密参数,即
rd.luks.options
的内容。
保存后执行 mkinitcpio
操作。
别忘了给 Bootloader 添加内核参数,只要添加一项 root=/dev/mapper/cryptroot
。
使用 Yubikey 开机解密
最近入手了一个 Yubikey 5,想着能不能用它来开机解密,实现真正的安全启动。答案是可以的7。
systemd
提供了 FIDO 硬件密钥解密的支持。
需要配置 systemd
的 HOOK ,并提前配置好 Yubikey 的 FIDO 功能。
方法
- 插入 Yubikey ,使用 ROOT 执行指令
指令中的块文件路径请按自己的加密盘实际路径修改。
这里需要的是加密盘物理分区的块文件,而不是解密后的映射分区块文件。
systemd-cyptenroll /dev/nvme0n1p2 --fido2-device=auto
有以下可选参数:
--fido2-with-client-pin=BOOL
解锁时是否需要输入 PIN ,默认为 yes 。建议添加并设置为 no ,否则每次开机不仅要插入密钥还要输入 PIN 。
--fido2-with-user-presence=BOOL
解锁时是否需要用户确认(即触摸密钥),默认为 yes ,需要 FIDO 设备支持 "up" 特性。如果使用 Yubikey 5 就不用设置这个了,即使关闭了也会被强制打开(有提示信息)。
--fido2-with-user-verification=BOOL
解锁时是否需要用户确认,默认为 no ,需要 FIDO 设备支持 "uv" 特性。不知道和上条有什么区别,不用管即可。
执行过程中需要输入 Yubikey 的 FIDO PIN ,并且需要输入加密盘的密码。
此处不能使用密钥文件解密。
建议提前添加一个密码,可以完成操作后移除。
修改 Bootloader 的解密参数。删除文件解密,否则硬件密钥不会生效
在内核参数中指定 FIDO 启动方式
在解密参数中添加
fido2-device=auto
。
开机
开机时需要插入 Yubikey ,等待指示灯闪烁后触摸。如果设置了输入 PIN 解密,需要先输入 PIN 再触摸。
不要求通电前插入密钥,在超时前插入并完成触摸即可。
设置 Yubikey 解密后,可以设置自动登陆,以实现“一键开机”的功能。
参考资料
https://wiki.archlinux.org/index.php/Btrfs_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)#%E5%8A%A0%E5%AF%86 ↩
https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#LUKS_on_a_partition ↩
https://wiki.archlinux.org/index.php/Solid_state_drive/Memory_cell_clearing ↩
https://wiki.archlinux.org/index.php/Dm-crypt/Drive_preparation ↩
https://wiki.archlinux.org/index.php/Dm-crypt/Device_encryption#Encryption_options_for_LUKS_mode ↩
https://wiki.archlinux.org/index.php/Dm-crypt/Device_encryption#Keyfiles ↩
https://wiki.archlinux.org/title/Universal_2nd_Factor#Data-at-rest_encryption_with_LUKS ↩