Dm-crypt
dm-crypt 是使用内核加密API框架和设备映射器(device mapper)子系统的磁盘加密系统。使用dm-crypt,管理员可以加密整个磁盘,逻辑卷,分区以及单个文件。
dm-crypt子系统支持Linux Unified Key Setup (LUKS)结构,允许多个密钥访问加密数据,以及操作密钥(例如更改密钥,添加额外的密码等)。尽管dm-crypt也支持非LUKS,本文将重点关注LUKS功能,主要是因为它的灵活性,可管理性以及社区中的广泛支持。
配置
在开始使用dm-crypt之前有两个先决条件:
- 配置Linux内核
- 安装 sys-fs/cryptsetup 包
内核配置
要使用dm-crypt,有一些必要的配置条目。
首先,必须包括对device mapper基础结构以及'crypt target 的支持:
[*] Enable loadable module support
Device Drivers --->
[*] Multiple devices driver support (RAID and LVM) --->
<*> Device mapper support
<*> Crypt target support
接下来,Linux内核需要支持管理员想要用于加密的一组加密API。这些可以在Cryptographic API部分找到:
[*] Cryptographic API --->
<*> XTS support
<*> SHA224 and SHA256 digest algorithm
<*> AES cipher algorithms
<*> AES cipher algorithms (x86_64)
<*> User-space interface for hash algorithms
<*> User-space interface for symmetric key cipher algorithms
如果根文件系统也要被加密,则需要创建初始ram文件系统,其中根文件系统在挂载之前被解密。 因此,这也需要initramfs支持:
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
如果使用tcrypt加密选项(TrueCrypt/tcplay/VeraCrypt兼容模式),则还需要将以下项目添加到内核中。否则,cryptsetup将返回以下错误:"device-mapper: reload ioctl failed: Invalid argument" 和 "Kernel doesn't support TCRYPT compatible mapping"。
Device Drivers --->
[*] Block Devices --->
<*> Loopback device support
File systems --->
<*> FUSE (Filesystem in Userspace) support
[*] Cryptographic API --->
<*> RIPEMD-160 digest algorithm
<*> SHA384 and SHA512 digest algorithms
<*> Whirlpool digest algorithms
<*> LRW support
<*> Serpent cipher algorithm
<*> Twofish cipher algorithm
安装 Cryptsetup
sys-fs/cryptsetup包提供cryptsetup命令,该命令用于打开或关闭加密存储以及管理与之关联的密码或密钥。
root #
emerge --ask sys-fs/cryptsetup
加密存储
Benchmark
cryptsetup provides a benchmarking tool which will help to decide which setup to choose. The output depends on kernel settings as well as USE flags and destination (HDD, SSD etc.).
root #
cryptsetup benchmark
# Tests are approximate using memory only (no storage IO). PBKDF2-sha1 3622024 iterations per second for 256-bit key PBKDF2-sha256 7410431 iterations per second for 256-bit key PBKDF2-sha512 3216490 iterations per second for 256-bit key PBKDF2-ripemd160 1157368 iterations per second for 256-bit key PBKDF2-whirlpool 1069975 iterations per second for 256-bit key argon2i 14 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time) argon2id 15 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time) # Algorithm | Key | Encryption | Decryption aes-cbc 128b 1520.5 MiB/s 4400.1 MiB/s serpent-cbc 128b 159.6 MiB/s 1061.9 MiB/s twofish-cbc 128b 310.8 MiB/s 662.1 MiB/s aes-cbc 256b 1175.8 MiB/s 4025.0 MiB/s serpent-cbc 256b 160.0 MiB/s 1054.8 MiB/s twofish-cbc 256b 312.6 MiB/s 655.5 MiB/s aes-xts 256b 4081.0 MiB/s 4073.5 MiB/s serpent-xts 256b 953.7 MiB/s 946.3 MiB/s twofish-xts 256b 597.5 MiB/s 616.8 MiB/s aes-xts 512b 3733.8 MiB/s 3743.3 MiB/s serpent-xts 512b 970.9 MiB/s 964.5 MiB/s twofish-xts 512b 598.1 MiB/s 611.3 MiB/s
密钥文件或密码
为了开始加密存储,管理员需要决定使用哪种方法作为加密密钥。cryptsetup支持使用密码或密钥文件。对于密钥文件,这可以是任何文件,但建议使用具有适当保护的随机数据的文件(考虑到访问此密钥文件将意味着访问加密数据)。
要创建密钥文件,可以使用dd命令:
root #
dd if=/dev/urandom of=/etc/keys/enc.key bs=1 count=4096
在接下来的部分中,我们将显示两种情况的每个命令 - 密码和密钥文件。当然,只需要其中一种方法。
创建加密存储平台
要创建加密存储平台(可以是磁盘,分区,文件......),请使用cryptsetup命令和luksFormat
操作。
例如,要将 /dev/vdb2作为加密数据的存储介质:
root #
cryptsetup -c aes-xts-plain64 -s 512 -y luksFormat /dev/vdb2
This will overwrite data on /dev/vdb2 irrevocably. Are you sure? (Type uppercase yes): YES Enter LUKS passphrase: ... Verify passphrase: ...
要使用密钥文件而不是密码:
root #
cryptsetup -c aes-xts-plain64 -s 512 -y luksFormat /dev/vdb2 /etc/keys/enc.key
This will overwrite data on /dev/vdb2 irrevocably. Are you sure? (Type uppercase yes): YES
-s 512
告诉cryptsetup用于真实加密密钥的密钥长度(与密码或密钥文件不同,这是用于真实加密密钥的)。
XTS splits the key into two halves, only one being used for the actual encryption. That means "aes-xts" with a 512-bit key actually uses 256 bits for the AES part.
If the LUKS header gets damaged, your encrypted data will be lost forever, even if you have a backup of the GPG key and passphrase. Therefore, you may wish to consider backing up this header to a separate device, and storing it securely. See the LUKS FAQ for more details on how to do this.
root #
cryptsetup luksHeaderBackup /dev/sdXn --header-backup-file /tmp/efiboot/luks-header.img
Full disk encryption booting
To boot from a fully encrypted device (including encrypted /boot) using GRUB, encrypt using luks1, since luks2 isn't fully supported yet. Example command:
root #
cryptsetup -c aes-xts-plain64 -s 512 -y luksFormat --type luks1 /dev/vdb2
打开加密存储
为了打开加密存储(即通过透明解密使真实数据可访问),请使用luksOpen
操作。
root #
cryptsetup luksOpen /dev/vdb2 myname
Enter passphrase for /dev/vdb2: ...
如果使用了密钥文件,那么命令将如下所示:
root #
cryptsetup luksOpen -d /etc/keys/enc.key /dev/vdb2 myname
命令成功完成后,名为/dev/mapper/myname的新设备文件将可用。
如果这是第一次使用此加密设备,则需要对其进行格式化。以下示例使用Btrfs文件系统,但当然任何其他文件系统都可以:
root #
mkfs.btrfs /dev/mapper/myname
格式化文件系统或过去已完成格式化后,可以在系统上挂载这个设备文件:
root #
mount /dev/mapper/myname /home
关闭加密存储
为了关闭加密存储(即确保不再通过透明解密访问实际数据),请使用luksClose
操作:
root #
cryptsetup luksClose myname
当然,请确保设备不再使用。
操作 LUKS 密钥
LUKS密钥用于访问真正的加密密钥。它们存储在(加密)分区,磁盘或文件的标头中的插槽中。
列出插槽
使用luksDump
操作,可以显示有关加密分区,磁盘或文件的信息。这包括插槽:
root #
cryptsetup luksDump /dev/vdb2
LUKS header information for /dev/vdb2 Version: 1 Cipher name: aes Cipher mode: xts-plain64 Hash spec: sha1 Payload offset: 4096 MK bits: 512 MK digest: 34 3b ec ac 10 af 19 e7 e2 d4 c8 90 eb a8 da 3c e4 4f 2e ce MK salt: ff 7c 7f 53 db 53 48 02 a4 32 dc e0 22 fc a3 51 06 ba b3 48 b3 28 13 a8 7a 68 43 d6 46 79 14 fe MK iterations: 59375 UUID: 2921a7c9-7ccb-4300-92f4-38160804e08c Key Slot 0: ENABLED Iterations: 241053 Salt: 90 0f 0f db cf 66 ea a9 6c 7c 0c 0d b0 28 05 2f 8a 5c 14 54 98 62 1a 29 f3 08 25 0c ec c2 b1 68 Key material offset: 8 AF stripes: 4000 Key Slot 1: ENABLED Iterations: 273211 Salt: 01 4c 26 ed ff 18 75 31 b9 89 5d a6 e0 b5 f4 14 48 d0 23 47 a9 85 78 fb 76 c4 a9 d0 cd 63 fb d7 Key material offset: 512 AF stripes: 4000 Key Slot 2: DISABLED Key Slot 3: DISABLED Key Slot 4: DISABLED Key Slot 5: DISABLED Key Slot 6: DISABLED Key Slot 7: DISABLED
在上面的例子中,使用了两个插槽。请注意,luksDump
不会泄露任何敏感内容 - 它只是显示LUKS标头内容。不需要提供解密密钥来调用luksDump
。
添加一个密钥文件或密码
要添加其他密钥文件或密码来访问加密存储,请使用luksAddKey
操作:
root #
cryptsetup luksAddKey /dev/vdb2
Enter any passphrase: (Enter a valid, previously used passphrase to unlock the key) Enter new passphrase for key slot: ... Verify passphrase: ...
要使用密钥文件解锁密钥(但仍然需要密码):
root #
cryptsetup luksAddKey -d /etc/keys/enc.key /dev/vdb2
Enter new passphrase for key slot: ... Verify passphrase: ...
如果要添加密钥文件(例如/etc/keys/backup.key):
root #
cryptsetup luksAddKey /dev/vdb2 /etc/keys/backup.key
或者,使用第一个密钥文件解锁主密钥:
root #
cryptsetup luksAddKey -d /etc/keys/enc.key /dev/vdb2 /etc/keys/backup.key
删除一个密钥文件或密码
使用luksRemoveKey
操作,可以删除密钥文件或密码(因此它们不能再用于解密存储):
root #
cryptsetup luksRemoveKey /dev/vdb2
Enter LUKS passphrase to be deleted: ...
或者删除密钥文件:
root #
cryptsetup luksRemoveKey -d /etc/keys/backup.key /dev/vdb2
确保至少有一种访问数据的方法仍然可用。一旦使用的密码或密钥文件被删除,就无法再次恢复。
清空一个插槽
Suppose the passphrase or keyfile is no longer known, then the slot can be freed. Of course, this does require prior knowledge of which slot that the passphrase or keyfile was stored in. 假设密码或密钥文件已遗失,则可以释放插槽。当然,这需要事先知道密码或密钥文件存储在哪个插槽中。
例如,要清空插槽2(这是第3个插槽,因为插槽从0开始编号):
root #
cryptsetup luksKillSlot /dev/vdb2 2
此命令将在继续之前要求输入有效的密码。或者可以传递密钥文件以使用:
root #
cryptsetup luksKillSlot -d /etc/keys/enc.key /dev/vdb2 2
自动挂载加密文件系统
到目前为止,本文主要关注加密文件系统的手动设置和挂载/卸载。存在一个init服务dmcrypt,它自动解密和挂载加密文件系统。
配置 dm-crypt
编辑/etc/conf.d/dmcrypt文件并为每个文件系统添加条目。支持的条目在文件中有详细记录,下面的示例只是 - 示例:
# Definition for /dev/mapper/home (for /home)
target=home
source=UUID="abcdef12-321a-a324-a88c-cac412befd98"
key=/etc/keys/home.key
# If trim is desired, it can be enabled like this.
# Keep in mind that trim is not enabled by default for a security reason.
options="--allow-discards"
# Definition for /dev/mapper/local (for /usr/local)
target=local
source=UUID="fedcba34-4823-b423-a94c-cadbefda2943"
key=/etc/keys/local.key
# Using an encrypted partition as key source.
target=other
source=UUID="ff24303e-49e1-4d13-b8ad-fc6b7e1d8174"
key=/keys/other.key # Relative to the root of the encrypted partition.
remdev=/dev/mapper/home # The recently decrypted partition.
# An empty line is important at the end of the file
If using passphrase instead of a keyfile, you'll be prompted for it on boot (given a simple target and source configuration).
配置fstab
下一步是将/etc/fstab配置为,在(解密的)文件系统可用时自动挂载。建议首先获取解密(已挂载)文件系统的UUID:
root #
blkid /dev/mapper/home
/dev/mapper/home: UUID="4321421a-4321-a6c9-de52-ba6421efab76" TYPE="ext4"
然后,相应的更新/etc/fstab文件。
UUID="4321421a-4321-a6c9-de52-ba6421efab76" /home ext4 defaults 0 0
UUID="bdef2432-3bd1-4ab4-523d-badcf234a342" /usr/local ext4 defaults 0 0
将initscript添加到bootlevel
不要忘记在boot启动时启动dmcrypt init服务:
root #
rc-update add dmcrypt boot
Make decrypted device nodes visible
If you have decrypted/unlocked a device before the services were started for example your root disk in an with an initramfs then it's possible that the mapped device is not visible. In this case you can run the following to recreate it.
root #
dmsetup mknodes
挂载 TrueCrypt/tcplay/VeraCrypt 卷
root #
cryptsetup --type tcrypt open container-to-mount container-name
使用/dev的设备文件或要打开的文件的路径替换container-to-mount。成功打开后,明文设备将显示为/dev/mapper/container-name,您可以像任何普通设备一样mount
。
如果您使用的是密钥文件,请使用--key-file
选项。打开隐藏卷,使用--tcrypt-hidden
选项。对于在系统模式下加密的分区或整个驱动器,请使用--tcrypt-system
选项。
完成后,unmount
(卸载)卷,然后使用以下命令关闭容器:
root #
cryptsetup close container-name
另请参阅
- Full Disk Encryption From Scratch — a guide which covers the process of configuring a drive to be encrypted using LUKS and btrfs.
- Dm-crypt full disk encryption — a guide which covers the process of configuring a drive to be encrypted using LUKS and btrfs.
- User:Sakaki/Sakaki's EFI Install Guide/Preparing the LUKS-LVM Filesystem and Boot USB Key
外部资源
- The cryptsetup FAQ hosted on GitLab covers a wide range of frequently asked questions.