我想使用 cryptsetup 对具有 ext4 文件系统的容器中的目录内容进行加密。容器的大小应该尽可能小,必要时尽可能大,因为我只想写一次然后备份。
首先尝试:将容器的大小设置为内容的大小。
dirsize=$(du -s -B512 "$dir" | cut -f 1)
dd if=/dev/zero of=$container count=$dirsize
losetup /dev/loop0 $container
fdisk /dev/loop0 # 1 Partition with max possible size
cryptsetup luksFormat --key-file $keyFile /dev/loop0
cryptsetup luksOpen --key-file $keyFile /dev/loop0 container
mkfs.ext4 -j /dev/mapper/container
mkdir /mnt/container
mount /dev/mapper/container /mnt/container
rsync -r "$dir" /mnt/container
Rsync 返回没有足够的空间来容纳数据。看起来很合理,因为加密和文件系统必须有一些开销。
我尝试使用相对偏移量:
dirsize=$(($dirsize + ($dirsize + 8)/9))
这可以解决大于 100 MB 的目录的问题,但不能解决小于 50 MB 的目录的问题。
如何确定容器必须比目录大的相应字节数?
答案1
LUKS 默认使用 2 MiB 作为其标头,主要是由于数据对齐原因。您可以使用cryptsetup luksDump
(Payload offset:
在扇区中)进行检查。如果您不关心对齐方式,则可以使用该--align-payload=1
选项。
至于ext4
,就复杂了。它的开销取决于文件系统大小、索引节点大小、日志大小等。如果您不需要日记,您可能更喜欢ext2
。其他文件系统的开销可能比 少ext*
,可能值得尝试。另外,一些mkfs
标志(类似-T largefile
或类似)可能会有所帮助,具体取决于您要放置在该东西上的文件类型。例如,如果您只想在其中放置十几个文件,则不需要创建具有一百万个索引节点的文件系统。
如果您希望容器尺寸最小,可以从一个较大的容器开始,然后将resize2fs -M
其缩小到最小尺寸。然后,您可以使用该大小加上LUKS 的truncate
容器。Payload offset:
这应该非常接近小,如果您需要它更小,请考虑使用tar.xz
而不是文件系统。虽然tar
对于数百 GB 的数据来说不是很好(需要提取所有内容才能访问单个文件),但对于您提到的大小来说应该没问题,并且应该小于大多数文件系统......
答案2
“LUKS 有 1032 个扇区(一个扇区为 512 字节)开销,用于存储 LUKS 标头。在标头之后,加密数据仅占用与其解密对应数据一样多的空间,呈线性”
答案3
很难预测文件系统的确切大小,因为文件系统包含的内容不仅仅是文件本身。看为什么有这么多不同的方法来测量磁盘使用情况?有关磁盘使用的一些微妙之处。尤其:
- 每个文件都以不完整的块结尾。运行
du
会考虑到这一点,但您需要省略该-B
参数,并且仅当您运行它的文件系统具有与您要复制文件的文件系统相同的块大小时才适用。 - 文件系统还需要包含索引节点和其他数据结构(超级块、日志……)。
如果您跟踪文件的数量并创建那么多的 inode,并将块的大小和 inode 的大小相加,您就会对文件系统的大小有一个很好的了解。但如果你希望它非常严格,就需要进行一些尝试和错误。
找到最小 ext2 映像大小的最简单方法是创建一个足够大的 ext4 映像,然后用于resize2fs
缩小它。
如果您正在制作一个可在 Linux 下读回的只读文件系统,南瓜文件系统将是比 ext4 更好的选择。
Dm-crypt 本身也有开销。这在常问问题。默认情况下,cryptsetup
在卷的开头保留 2MB 用于元数据(常见问题解答 2.18);开销与卷大小无关。 FAQ 6.12 和 6.13 解释了如何减少开销。选择 128 位密钥大小(为了安全起见,您需要这么多,不再需要更多),除了固定大小的标头 (544B) 之外,还需要 512kB 的密钥槽。选择尽可能小的对齐方式,或接近它的对齐方式;我认为,对于块大小为 4kB 的文件系统,如果使用小于 4kB 的对齐方式,性能将会受到较小的影响,而且 4kB 在该规模上可以忽略不计,因此我建议使用 4kB 对齐方式,以获得总开销的516kB。创建卷时的选项包括
cryptsetup luksFormat -s 128 --align-payload=8 --key-file $keyFile /dev/loop0