安全擦除磁盘
擦除磁盘是通过将新数据写入每个位来完成的。
常用用例
擦除设备上遗留的所有数据
完全且不可撤销地擦除设备的最常见用例是设备将被赠送或出售时。设备上可能遗留(未加密的)数据,您希望防止简单的取证调查,例如使用 文件恢复 软件,这只是小菜一碟。
如果您想快速擦除磁盘上的所有内容,/dev/zero
或简单模式可实现最大性能,而在某些情况下,足够的随机性可能是有利的,这应在 #数据残留 中介绍。
每个被覆盖的位都意味着提供一定级别的数据擦除,不允许使用正常的系统功能(如标准的 ATA/SCSI 命令)和硬件接口进行恢复。上述任何文件恢复软件都需要专门针对专有的存储硬件功能。
在 HDD 的情况下,如果没有至少未公开的驱动器命令或篡改设备的控制器或固件以使其读出例如重新分配的扇区(S.M.A.R.T. 停用的坏块),则不可能重建数据。
不同的物理存储技术存在不同的擦除问题。最值得注意的是,所有基于闪存的设备和较旧的磁存储设备(旧 HDD、软盘、磁带)。
块设备加密的准备工作
为了之后在擦除区域内准备用于 块设备加密 的驱动器,建议使用由密码学上强大的随机数生成器(在本文中从现在开始称为 RNG)生成的 #随机数据。
另请参见 Wikipedia:随机数生成。
数据残留
另请参见 Wikipedia:数据残留。即使在尝试删除或擦除数据之后,数据的表示形式也可能仍然存在。
操作系统、程序和文件系统
操作系统、执行的程序或 日志文件系统 可能会在整个块设备中复制您的未加密数据。当写入普通磁盘时,这仅应与上述之一相关。
如果数据可以精确定位在磁盘上并且从未复制到其他任何地方,则使用伪随机数据进行擦除可以彻底且非常快速。
一个很好的例子是 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 介质(USB、CD、PXE 等)启动,或者使用脚本 防止因输入错误而擦除已挂载的分区。
选择数据源
要擦除敏感数据,可以使用任何符合需求的数据模式。
零
在大多数情况下,用 /dev/zero
或简单模式覆盖被认为是安全的。对于今天的 HDD,它被认为是适合且快速的磁盘擦除方式。
但是,写入模式或归零速度异常快的驱动器可能正在进行透明压缩。显然可以推测并非所有块都以这种方式擦除。一些 #闪存 设备确实有这种“功能”。
为了之后设置块设备加密,应该使用随机数据(见下一节)擦除该区域,以避免削弱加密强度。
随机数据
/dev/urandom
可以用作来自 Linux 内核的密码学安全伪随机数据的快速安全来源。有关随机和伪随机数据源的更多详细信息,请参见 随机数生成。
在过去,当内核的随机数生成器速度较慢时,伪随机数据生成的一种常见替代方法是使用加密数据流,例如通过使用随机密钥加密 /dev/zero
。虽然这在理论上应该是安全的,但它不再比内核新的、更快的随机数生成器有任何优势,并且存在临时密钥可能意外保存在某处的风险。
选择块大小
另请参见 Wikipedia: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
在这里,为了用一个实际示例进行说明,我们将展示 fdisk 命令在分区 /dev/sdX
上的输出
# 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/Drive 准备#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 的常用方法