我可以用解密的内容覆盖 LUKS 分区吗?

我可以用解密的内容覆盖 LUKS 分区吗?

我的硬盘上有我的数据(其他硬盘上可用的最重要数据的部分备份),目前它的格式为 Ext4 over LVM over LUKS。我想删除 LUKS 层,但重新格式化和从备份恢复数据太长/没有乐趣。是否有可能/机会在不使用大缓冲区且不损坏数据的情况下用其内容覆盖 LUKS 分区?

答案1

无论如何,您都必须复制所有数据。此时您绝对应该有备份。除非您的备份设备比活动磁盘慢得多,否则从备份恢复的速度会尽可能快。

LUKS 卷以标头 (最大 2MB)。如果丢失标头,卷中的数据就会丢失。只要标头完好无损,就可以访问独立的 512 字节扇区中的数据。

像这样的策略cat /dev/mapper/encrypted >/dev/sdz99将会起作用,因为密文位于相对于明文的正偏移量(标头大小)处。但是,这可能比从备份恢复慢,因为它是同一磁盘上的副本(使用磁盘到磁盘的复制,读取和写入是并行完成的)。对于同一磁盘副本,dd具有大块大小的速度仅比cat。此策略有一个主要警告:如果在复制过程中出现电源故障或其他系统崩溃,您的整个分区将被冲洗,因为标头已首先被覆盖。

您可以将前 2MB 数据保存在其他位置,然后移动其余数据:

dd if=/dev/mapper/encrypted of=/dev/sdz99 bs=2M skip=1 seek=1

这样,您可以在中断后恢复(但不要尝试组装逻辑卷,更不用说挂载文件系统了!);然而这需要知道你从哪里停下来的。这实际上是不可能确定的(您必须使用复制工具来输出正在复制的块的踪迹,并将其与块副本同步写入磁盘)。

如果您的备份存储非常慢,那么您可以使用这种转移策略(简单的cat转移即可),并在发生任何问题时回退到从备份进行恢复。

如果备份存储确实很笨重,那么另一种方法是:

  1. 缩小文件系统 ( resize2fs)。
  2. 缩小逻辑卷 ( lvreduce)。
  3. 缩小物理体积 ( pvresize)。
  4. 缩小加密卷
  5. 缩小分区(fdiskgdisk),并在释放的空间中创建一个新分区。
  6. 在新分区 ( pvcreate) 中创建物理卷并将其添加到卷组 ( vgextend)。
  7. 将尽可能多的物理盘区移出加密卷 ( pvmove)。
  8. 如果加密卷不为空,请从步骤 1 开始重复。
  9. 摆脱现在未使用的物理卷(vgreduce然后pvremove)。

又长又曲折?是的。再次强调,我的建议是从备份中恢复。

答案2

LUKS 在大小通常为 2MiB 的卷上放置标头。

因此,您可以使用 将打开的 LUKS 卷内容复制到 LUKS 基本卷dd

请注意,如果在复制过程中断电,您将留下无法破译的数据,因为卷标头将丢失。

如果只有一小部分卷被数据覆盖,那么缩小 LUKS 卷、在其后面创建一个新卷并在文件系统级别复制数据可能会更快(cp -a)。

答案3

简短回答:这是可能的,但我不会对我的数据这样做,因为无法保证数据安全和低速(转换我的 1TB 磁盘可能需要大约 10 小时)

长话短说:

我决定在 VirtualBox 虚拟机中检查这一点,并附加 2GB 虚拟 HDD 卷作为 /dev/sdb。我编写了一些脚本(参见答案末尾)来测试从文件系统堆栈中删除 LUKS 层。第二件重要的事情(第一件事是对数据进行完整备份)是将 LUKS 标头转储到外部存储并使用该外部标头打开 LUKS 卷(因为卷上的标头将被覆盖)。如果没有它,失败率约为 50%(4 次测试中有 2 次失败)。使用外部标头 4 of 4 测试成功...无论如何,我懒得做更多检查(我只检查了一个大文件的 md5sum),所以无法保证您的数据安全。如果您想使用它,您可能需要编辑脚本(与 行Disk=/dev/sdb

#!/bin/bash

Disk=/dev/sdb

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root. Exit"
   exit 1
fi
echo ----------------------------------------------------
echo "Removing old test data"
echo ----------------------------------------------------
vgremove test -f
umount -l /mnt/old
rm -rf /mnt/old
mkdir /mnt/old
umount -l /mnt/new
rm -rf /mnt/new
mkdir /mnt/new
rm -f /tmp/header
rm -f /tmp/key
echo ----------------------------------------------------
DiskCrypt="$(basename $Disk)_crypt"
echo "Creating LUKS device with name $DiskCrypt for disk $Disk"
echo ----------------------------------------------------
echo "password" > /tmp/key
cryptsetup -q luksFormat -c aes-xts-plain64 -s 512 -d /tmp/key $Disk
cryptsetup -q luksHeaderBackup $Disk --header-backup-file /tmp/header
cryptsetup -q luksOpen --header /tmp/header -d /tmp/key $Disk $DiskCrypt
echo ----------------------------------------------------
echo "Creating LVM volume group and logical volume"
echo ----------------------------------------------------
vgcreate test /dev/mapper/$DiskCrypt
lvcreate -n test -l 100%FREE test
pvdisplay
echo ----------------------------------------------------
echo "Format volume to Ext4"
echo ----------------------------------------------------
mkfs.ext4 /dev/mapper/test-test
mount /dev/mapper/test-test /mnt/old
chmod o+rwx /mnt/old
cd /mnt/old
rm -f ./test-file
echo ----------------------------------------------------
echo "Create file with random content to fill entire volume"
echo ----------------------------------------------------
dd if=/dev/urandom of=./test-file bs=64M
stat ./test-file
echo ----------------------------------------------------
echo "Checking MD5 sum"
echo ----------------------------------------------------
md5old=$(md5sum ./test-file)
# cp ./test-file /tmp/
cd /
umount -l /mnt/old
echo ----------------------------------------------------
echo "Disabling and exporting LVM volume group"
echo ----------------------------------------------------
vgchange -an test
vgexport test
echo ----------------------------------------------------
echo "Moving data using dd"
echo ----------------------------------------------------
dd if=/dev/mapper/$DiskCrypt of=$Disk bs=64M
cryptsetup -q luksClose $DiskCrypt
echo ----------------------------------------------------
echo "Importing LVM volume group and check file system"
echo ----------------------------------------------------
pvscan
vgimport test
vgchange -ay test
pvdisplay
# Device may be not ready yet
sleep 5
fsck -f /dev/test/test
resize2fs /dev/test/test
echo ----------------------------------------------------
echo "Checking MD5 sum"
echo ----------------------------------------------------
mount /dev/mapper/test-test /mnt/new
cd /mnt/new
stat ./test-file
md5new=$(md5sum ./test-file)
echo ====================================================
echo "Old File MD5 sum:"
echo "$md5old"
echo ====================================================
echo "New File MD5 sum:"
echo "$md5new"
echo ====================================================
if [ "$md5old" == "$md5new" ]
then
    echo "<< SUCCESS >>"
else
    echo ">> FAILED <<"
fi
echo ====================================================
cd /
umount -l /mnt/new

相关内容