安全地擦除磁碟/提示和技巧 - Arch Linux 中文维基

跳至內容

# 安全地擦除磁碟/提示和技巧

出自 Arch Linux 中文维基
< 安全地擦除磁盘

翻譯狀態：

- 本文（或部分內容）譯自 Securely wipe disk/Tips and tricks，最近一次同步於 2025-08-08，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

主文章請見安全地擦除磁碟。

本文額外介紹了一些擦除工具，可替代專用擦除工具，並加快擦除速度。

警告：某些文件系統的保留塊不能通過創建文件的方式擦除，但可以使用工具 `tune2fs` 禁用。

## 擦除單個文件

警告：如果曾對存儲文件的分區進行了 碎片整理、調整大小或移動操作，或者文件曾在同一設備上被複製過，那麼擦除效果將受到影響。若數據存儲在加密容器上，並擦除整個加密容器，則文件恢復將變得困難得多，但加密可能會大幅降低 磁碟性能（除非使用硬體加密）。另見 安全地擦除磁碟#數據殘留。
注意：要在擦除時保留文件的訪問和修改時間不變，在修改文件前先使用stat(1)獲取文件當前的時間信息，之後可使用touch(1)手動修改文件時間。另請參閱不同文件系統對元數據和時間戳的支持情況。

本節將介紹擦除單個文件的兩種基本方法。此外，還有一種專門用於反取證的高級方法，其非常耗時，並且只能通過專用工具完成，本文不作介紹。

- 在刪除前用隨機數據覆寫，或在不改變文件大小的情況下用其他內容替換原內容。
- 使用專用工具擦除文件和文件系統存儲的元數據
  - 搜索整個磁碟，找到並清除已刪除文件的殘留部分，同時不對其它文件造成影響。

可以使用常見的 Linux 工具在不改變文件大小的情況下覆寫文件：

- 使用 `shred -x <目標文件>`， `-x`選項會用偽隨機數據替換文件的內容，且不改變文件大小。`-u` 選項會在覆寫後刪除文件。
- 使用 `mkfs` 可以將文件格式化為文件系統，掛載該文件系統後，任何對文件系統的修改都將反映到文件上，在文件系統上存儲其它內容，可達到覆蓋原始文件內容的目的。
- `dd` 可創建指定大小、內容的文件，若目標文件已存在，則直接會覆寫。通過組合 `skip` 和 `seek` 選項，可以將整個文件或文件的一部分替換為其他內容。在操作前，需要知道文件大小，以避免意外擴容文件。文件大小可以使用 `du -b <文件名> | cut -f1` 或 `stat -c "%s" <文件名>`獲取。注意使用`dd`時，必須指定 `iflag=fullblock` 選項，詳見 Dd#部分讀取：複製的數據量小於要求的大小。
- 使用 perl包 工具可以用單個符號（symbol）替換文件內容，同時避免文件大小發生變化。

要擦除文件的元數據，可以不斷創建新文件，直到填滿分區，這將迫使文件系統覆蓋舊的文件元數據條目，以存儲新創建文件的條目。此外，也可以使用專用工具。詳見#擦除可用空間。

組合使用提到的文件創建和轉換工具擦除文件內容，可達到避免文件被恢復、誤導恢復工具及其使用者（可通過覆寫隨機數據或預先定義好的其它內容實現）的目的。具體的組合方式可依情況和需求而定。

注意：

- 若存儲文件的文件系統還有可用空間，則簡單的覆寫操作可能無法清除文件的某些部分。
- 若要覆寫特定文件的內容，同時確保該文件在硬碟上的邏輯位置不變，可以先創建一個或多個文件將文件所在分區填滿，再使用合適的工具重寫或替換目標文件的內容。不過，如果分區的可用空間很多，而要覆蓋的文件很少，這會消耗大量時間。

例如：

使用Perl，用 `.` 替換文件中所有內容的：

    $ perl -p -i -e 's\[^*]\.\g' <文件名>

使用dd：

    $ <覆盖内容> | dd bs=<目标文件大小（字节）> count=1 iflag=fullblock of=<目标文件> seek=0

