安全擦除磁盘
擦除磁盘是通过在每个位上写入新数据来完成的。
常见用例
擦除设备上遗留的所有数据
完全且不可撤销地擦除设备最常见的用例是设备将被赠送或出售时。设备上可能遗留有(未加密的)数据,您希望防止简单的司法调查,例如使用 文件恢复 软件,这简直是小菜一碟。
如果您想快速擦除磁盘上的所有内容,/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 Media(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/驱动器准备#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 迭代地在文件或磁盘设备上写入模式,以使检索数据更加困难。
以下命令使用默认设置调用 scrub,在模式 1 中,使用符合 NNSA Policy Letter NAP-14.x 的模式覆盖目标设备。这是最有效的方法。
$ scrub /dev/sdX
以下命令使用默认设置调用 scrub,在模式 2 中,使用符合 NNSA Policy Letter NAP-14.x 的模式覆盖目标文件,将写入的字节数向上舍入以填充最后一个文件系统块。请注意,此模式存在注意事项,请参阅 manual 以获取更多详细信息。
$ scrub /path/to/file # where file is a regular file
以下命令使用默认设置调用 scrub,在模式 3 中,创建一个目录并用文件填充它,直到文件系统已满。然后使用符合 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 的常用方法