安全擦除磁盘
擦除磁盘是通过在新数据上写入每一个比特位来完成的。
常见用例
擦除设备上遗留的所有数据
完全且不可撤销地擦除设备的最常见用例是设备将被赠送或出售时。设备上可能遗留有(未加密的)数据,您希望防止简单的取证调查,例如使用 文件恢复 软件,这只是小菜一碟。
如果您想快速擦除磁盘上的所有内容,/dev/zero
或简单模式可以实现最高的性能,而在某些应在 #数据残留 中涵盖的情况下,适当的随机性可能是有利的。
每个被覆盖的位都意味着提供一定级别的数据擦除,不允许使用正常的系统功能(如标准 ATA/SCSI 命令)和硬件接口进行恢复。上面提到的任何文件恢复软件都需要专门针对专有的存储硬件功能。
对于 HDD,如果不使用至少未公开的驱动器命令或篡改设备的控制器或固件以使其读取例如重新分配的扇区(S.M.A.R.T. 从使用中退役的坏块),则不可能重新创建数据。
不同的物理存储技术存在不同的擦除问题。最值得注意的是,所有基于闪存的设备和较旧的磁存储设备(旧 HDD、软盘、磁带)。
块设备加密的准备工作
为了在之后在擦除区域内准备用于 块设备加密 的驱动器,建议使用由密码学上强大的随机数生成器(在本文中从现在起称为 RNG)生成的 #随机数据。
另请参见 维基百科:随机数生成。
数据残留
另请参见 维基百科:数据残留。即使在尝试删除或擦除数据之后,数据的表示形式也可能仍然存在。
操作系统、程序和文件系统
操作系统、执行的程序或 日志文件系统 可能会在整个块设备中复制您的未加密数据。当写入普通磁盘时,这应该仅与上述之一相关。
如果数据可以精确定位在磁盘上,并且从未复制到其他任何地方,则使用伪随机数据擦除可能是彻底且非常快速的。
一个很好的例子是 cryptsetup 使用 /dev/urandom
来 擦除 LUKS 密钥槽。
硬件相关问题
闪存
写入放大 和其他特性使闪存(包括 SSD)成为可靠擦除的顽固目标。由于设备控制器芯片和操作系统所见的数据之间存在大量透明抽象,因此在原位永远不会覆盖可见数据,并且擦除特定块或文件不可靠。
其他“功能”,如透明压缩(所有 SandForce SSD),可以压缩您的零或重复模式,因此如果擦除速度快得令人难以置信,这可能是原因。
拆卸闪存设备、将芯片焊下并在没有控制器的情况下分析数据内容是可行的,使用 简单的硬件 即可轻松完成。数据恢复公司以低廉的价格做到这一点。
有关更多信息,请参见
标记为坏扇区
如果硬盘驱动器将扇区标记为坏扇区,它会将其隔离,并且该部分变得无法通过软件写入。因此,完全覆盖将无法到达它。但是由于块大小的原因,这些部分仅相当于几个理论上可恢复的 KiB。
剩余磁性
使用零或随机数据进行单次完全覆盖不会导致现代高密度存储设备上出现任何可恢复的数据。请注意,现在不必重复操作。[1] 其他指示指的是单个残留位;字节模式的重建通常是不可行的。[2] 另请参见 [3]、[4] 和 [5]。
选择目标
使用 fdisk 查找用户具有读取访问权限的所有读/写设备。
检查以设备(如 /dev/sdX
)开头的行输出。
这是一个格式化为启动 Linux 系统的 HDD 示例
# fdisk -l
Disk /dev/sda: 250.1 GB, 250059350016 bytes, 488397168 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00ff784a Device Boot Start End Blocks Id System /dev/sda1 * 2048 206847 102400 83 Linux /dev/sda2 206848 488397167 244095160 83 Linux
或另一个示例,其中 Arch Linux 映像写入到 4GB USB 拇指驱动器
# fdisk -l
Disk /dev/sdb: 4075 MB, 4075290624 bytes, 7959552 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x526e236e Device Boot Start End Blocks Id System /dev/sdb1 * 0 802815 401408 17 Hidden HPFS/NTFS
如果您担心主计算机上重要数据的意外损坏,请考虑使用隔离环境,例如虚拟机环境(VirtualBox、VMWare、QEMU 等),其中直接连接到它的磁盘驱动器或仅一台计算机,其中只有需要从 Live Media(USB、CD、PXE 等)启动的存储磁盘,或使用脚本 通过键入错误防止擦除已挂载的分区。
选择数据源
要擦除敏感数据,可以使用任何符合需求的数据模式。
零
在大多数情况下,使用 /dev/zero
或简单模式进行覆盖被认为是安全的。对于当今的 HDD,它被认为适合且快速用于磁盘擦除。
但是,在写入模式或归零方面异常快速的驱动器可能正在进行透明压缩。显然可以推测并非所有块都以这种方式擦除。一些 #闪存 设备确实“具有”该功能。
要在之后设置块设备加密,应使用随机数据(见下一节)擦除该区域,以避免削弱加密。
随机数据
/dev/urandom
可用作来自 Linux 内核的密码学安全伪随机数据的快速且安全来源。有关随机数据和伪随机数据源的更多详细信息,请参见 随机数生成。
过去,当内核的随机数生成器速度较慢时,伪随机数据生成的一种常见替代方法是使用加密的数据流,例如通过使用随机密钥加密 /dev/zero
。虽然这在理论上应该是安全的,但它不再比内核新的、更快的随机数生成器具有任何优势,并且存在临时密钥可能意外保存在某处的风险。
选择块大小
另请参见 维基百科:Dd (Unix)#块大小、blocksize io-limits。
如果您有 高级格式 硬盘驱动器,建议您指定大于默认值 512 字节的块大小。为了加快覆盖过程,请选择与您的驱动器物理几何结构匹配的块大小,方法是将块大小选项附加到 dd 命令(即 bs=4096
表示 4 KiB)。
fdisk 打印每个磁盘的物理和逻辑扇区大小。或者,sysfs 会公开信息
/sys/block/sdX/size /sys/block/sdX/queue/physical_block_size /sys/block/sdX/queue/logical_block_size /sys/block/sdX/sdXY/alignment_offset /sys/block/sdX/sdXY/start /sys/block/sdX/sdXY/size
genwipe.sh /dev/sdXY
。手动计算要擦除的块
块存储设备分为扇区,单个扇区的大小可用于计算整个设备的大小(以字节为单位)。为此,将扇区数乘以驱动器扇区大小。
例如,我们使用 dd 命令的参数来擦除分区
# dd if=data_source of=/dev/sdX bs=sector_size count=sector_number seek=partitions_start_sector status=progress
在这里,为了用一个实际示例进行说明,我们将显示分区 /dev/sdX
上 fdisk 命令的输出
# fdisk -l /dev/sdX
Disk /dev/sdX: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors Disk model: ST3500413AS Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes ... Device Boot Start End Sectors Size Id Type /dev/sdX1 2048 3839711231 3839709184 1,8T 83 Linux /dev/sdX2 3839711232 3907029167 67317936 32,1G 5 Extended
- fdisk 输出的第一行显示了磁盘大小(以字节和逻辑扇区为单位)。
- 存储设备或分区的大小也可以使用命令
blockdev --getsize64 /dev/sdXY
获得。 - fdisk 输出的 Units 行显示了单个逻辑扇区的大小;逻辑扇区大小也可以从字节数除以逻辑扇区数得出,此处使用:
echo $((2000398934016 / 3907029168))
。 - 要了解物理扇区大小(以字节为单位)(这将使其工作更快),我们可以使用下一行。
- 要获得以物理扇区为单位的磁盘大小,可以将以字节为单位的磁盘大小除以单个物理扇区的大小,此处为
echo $((2000398934016 / 4096))
,
- 在下面的示例中,我们将使用逻辑扇区大小。
- 您甚至可以使用
dd
命令擦除未分配的磁盘空间,方法是计算一个分区结尾和下一个分区开始之间的差值。
要擦除分区 /dev/sdX1
,将按如下方式使用逻辑扇区的示例参数。
- 通过使用设备上分区的起始地址,使用
seek=
参数
# dd if=data_source of=/dev/sdX bs=${BytesInSector} count=${End - Start} seek=${Start} status=progress
其中 Start=2048
,End=3839711231
和 BytesInSector=512
。
- 或者通过使用分区大小(以逻辑扇区为单位)
# dd if=data_source of=/dev/sdX1 bs=${BytesInSector} count=${LogicalSectors} status=progress
其中 LogicalSectors=3839709184
。
或者,要通过使用物理扇区来擦除整个磁盘
# dd if=data_source of=/dev/sdX bs=${PhysicalSectorSizeBytes} count=${AllDiskPhysicalSectors} seek=0 status=progress
其中 AllDiskPhysicalSectors=488378646
和 PhysicalSectorSizeBytes=4096
。
sdXY
或 sdX
)时,count=
选项不是必需的,但是当它尝试写入限制之外时,它会显示有关可用空间不足的错误。覆盖目标
您可以从多个实用程序中选择来覆盖驱动器。如果您只想擦除单个文件,安全擦除磁盘/技巧与窍门#擦除单个文件 除了下面提到的实用程序外,还有一些注意事项。
通过重定向输出
重定向的输出可用于创建文件、重写分区上的可用空间以及擦除整个设备或其上的单个分区。此处的示例使用 /dev/zero
将设备归零,但如果需要随机擦除,则可以使用 /dev/urandom
代替。
以下示例显示了如何通过重定向来自其他实用程序的 stdout 来重写分区或块设备
# cat /dev/zero > /dev/sdXY
cat: write error: No space left on device
# xz -z0 /dev/zero -c > /dev/sdXY
xz: (stdout): Write error: No space left on device
# dd if=/dev/zero status=progress > /dev/sdXY
dd: writing to ‘standard output’: No space left on device 20481+0 records in 20480+0 records out 10485760 bytes (10 MB, 10 MiB) copied, 2.29914 s, 4.6 MB/s
dd
另请参见 dd 和 安全擦除磁盘/技巧与窍门#擦除单个文件。
of=...
选项指向目标驱动器,而不是系统磁盘。通过使用 /dev/zero 流将零字节写入磁盘上的每个可寻址位置来零填充磁盘。
# dd if=/dev/zero of=/dev/sdX bs=4096 status=progress
或 /dev/urandom 流
# dd if=/dev/urandom of=/dev/sdX bs=4096 iflag=fullblock status=progress
当 dd 报告 设备上没有剩余空间
并返回控制权时,该过程完成
dd: writing to ‘/dev/sdX’: No space left on device 7959553+0 records in 7959552+0 records out 4075290624 bytes (4.1 GB, 3.8 GiB) copied, 1247.7 s, 3.3 MB/s
要加快擦除大型驱动器的速度,另请参见
- 安全擦除磁盘/技巧与窍门#dd - 高级示例,它使用 OpenSSL,
- 安全擦除磁盘/技巧与窍门#使用模板文件,它使用非随机预设数据擦除(例如,使用单个文件覆盖整个磁盘),但速度非常快
- Dm-crypt/驱动器准备#dm-crypt 特定方法,它使用 dm-crypt。
cp
文件复制命令 cp(1) 也可用于重写设备,因为它忽略目标类型
# cp /dev/zero /dev/sdXY
cp: error writing ‘/dev/sdXY’: No space left on device cp: failed to extend ‘/dev/sdXY’: No space left on device
pv
使用 pv 将显示进度条、花费的时间和完成的估计时间。将 选定的数据源 传递给 pv(1) 并使用 -o
/--output
选项指定将要写入的磁盘。例如,要使用 /dev/zero
填充磁盘 /dev/sdX
# pv /dev/zero -o /dev/sdX
wipe
一个专门用于擦除文件的程序。它作为 wipe 软件包的一部分提供。要快速擦除目标,您可以使用类似以下内容
$ wipe -r /path/to/wipe
另请参见 wipe(1)。该工具最后一次更新是在 2009 年。它的 SourceForge 页面 表明它目前未维护。
shred
shred(来自 coreutils 软件包)是一个 Unix 命令,可用于安全地删除单个文件或完整设备,以便只能使用专业的硬件(如果可能的话)非常困难地恢复它们。默认情况下,shred 使用三个遍,在每个遍期间将 伪随机数据 写入设备。这可以减少或增加。
以下命令使用其默认设置调用 shred 并显示进度。
# shred -v /dev/sdX
Shred 也可以在单个分区上使用,例如,要擦除第一个分区,请使用 shred -v /dev/sdX1
。
或者,可以指示 shred 仅执行一遍,使用例如 /dev/urandom
的熵,以及最终使用零进行覆盖。
# shred --verbose --random-source=/dev/urandom -n1 --zero /dev/sdX
scrub
scrub 迭代地将模式写入文件或磁盘设备,以使检索数据更加困难。
以下命令使用默认设置(在模式 1 中)调用 scrub,使用符合 NNSA Policy Letter NAP-14.x 的模式覆盖目标设备。这是最有效的方法。
$ scrub /dev/sdX
以下命令使用默认设置(在模式 2 中)调用 scrub,使用符合 NNSA Policy Letter NAP-14.x 的模式覆盖目标文件,将写入的字节数向上舍入以填充最后一个文件系统块。请注意,此模式存在注意事项,请参见 manual 以获取更多详细信息。
$ scrub /path/to/file # where file is a regular file
以下命令使用默认设置(在模式 3 中)调用 scrub,创建一个目录并使用文件填充它,直到文件系统已满。然后使用符合 NNSA Policy Letter NAP-14.x 的模式擦除文件,将写入的字节数向上舍入以填充最后一个文件系统块。请注意,此模式存在注意事项,请参见 manual 以获取更多详细信息。
$ scrub /path/to/dir # where dir is a new directory name.
有关更多用法和信息,请参见 manual。
badblocks
来自 e2fsprogs 的工具 badblocks 能够执行破坏性的读写测试,有效地擦除设备。默认情况下,它执行四个遍,并且可能需要很长时间。
# badblocks -wsv /dev/device
hdparm
hdparm 支持 ATA 安全擦除,其功能等同于零填充磁盘。但是,它由硬盘驱动器固件本身处理,并且包括“隐藏数据区域”。因此,它可以被视为现代的“低级格式化”命令。SSD 驱动器据报告在发出此命令后可实现出厂性能,但可能未被充分擦除(请参见 #闪存)。
某些驱动器支持增强型安全擦除,它使用制造商定义的独特模式。如果设备的 hdparm -I
输出指示增强型擦除具有多倍的时间优势,则该设备可能具有硬件加密功能,并且擦除将仅对加密密钥执行。
有关使用 ATA 安全擦除的详细说明,请参见 固态硬盘/内存单元清除 和 Linux ATA wiki。
blkdiscard
请参见 固态硬盘/内存单元清除#使用 blkdiscard 的常用方法