或者，也可使用stdout重定向。這種方式在創建文件時速度更快，但無法使用 `seek` 選項來跳過目標文件中的某些部分：

    $ <覆盖内容> | dd bs=<目标文件大小（字节）> count=1 iflag=fullblock > <目标文件>

提示：如果覆蓋內容長度小於目標文件，需將其與下文介紹的 `while` 循環結合使用。

另見：

- 轉換文本文件的字符集
- Advanced Bash-Scripting Guide - 描述使用 bash 腳本創建文件的高級方法
- sed alternatives - 一個 perl 示例，在替換文件內容方面比 sed 效果更好

## 覆寫目標

### 防止擦除已掛載的分區

選擇要擦除的設備時需要格外小心，簡單的拼寫錯誤就可能導致錯誤的目標被擦除，從而損壞系統。為了降低風險，可以使用腳本來包裝選定的擦除工具。例如：

    if [[ -e "$1" && -b "$1" ]];then
    NOT_safe="$(lsblk -o "NAME,MOUNTPOINT" ${1//[0-9]/} | grep -e / -e '\]')";
     if [[ -z "$NOT_safe" ]];then
    # 在这里你可以使用任何擦除工具擦除目标
    # 擦除目标由命令行传入，并存储在变量“$1”中
    #
      else
      echo 'Not allowed to destroy if any of the partitions is mounted: '"$NOT_safe"
     fi
    fi

### 使用dd進行高級擦除

在使用`dd`時，可以利用OpenSSL，使用隨機密碼進行AES加密，並將密文用於擦除目標，以實現隨機擦除：

    # DEVICE="/dev/sdX"
    # PASS=$(tr -cd '[:alnum:]' < /dev/urandom | head -c128)
    # openssl enc -aes-256-ctr -pass pass:"$PASS" -nosalt < /dev/zero | dd obs=64K ibs=4K of=$DEVICE oflag=direct status=progress

上述命令使用`/dev/urandom`生成128位元組的加密密鑰，並使用 CTR 模式的 AES-256 算法來加密 `/dev/zero` 的輸出。相比直接使用偽隨機源，使用加密算法可能可以獲得更快的寫入速度。最終設備將被 AES 密文填充。

上述命令將塊大小設置為 64K，通常比默認的 512 字節更快。還可以嘗試更大的塊大小，以找到適合硬體的最佳傳輸速率。參考 [1]及其中的參考文獻。

類似的方法還可參見 Dm-crypt/準備磁碟#dm-crypt_擦除空設備或分區。

### 使用模板文件

除了用零填充，還可以使用內容無關緊要的文件進行填充。若使用`mkfs`格式化了目標文件，需要掛載該文件系統，並使用特定內容填滿該文件系統（可以使用無關緊要的文件，或相關工具生成的重複輸出）。

