此方法旨在加密资产之前先擦除其内容。 如果您已经打算加密的磁盘上有数据,您应该将其临时复制到其他地方,然后在设置加密后将其移回。 原位加密数据是可能的,但目前我认为这种魔法对于本指南来说太高级了。 如果您对该方法感兴趣,请参阅loop-AES的README了解更多详情。
要执行以下操作,您需要运行一个具有loop-AES内核的系统。 如果您还没有,我建议使用KNOPPIX。 它从CD-ROM启动,不需要安装,所以几乎没有麻烦。
为了简单起见,这些说明假设您将在同一台计算机上准备钥匙链和资产,但这并非必须如此。 根据您的方便程度调整说明。
如果您采用仅加密文件而不是磁盘或分区的方法,您可以跳过本节,直接转到第2.2节。
在理想的设置中,您将使用可启动的钥匙链设备,例如USB闪存驱动器或名片大小的CD-ROM。 这是因为我们希望尽可能少地暴露您的磁盘,但我们将不得不暴露一个最小的引导过程,否则计算机将永远无法启动。 由于引导过程必然是未加密的,因此最好将其从您的计算机上移开(在您的钥匙链上)。 如果由于某种原因您不能或不想使用可启动的钥匙链,那么无论如何请按照这些说明进行操作,但将其应用于磁盘上的一个小型启动分区,而不是钥匙链。
在下面的示例中,钥匙链显示为第一个SCSI驱动器/dev/sda。 替换/dev/sda为您的驱动器对应的设备。
第一步——将钥匙链清零——在技术上是不必要的,但如果您按照第2.4节中的建议将其备份为映像,这将使钥匙链备份更小。
bash# dd if=/dev/zero of=/dev/sda
接下来,像分区任何可引导磁盘一样分区钥匙链。 如果您需要分区方面的帮助,请参阅Linux分区指南。
bash# cfdisk /dev/sda
在第一个分区上放置一个文件系统。
bash# mkfs /dev/sda1
挂载钥匙链。
bash# mkdir /tmp/keychain bash# mount /dev/sda1 /tmp/keychain bash# cd /tmp/keychain
如果您使用钥匙链连接多台计算机,您可能需要为每台计算机构建不同的内核。
您可能需要为您的钥匙链构建一个自定义内核,以便您可以确保两件事
它已正确地用loop-AES打补丁,并且启用了加密支持。
启动计算机并使资产可访问所需的所有设备驱动程序都已编译到内核中,而不是作为模块加载。
您可以将设备驱动程序作为模块加载,因为我们正在使用initrd,但我选择将它们编译到内核中,以便使启动盘尽可能简单。 随意以不同的方式进行操作。
有关构建自定义内核的帮助,请阅读Linux内核指南。 请务必设置CONFIG_BLK_DEV_RAM在内核配置中,以便可以使用initrd启动。
按照loop-AES随附的说明构建新的循环驱动程序。 还要按照说明重建util-linux工具,其中一些工具稍后我们将复制到钥匙链。 您的发行版可能已经为您构建了它们(例如,参见loop-aes-utils和loop-aes-sourceDebian中的软件包)。
构建内核后,将其复制到钥匙链。
bash# mkdir boot bash# cp arch/i386/boot/bzImage boot/vmlinuz-laptop
安装GRUB或您喜欢的引导加载程序。
bash# grub-install --root-directory=. /dev/sda
这是一个示例menu.lst为GRUB。 它有两台名为laptop和desktop的计算机的条目。
![]() | 需要将密钥名称(我建议您以计算机命名)作为第一个参数传递给linuxrc。 |
我们使用initrd启动钥匙链,以便我们可以在引导过程开始后将其删除(谁希望在咖啡馆里试图看起来很酷的时候,USB闪存驱动器挂在笔记本电脑上?)。 为了获得对资产的访问权限,我们创建了一个连接到initrd的/dev/loop0的环回设备。 将设备文件放在initrd上意味着initrd必须在挂载资产时保持挂载状态(没什么大不了的)。
要了解有关制作初始RAM磁盘的所有信息,欢迎您阅读Linux启动盘指南和Linux的Documentation/initrd.txt,或者不要麻烦,只需按照操作即可。
我们首先选择4MB作为初始RAM磁盘的大小,我们不需要所有这些,但它是传统的最大大小(并且没有害处),所以少做了一个决定。
bash# head -c 4m /dev/zero > boot/initrd bash# mke2fs -F -m0 -b 1024 boot/initrd
挂载initrd以便我们可以对其进行处理。
bash# mkdir /tmp/initrd bash# mount -o loop=/dev/loop3 boot/initrd /tmp/initrd bash# cd /tmp/initrd
创建我们将需要的最小目录结构。
bash# mkdir -p {bin,dev,lib,mnt/{keys,new-root},usr/sbin,sbin}
创建我们将需要的最小设备集。 请注意,tty对于密码提示是必需的。 此命令假定您的资产是驱动器/dev/hda。 根据需要进行更改。
bash# cp -a /dev/{console,hda,loop0,loop1,tty} dev
我们将复制我们需要的六个程序。
![]() | 您可以使用which查找程序的完整路径名,例如
|
复制程序
bash# cp /bin/{mount,sh,umount} bin bash# cp /sbin/{losetup,pivot_root} sbin bash# cp /usr/sbin/chroot usr/sbin
使用ldd找出每个程序使用哪些共享库
bash# ldd /bin/{mount,sh,umount} /sbin/{losetup,pivot_root} /usr/sbin/chroot /bin/mount: libc.so.6 => /lib/libc.so.6 (0x40023000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) /bin/sh: libncurses.so.5 => /lib/libncurses.so.5 (0x40020000) libdl.so.2 => /lib/libdl.so.2 (0x4005c000) libc.so.6 => /lib/libc.so.6 (0x4005f000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) /bin/umount: libc.so.6 => /lib/libc.so.6 (0x40023000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) /sbin/losetup: libc.so.6 => /lib/libc.so.6 (0x40023000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) /sbin/pivot_root: libc.so.6 => /lib/libc.so.6 (0x40023000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) /usr/sbin/chroot: libc.so.6 => /lib/libc.so.6 (0x40023000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
复制库。 在我的系统上,我复制了这些库(您的系统可能不同)
bash# cp /lib/{ld-linux.so.2,libc.so.6,libdl.so.2,libncurses.so.5} lib
您可以根据需要多次重复这些步骤,以使用同一钥匙链处理多台计算机。 每台计算机都有自己的密钥,可能还有自己的内核。 此处的说明假定计算机的名称为laptop; 每次重复这些步骤时,请替换为您正在使用的计算机的名称。
首先,备份您的数据。 请参阅Linux完整备份和恢复指南。
不,停下来,听我说。 备份你的数据。 真的。 如果您由于犯了一些错误而无法解密它,那么拥有一个加密的硬盘就不好玩了。 这些工具是强大的魔法; 如果你搞砸了,你不能只是打电话给Computer Gurus Are Us并期望他们帮你找回你的数据。 这就是这项练习的全部意义。
如果您正在加密整个磁盘(推荐),请替换/dev/hda为您的磁盘对应的设备。
bash# ln -s /dev/hda /tmp/asset
如果您正在加密分区(多重引导情况),请替换/dev/hda3为您的分区对应的设备。
bash# ln -s /dev/hda3 /tmp/asset
如果您只加密文件,请替换~/encrypted为文件名并创建一个名为/tmp/keychain的链接,该链接指向您决定存储密钥文件的位置(一个已经准备好的可移动介质,例如/mnt/cf).
bash# ln -s ~/encrypted /tmp/asset bash# ln -s /mnt/cf /tmp/keychain
使用随机数据初始化资产。 这将使攻击者不太容易发现哪些部分是可用空间。
bash# shred -n 1 -v /tmp/asset
在这里,我们创建一个加密文件系统来保存密钥。 你说,更多的加密? 是的,以防您的钥匙链被盗(请参阅表1),您不希望您的密钥被暴露。 我选择1MB作为文件系统的大小,因为它是一个整数。 我们不可能需要那么多的空间来存储密钥,所以如果您愿意,可以自由选择更小的大小(每个密钥文件长61字节)。
同样,使用随机数据初始化。
bash# cd /tmp/initrd bash# head -c 1m /dev/urandom > keys
为了使密码抵抗字典攻击,我们将生成一个种子。 无论何时看到符号<seed>请务必将其替换为您生成的种子。 以下命令将在屏幕上显示一个随机种子。
bash# head -c 15 /dev/random | uuencode -m - | head -2 | tail -1
使用种子设置环回设备。 在这里您可以选择您的密码,密码长度必须至少为20个字符。 小心选择一个您知道您不会忘记的密码。 您可能想使用Diceware方法来选择安全的密码。
bash# losetup -e AES128 -C 100 -S <seed> -T /dev/loop1 keys
格式化并挂载密钥文件系统(decrypt.sh脚本假定您在此处使用ext2文件系统)。
bash# mke2fs /dev/loop1 bash# mkdir /tmp/keys bash# mount /dev/loop1 /tmp/keys
现在是实际的资产密钥,45个字节,尽可能随机地由您的计算机生成。 尝试针对它进行字典攻击,攻击者! 哈! 我们以将要使用密钥的计算机(laptop)命名密钥。 替换为您的计算机的名称。
bash# head -c 45 /dev/random | uuencode -m - | head -2 | tail -1 > /tmp/keys/laptop
使用密钥设置环回设备以加密访问资产。
bash# losetup -e AES128 -p 0 /dev/loop0 /tmp/asset < /tmp/keys/laptop
卸载密钥文件系统。
bash# umount /tmp/keys bash# losetup -d /dev/loop1
如果您只加密文件,请跳过本节。
至关重要的是给予mkswap此处的大小参数,因为我们没有向其提供专用分区。 选择您想要的任何大小; 我选择了2GB。
bash# mkswap /dev/loop0 $((2*1024*1024)) mkswap: warning: truncating swap area to 2097144kB Setting up swapspace version 1, size = 2147471360 bytes
如果您只加密文件,请使用如下文件系统对其进行格式化,然后跳到第2.3节。
bash# mkfs /dev/loop0
我们将在交换空间之后创建根“分区”。 我把“分区”这个词放在引号里,因为它不是一个真正的分区。 我们使用losetup.
的偏移量参数来伪造它。mkswap如何告诉我们交换空间的实际大小,这不一定是请求的大小。 指定开始根文件系统的偏移量时,请使用实际大小(在以上示例中为2147471360)。
bash# losetup -o <root offset> /dev/loop1 /dev/loop0
如果资产是整个磁盘或磁盘上的最后一个分区,那么我们无需担心为文件系统指定大小。如果这适用于你,请执行以下操作并跳到第 2.2.2.1 节。
bash# mkfs /dev/loop1
由于资产不是磁盘上的最后一个分区,我们必须给mkfs一个大小限制,否则它会覆盖此分区和磁盘末尾之间所有分区上的数据。我重复一遍,如果你不在此处为mkfs提供正确的大小参数,你可能会丢失数据。mkfs实际上只是一个前端,所以为了尽可能谨慎,我们将选择一个实际的文件系统创建器,在本例中是mke2fs.
可以通过指定块的大小来限制文件系统的大小,但是mke2fs根据文件系统的大小选择块大小。 这是一个经典的Catch-22! 我们可以要求它在磁盘的其余部分(超过我们想要的)上进行试运行,以查看它将选择的块大小。
bash# mke2fs -n -j /dev/loop1 mke2fs 1.34-WIP (21-May-2003) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) 9781248 inodes, 19544448 blocks 977222 blocks (5.00%) reserved for the super user First data block=0 597 block groups 32768 blocks per group, 32768 fragments per group 16384 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424
在本例中,它选择了 4096。无论它选择什么,对于我们的文件系统来说都可能足够接近。 计算块中的正确大小。
文件系统大小 = (分区大小 - 交换空间大小) / 块大小
假设分区的大小为 10GB,交换空间的大小为 2GB。 的正确大小mke2fs是 (10 − 2) * 230 / 4096 = 2097152。 不要弄错! 备份! 三思而后行!
bash# mke2fs -j /dev/loop1 2097152
挂载新的根文件系统并创建initrd挂载点。 这对于 linuxrc 脚本调用pivot_root.
bash# mount /dev/loop1 mnt/new-root bash# mkdir mnt/new-root/initrd bash# umount mnt/new-root
我们有足够的信息来创建解密脚本。 更改开头的变量以反映你的设置(包括你之前生成的种子)。
如果你要加密整个磁盘或分区,请设置ROOT_OFFSET为你从获得的尺寸mkswap。 将脚本放在/tmp/initrd并命名为decrypt.sh.
如果你仅加密文件,则此脚本可以位于任何位置。 在这种情况下,请务必设置ROOT_OFFSET为零并设置MOUNT到一个方便的挂载点(可能不是/mnt/new-root).
图 1./tmp/initrd/decrypt.sh
#!/bin/sh SEED=<seed> ASSET=/dev/hda ROOT_OFFSET=<root offset> ROOT_TYPE=ext3 MOUNT=/mnt/new-root KEY="$1" # Ask for a passphrase to open the keys (this prevents exposure of the keys in # case the owner loses the keychain). Give the user three tries to get the # passphrase right. for ((FAILED=1, TRY=1; ($FAILED != 0) && (TRY <= 3); TRY++)) do mount -n -t ext2 -o loop=/dev/loop1,encryption=AES128,itercountk=100,pseed=$SEED keys /mnt/keys FAILED=$? done if [ $FAILED -ne 0 ]; then echo "Sorry, you get only three attempts to guess the password." exit 1 fi # Use the key to decrypt the asset. losetup -e AES128 -p 0 /dev/loop0 $ASSET < "/mnt/keys/$KEY" # Close the keys. umount -n /mnt/keys losetup -d /dev/loop1 # Set up the root "partition" device. losetup -o $ROOT_OFFSET /dev/loop1 /dev/loop0 # Mount the root file system (read-only, so it can be checked with fsck). mount -n -r -t $ROOT_TYPE /dev/loop1 $MOUNT |
使脚本可执行。
bash# chmod +x decrypt.sh
如果你只加密文件,请跳到 第 2.4 节。 否则,将以下启动脚本另存为linuxrc并将其放置在/tmp/initrd.
图 2./tmp/initrd/linuxrc
#!/bin/sh # Decrypt the asset source decrypt.sh "$1" # Pivot to the asset's root file system. cd $MOUNT /sbin/pivot_root . initrd # Pass control to init. shift 1 exec chroot . /sbin/init $* <dev/console >dev/console 2>&1 |
使脚本可执行。
bash# chmod +x linuxrc
好的,密钥链和资产现在已准备就绪。 卸载所有内容。
bash# umount /tmp/{initrd,keychain}
你现在有一个空的,加密的文件系统。 万岁!
通过启动密钥链或根据需要执行 decrypt.sh 脚本来测试你的系统(将其要用作参数的密钥的名称赋予它)。 启动后,可能会出现有关不存在的/sbin/init的抱怨,但现在没关系。
检查以确保你的根文件系统已成功挂载。 当你确信一切正常时,备份你的密钥链。 实际上,进行大量备份。 你可能会问:“但是,在某处拥有密钥链的副本不是不安全的吗?” 答案是肯定的,但是,如果将安全性定义为也意味着“确保访问我的数据”,则不如丢失唯一的密钥链那么不安全。
因为我的密钥链很小,所以我决定备份整个镜像,以便易于恢复
bash# bzip2 -c /dev/sda > keychain.img.bz2
如果你仅加密文件,则此时可以拍拍自己的后背,因为你已完成。
当系统无法正常运行和/或拒绝启动时,救援磁盘很有用。 检查以确保你的救援磁盘在其内核中具有 loop-AES 支持,并且具有正确修补的 util-linux 工具,例如losetup和mount,否则它将对你新加密的资产毫无价值。 将来,所有救援磁盘都将包含此支持,因为它将成为 2.6 内核的标准配置。 同时,KNOPPIX(例如)已经具有所有必要的支持,可以用作救援磁盘。
启动适当的救援磁盘后,挂载你的密钥链并执行 decrypt.sh 脚本。
bash# mkdir /tmp/{keychain,initrd} bash# mount /dev/sda1 /tmp/keychain bash# mount -o loop=/dev/loop3 /tmp/keychain/boot/initrd /tmp/initrd bash# pushd /tmp/initrd bash# ./decrypt.sh laptop bash# popd bash# umount /tmp/{initrd,keychain}
现在,你可以通过在 decrypt.sh 中指定的挂载点访问你的资产。
你的最终任务是将 Linux 安装到新的加密文件系统中。 执行此操作时,请确保你的/etc/fstab中根目录和交换区的条目看起来像下面这样
# /etc/fstab: static file system information. # # <file system> <mount point> <type> <options> <dump> <pass> /dev/loop0 none swap sw 0 0 /dev/loop1 / ext3 errors=remount-ro 0 1 |
如果你已经在其他地方进行了安装,请阅读 硬盘升级迷你指南,以了解如何将其复制过来。
对于每个发行版,全新安装 Linux 的过程都不同。 请给我发送下面未列出的发行版的说明,我将在此处包括它们。
按照 第 2.5 节中的说明从救援磁盘启动。
使用方法 3.7 从 Unix/Linux 系统安装 Debian GNU/Linux 进行安装。
按照 第 2.5 节中的说明从救援磁盘启动(Gentoo 的 Live CD 1.4 将无法工作)。
如果创建了交换分区,则激活它。
bash# swapon /dev/loop0
将/mnt/gentoo指向根文件系统。
bash# ln -s new-root /mnt/gentoo
跳到 第 8 章。Stage tarballs and chroot,位于 Gentoo Linux 1.4 安装说明中。
系统启动并运行后,考虑将其配置为在一段时间不活动后自动注销。 这将减少(但不能消除)在笔记本电脑开启时被盗时暴露资产的风险(请参阅 表 1)。