LUKS2 与 LUKS1:区别、如何查看版本以及如何转换
相比 LUKS1,LUKS2 增加了 Argon2id、冗余 JSON 头部、令牌和完整性校验。用 cryptsetup luksDump 查看版本,并在备份头部后安全转换。
简答:LUKS2 是 Linux 磁盘加密当前的磁盘格式,自 cryptsetup 2.1 起成为默认格式。与 LUKS1 相比,它增加了冗余且带校验和的 JSON 元数据头部、以内存密集型的 Argon2id 取代 PBKDF2 作为密钥派生函数、32 个密钥槽(LUKS1 为 8 个)、用于 TPM2 和 FIDO2 解锁的令牌,以及可选的认证加密。除非旧版 GRUB 必须自行解密 `/boot`,否则请使用 LUKS2。
两种格式加密数据的方式相同,通常都是 AES-XTS。区别在于头部:密钥如何存储、密码被暴力破解的难度,以及哪些工具能读取它。本指南介绍两者的区别、如何查看你使用的是哪种,以及如何用 `cryptsetup convert` 在不丢失磁盘数据的情况下转换。如果你要为 小型 VPS 自托管栈加密一台新服务器,应选择 LUKS2。
LUKS2 与 LUKS1 一览
| 特性 | LUKS1 | LUKS2 |
|---|---|---|
| 头部 | 单个 592 字节二进制头部加密钥槽区域 | 两个二进制头部加 JSON 元数据,带校验和并有冗余副本 |
| 默认头部 / 数据偏移 | 2 MiB | 16 MiB |
| 密钥槽 | 8 | 32 |
| 密钥派生(PBKDF) | 仅 PBKDF2 | Argon2id(默认)、Argon2i 或 PBKDF2 |
| 令牌(TPM2、FIDO2、PKCS#11、Clevis) | 否 | 是 |
| 认证加密(dm-integrity) | 否 | 可选,实验性 |
| 在线重加密 | 仅离线 | 是,可对已挂载设备执行 `cryptsetup reencrypt` |
| 持久化标志和标签 | 否 | 是,例如 `--allow-discards --persistent` |
| 加密 /boot 时由 GRUB 解锁 | 是 | 上游 GRUB 仅支持 PBKDF2 密钥槽 |
头部格式与密钥槽
LUKS1 头部是一个固定的二进制结构,后跟八个密钥槽区域。如果设备开头的扇区被覆盖(例如误执行 `mkfs` 或分区工具),所有密钥槽都会消失,除非你有头部备份,否则数据将丢失。
LUKS2 存储一个二进制头部和一个 JSON 元数据区,并为两者各保留一份副本。每份副本都带有校验和,因此 `cryptsetup` 能检测到损坏并回退到另一份副本。JSON 区描述了密钥槽、数据段、摘要和令牌,正因如此,无需再次更改格式就能加入新功能。不过冗余仍然不能替代头部备份:前几 MB 被完全覆盖会同时摧毁两份副本。
Argon2id 与 PBKDF2
密码从不直接用作密钥。密钥派生函数会对其进行拉伸,让每次猜测都代价高昂。LUKS1 只能使用 PBKDF2,它在 GPU 和 ASIC 上运行成本很低,因此拿到头部副本的攻击者可以高速并行地测试密码。
LUKS2 默认使用 Argon2id,每次猜测都需要可配置数量的内存(默认最多 1 GiB,受格式化时可用内存的限制),并行化的代价要高得多。强密码仍是主要防线,但 Argon2id 显著提高了每次猜测的成本。
在小型服务器上要注意内存开销。在大内存机器上创建的密钥槽,解锁时所需的内存可能超过 1 GB VPS(例如 NoctisNode 的 Wisp 套餐)在 initramfs 中能提供的内存。在大机器上为小机器格式化或添加密钥时,请用 `--pbkdf-memory`(单位 KiB)显式设置。
# Inspect PBKDF parameters of each keyslot
cryptsetup luksDump /dev/vda3 | grep -A6 '^ [0-9]*: luks2'
# Re-derive keyslot 0 with Argon2id and 512 MiB memory cost
cryptsetup luksConvertKey /dev/vda3 --key-slot 0 \
--pbkdf argon2id --pbkdf-memory 524288令牌、完整性与 GRUB 注意事项
令牌是 LUKS2 头部中的 JSON 对象,告诉工具如何自动获取密钥。`systemd-cryptenroll` 用它们把密钥槽绑定到 TPM2 芯片、FIDO2 安全密钥或 PKCS#11 智能卡,Clevis 则用它们配合 Tang 服务器实现网络绑定解锁。这些在 LUKS1 中都不存在。
完整性模式(`cryptsetup luksFormat --integrity hmac-sha256`)将加密与 dm-integrity 结合,被篡改的扇区会产生读取错误,而不是悄无声息地返回被修改的数据。它会占用磁盘空间、降低写入速度、需要在格式化时完整擦除,且仍被标记为实验性。大多数服务器不使用它。
GRUB 是人们至今仍会遇到 LUKS1 的主要原因。上游 GRUB 2.06 及更高版本可以打开 LUKS2,但仅限使用 PBKDF2 的密钥槽,因为上游 GRUB 不支持 Argon2。如果必须由 GRUB 自己解密加密的 `/boot`,请使用 LUKS1 或带 `--pbkdf pbkdf2` 的 LUKS2 密钥槽。Debian 和 Ubuntu 安装程序会保持 `/boot` 不加密,由内核和 initramfs 完成解锁,因此 Argon2id 可以正常使用,包括通过 SSH 远程解锁。
如何查看卷是 LUKS1 还是 LUKS2
以下任一方法都可以在运行中的系统上以 root 身份使用。`cryptsetup luksDump` 输出中的 `Version:` 行是权威答案;该输出还会显示密钥槽、PBKDF 类型和令牌。
# Find encrypted partitions (FSVER column shows 1 or 2)
lsblk -f
# Authoritative: header version
cryptsetup luksDump /dev/vda3 | grep -E '^Version'
# Version: 2
# Exit code 0 only if the device is LUKS2
cryptsetup isLuks --type luks2 /dev/vda3 && echo LUKS2使用 cryptsetup convert 进行转换
`cryptsetup convert` 会原地重写头部,不会触碰加密数据。设备必须处于关闭状态,因此对于根文件系统,你需要在救援系统或 Live 系统中运行。转换过程中出错或断电可能导致头部无法使用,所以备份这一步必不可少。
- 01.启动救援系统或 Live 系统,确保 LUKS 设备未被打开(如有需要执行 `cryptsetup close`)。
- 02.用 `cryptsetup luksHeaderBackup` 备份头部,并将文件复制到服务器之外。任何拿到此文件和旧密码的人都能解锁磁盘,所以请加密保存。
- 03.用 `cryptsetup convert --type luks2` 将 LUKS1 转换为 LUKS2。现有密钥槽仍保持 PBKDF2。
- 04.除非 GRUB 需要读取,否则用 `cryptsetup luksConvertKey --pbkdf argon2id` 将每个密钥槽升级为 Argon2id。
- 05.测试设备能否正常打开,然后用 `update-initramfs -u` 重建 initramfs 并重启。
- 06.若要从 LUKS2 转回 LUKS1,需先把每个密钥槽转换为 PBKDF2,并移除令牌和 LUKS2 专有功能;否则 `cryptsetup convert --type luks1` 会拒绝执行。
# From a rescue system, device closed
cryptsetup luksHeaderBackup /dev/vda3 --header-backup-file /root/vda3-luks-header.img
cryptsetup convert --type luks2 /dev/vda3
cryptsetup luksConvertKey /dev/vda3 --key-slot 0 --pbkdf argon2id
cryptsetup open /dev/vda3 cryptroot && cryptsetup close cryptroot
# Emergency restore (overwrites the current header!)
# cryptsetup luksHeaderRestore /dev/vda3 --header-backup-file /root/vda3-luks-header.imgNote · 恢复头部后,备份时有效的密码会重新生效,包括你之后删除的密码。轮换密码时请删除旧的头部备份。将当前备份单独存放,例如放在 restic 备份指南中介绍的仓库里。
常见问题
QLUKS2 比 LUKS1 更好吗?
A对于几乎所有新部署,是的。LUKS2 拥有冗余头部、Argon2id 密钥派生、用于 TPM2 或 FIDO2 的令牌以及在线重加密;只有在旧版 GRUB 必须自行解密 `/boot` 时才需要 LUKS1。
Q如何查看我的 LUKS 版本?
A以 root 身份运行 `cryptsetup luksDump /dev/sdX | grep Version`,它会输出 1 或 2。`lsblk -f` 也会在 FSVER 列中显示 crypto_LUKS 分区的版本。
Q能否在不丢失数据的情况下把 LUKS1 转换为 LUKS2?
A能。`cryptsetup convert --type luks2` 在设备关闭时只重写头部。请先用 `cryptsetup luksHeaderBackup` 备份头部,因为转换中断可能导致卷无法读取。
QGRUB 支持 LUKS2 吗?
A上游 GRUB 2.06 及更高版本可以解锁 LUKS2,但仅限使用 PBKDF2 的密钥槽,不支持 Argon2id。这只在 `/boot` 本身被加密时才有影响;如果 `/boot` 未加密,initramfs 可以正常用 Argon2id 解锁 LUKS2。
QLUKS2 默认使用什么加密算法?
A当前的 cryptsetup 默认使用 512 位密钥的 `aes-xts-plain64`(XTS 模式的 AES-256),并用 Argon2id 进行密钥派生。运行 `cryptsetup --help` 可查看你系统上编译时的默认值,完整配置请参阅 LUKS 加密根分区指南。