一種方法是反覆使用模板文件進行擦除，直到設備末尾。若使用此方法，當出現到達設備末尾的錯誤時，必須手動使用停止鍵來中斷 `while` 循環，因而不推薦使用：

    $ while [ 1 -lt 2 ];do cat file1-to-use.as-template file2-to-use.as-template /tmp/templatefiles/* ;done > /dev/sd"XY"

若使用`dd`，如果通過選項正確設置了要擦除的大小，就可以安全地進行重複擦除，而不會出現空間不足的錯誤。這可通過將while循環產生的模板文件輸出作為`dd`的輸入實現。此外，通過設置`skip` 和 `seek` 選項的值，還能確定要擦除的範圍。除了例子中使用的`cat`外，還可以使用head(1)、tail(1)將模板文件的部分內容輸出到標準輸出。

    while [ 2 -gt 1 ]; do
     if [ -z "$(pidof dd)"  ];then
      break ;
     fi;
    cat file1-to-use.as-template file2-to-use.as-template /tmp/templatefiles/* ;
    done | dd of=/dev/sd"XY" seek=<起始扇區> bs=<扇區大小> count=<擦除扇區數量>

提示：若要重複覆寫同一區域，可以在 `while ... done | dd ...` 外層新增一個循環，使用新增循環的循環變量，在每次循環中使用不同的模板文件進行覆寫。
注意：如果用於覆寫的預定義模板文件數量很多，可以利用 SquashFS 來壓縮文件和文件夾，並存放到掛載的 內存檔 中。這樣能最大限度地減少磁碟讀取次數，但同時會增加 CPU 使用率。此外，也可以為模板文件創建壓縮包，將壓縮包複製到內存檔中，並使用能夠將解壓後的內容輸出到標準輸出的解壓縮工具。使用壓縮包的缺點是，難以在每次覆寫時只是用壓縮包中的部分模板文件。不過，使用壓縮包也存在優點：若在創建壓縮包時使用了分卷壓縮，可以直接將某一分卷作為覆寫內容覆寫文件

另見：

- sector size - 文件創建和扇區大小

## 擦除可用空間

警告：若正在為塊設備加密準備可用空間，不適合使用此方法。

可以通過以下幾種方式擦除可用空間：

- 將輸出重定向到一個文件，而不是分區或設備。
- 在循環中，使用隨機文件名或目錄名創建多個文件副本（例如，使用`cp`），直到占滿所有可用空間。
- 使用帶有文件加密功能的工具，並使用隨機密碼、隨機文件名進行加密。某些文件壓縮工具支持加密功能，且可以通過選項設置壓縮方法、文件類型等，有的還支持分卷壓縮。通過使用循環，在循環中隨機設置壓縮選項，可以用加密數據填滿可用空間，以覆寫以前的數據。
- 使用專門用於擦除可用空間的程序，例如：

wipefreespace — 安全地擦除文件系統上的可用空間，以防止已刪除的敏感數據被恢復。

  https://sourceforge.net/projects/wipefreespace/ || wipefreespaceAUR

zerofree — 掃描並以零填充文件系統中的非零空閒塊

  https://frippery.org/uml/ || zerofreeAUR

### 使用 dd

可以使用 dd 創建一個文件來填滿可用空間：

    dd if=<填充数据源> of=junk
    sync
    rm junk

`<填充數據源>` 可以是 `/dev/urandom` 隨機流或 `/dev/zero` 全零流。

注意需要確保數據已同步到磁碟後，再刪除該文件。

### 使用 7-Zip

    Password="$(dd if=/dev/random bs=128 count=1 iflag=fullblock)"
    DestinationFile="$((${RANDOM/0/1}$(date "+%s")/${RANDOM/0/1}))"
    7z a -t7z -mhe=on -p"${Password}" -mx=0 -v1m ${DestinationFile} source

所用選項的詳細說明參見 `7z --help`。

`source` 可以是一個包含隨機數據的文件，也可以是一個設備（例如 `/dev/urandom`），或者另一個塊設備或其上的分區（例如 `/dev/sd"XY"`）。注意當使用塊設備時，該塊設備中不應含有敏感數據，並且，塊設備中已在文件系統層面刪除的數據也可能會被讀取並壓縮，以填充目標位置。

注意：

- 不必設置壓縮級別，只需將數據存儲到壓縮文件中即可，以最大限度地減少 CPU 使用率並更快地填滿可用空間。
- 如果使用單個文件作為源，可以將其放入 內存檔 或 `/tmp` 文件夾。`/tmp`文件夾使用tmpfs，用於將文件存儲到內存中，可加快讀取速度。

### 藉助 timeout 命令創建多個文件

若在循環中使用`timeout`命令，並設置隨機的等待時間。則`timeout`將在隨機時間後中斷文件的創建，從而使得創建的文件大小隨機化。不過該方法速度較慢。

在循環中使用帶有隨機等待時間的 `timeout` 命令會中斷命令，從而留下一個隨機大小的文件。這是一種很慢的方法，但也是一種可行的替代方案。此外，對於文件名，可以在隨機部分之前附加特定的預定義前綴。

    AA=${RANDOM/0/1};
    timeout $((AA/100)) cat /dev/urandom > filename${RANDOM}.tmp;

## 另見

- limits for the file creation on the different file systems.
- meta-data in the filesystem may keep information about file after it was deleted.
- forensic software uses meta-data to recovery and what need to do for wiping of the meta-data.

分類：​

- 安全
- 文件系統

安全地擦除磁碟/提示和技巧
新增話題