跳到內容
getnextpdf.com

塗黑不是一個黑色矩形

Spec: ISO 32000-2, §7.11Spec: ISO 32000-2, §14.13.5

一個畫在名字上的黑色矩形什麼也沒藏。頁面看起來像是塗黑了,但底下的文字仍在那裡,仍可選取、仍可複製。真正的塗黑不會蓋住內容。它會刪除內容。

本頁說明一層裝飾性覆蓋與真正內容移除之間的落差、為何中介資料與內嵌檔案能在一份天真的處理下倖存,以及 NextPDF 企業版 RedactionEngine 在無法真正移除某個區域時,為何拒絕假裝它已不復存在。

最常被引用的 PDF 資料外洩事件並不是什麼巧妙的攻擊。它們是黑色矩形。有人在一段敏感的段落上畫了一個填滿的盒子、匯出檔案,然後就把它送了出去。收件者按下那個盒子、橫向拖曳,原始的文字便直接從文件複製到了剪貼簿上。

原因是結構性的。一個 PDF 頁面是一組依序疊放的繪圖運算子。畫上一個不透明的矩形,是在最上層多加一個運算子;它並不會移除底下那個顯示文字的運算子。在眼中文字被藏起來了。在機器看來,它就在它一直所在之處。那層覆蓋是一套戲服,而戲服是會被脫下的。

這之所以代價高昂,是因為失敗既無聲又無可挽回。文件看起來正確、通過了目視審查,便被發布了。外洩在事後才被某個選取了文字的人發現,而到那時,每一份副本都早已流出。

  • 一個黑盒子是一次疊在文字之上的繪圖操作,而非對它的一次刪除。位元組倖存了下來。
  • 可選取的文字之所以倖存,是因為頁面內容串流仍攜帶著繪出那些字詞的字符。
  • 文件中介資料之所以倖存,是因為它住在一個各別的地方——文件資訊字典與 XMP 封包——那是頁面上任何矩形都搆不著的。
  • 內嵌檔案之所以倖存,是因為 PDF 能把整份檔案以內嵌檔案串流的形式攜帶在內部。Spec: ISO 32000-2, §7.11 一個頁面上的標記永遠不會碰到一個附件。
  • 真正的塗黑是破壞性的。 它從位元組串流中移除內容,而非從圖像中移除。消失的就是消失了,而那些殘留面也一併被清理乾淨。

一層裝飾性覆蓋改變的是一頁看起來像什麼。破壞性塗黑改變的是文件含有什麼。前者任何握著文字游標的人都能還原。後者則什麼都不留給人挽回。

NextPDF 企業版 RedactionEngine 是為文字內容層級的破壞性情形而打造的。它的 redact() 方法接受內容、一份描述要找什麼以及如何替換的 RedactionPolicy,並回傳一個 RedactionResult。在內部,它偵測敏感的跨距、把任何彼此重疊者合併成不相交的涵蓋範圍,接著以 substr_replace改寫內容字串,讓每一個被涵蓋的位元組恰好被移除一次。敏感文字並非被蓋住。它從結果所帶回的緩衝區中消失了。

結果對所發生之事是誠實的:它記錄原始內容的 SHA-256 雜湊值、改寫後的 redactedContent、一份載明每一處發現的稽核報告,以及一個 wasModified 旗標。你可以證明位元組變了,也可以證明變的是哪些。

移除可見的文字是必要的,卻不充分。同樣的字詞,以及你在頁面上從未見過的字詞,藏身於頁面層級的編輯永遠搆不著的地方。

一份文件攜帶中介資料兩遍:一份舊有的資訊字典,以及一個 XMP 封包,兩者之中任一個都可能保有一個作者姓名、一個標題,或一段工具指紋。它能把整份檔案以內嵌檔案串流的形式攜帶。Spec: ISO 32000-2, §7.11 它能把那些酬載繫結到頁面結構,作為關聯檔案,這是一條頁面不會繪製、但文件仍持有的相關產物通道。Spec: ISO 32000-2, §14.13.5 這些都不在你所塗黑的頁面上,因此它們都不會被一個矩形碰到。關於這方面的經典指引——NSA 的「Hidden Data and Metadata in Adobe PDF Files」報告——之所以存在,正是因為太多真實外洩來自殘留,而非可見的頁面。

一次塗黑若刪除了頁面上的字詞、卻留下 XMP 封包中的作者姓名以及作為附件的原始試算表,那它並沒有塗黑這份文件。它塗黑的是其中的一個檢視。

  1. DetectFind every sensitive span — visible text, and the entity types a policy targets — not just the region you happen to see.
  2. Delete, do not coverRewrite the content stream so the glyphs are removed from the bytes. An opaque box on top leaves the text underneath intact.
  3. Clear the residueStrip the information dictionary and XMP metadata, and remove embedded and associated files that carry the same payload off-page.
  4. VerifyConfirm no selectable text, metadata field, or attachment reproduces the redacted content before the file leaves the building.
What a complete destructive redaction removes, in order: detect the sensitive content, delete the bytes from the content stream rather than draw over them, then clear the residue surfaces — metadata and embedded payloads — that a page-level mark never reaches, and finally verify nothing copyable survived.

有兩種塗黑的方式:依內容(找到這個名字、刪除它)以及依區域(把頁面的這個矩形塗掉,不論它底下是什麼)。企業版引擎真實地做到了前者。它刻意假裝做到後者。

redact() 方法接受第三個引數,一份 ZoneRedaction 座標區域的清單。文字內容引擎沒有頁面內容覆蓋的接收端——沒有辦法真正移除坐落在一個座標盒子內的東西。所以當那份清單非空時,它不會畫一個矩形然後把那個區域稱為「已塗黑」。它擲出一個型別化的 RuntimeException,並告訴你改為把該區域導向一條頁面內容塗黑管線。

那次拒絕,正是本頁的全部要旨化為程式碼的樣子。引擎寧可停下來、點明它做不到的事,也不願為一個它完全沒動過的區域回傳一個「已塗黑」的發現。一次被當作移除來回報的無聲裝飾性覆蓋,正是那種會釀成外洩的虛假保證。失敗封閉把那場外洩,轉成一則你在送出之前就會看到的錯誤訊息。

「我在它上面畫了一個黑盒子,所以它被塗黑了。」

這就是陷阱,而且是整個格式中最常見的一個。一個填滿的矩形是一道堆疊在文字之上的繪圖指令。顯示文字的運算子仍在內容串流之中、字符仍會繪出,而一次選取或一次複製便會原封不動地把它們讀出來。你藏起了一張圖像;你並沒有改變一份文件。

第二個更細微的陷阱:「我刪除了頁面上的文字,所以文件乾淨了。」還沒。同樣的內容,以及你從未顯示過的內容,可以留存在中介資料與內嵌檔案中。唯有當每一個——頁面內容、中介資料與附件——都清除了你打算移除的東西時,塗黑才算完成。

依版本劃分,NextPDF 在這方面所做之事的誠實範圍:

  • 核心完全沒有文件塗黑。 它隨附一個針對稽核日誌 PII 的隱私清理器——把敏感的值排除在你自己的診斷記錄之外——而那與塗黑一份已交付的 PDF 完全是兩回事。如果你在用核心、而你需要塗黑一份文件,你所要的能力並不存在。別畫一個盒子就假設引擎移除了任何東西。
  • 企業版 RedactionEngine 破壞性地塗黑文字內容。 它改寫內容緩衝區以移除敏感位元組,並回報一個雜湊值、一份稽核報告,以及一個 wasModified 旗標,讓那次移除可被證明。
  • 座標區域塗黑失敗封閉。 傳入一份非空的 ZoneRedaction 清單,引擎便會擲出例外,而非假造一層覆蓋。那是一項刻意的安全性質,而非一個缺失的功能:一個它無法真正清除的區域,就是一個它拒絕稱為已清除的區域。
  • 清除每一個殘留面也是操作者的責任。 移除可見文字只是一步。一次完整的工作還會剝除資訊字典、XMP 封包,以及任何攜帶同樣酬載而離開頁面的內嵌或關聯檔案(Spec: ISO 32000-2, §7.11Spec: ISO 32000-2, §14.13.5)。
Document redaction — edition availability
EditionAvailability
Core

Not in this edition. Core has no document redaction. It provides only an audit-log PII sanitiser, which keeps sensitive values out of your own diagnostic records — it does not redact a delivered PDF.

ProNot in this edition
Enterprise

Available. The enterprise RedactionEngine performs destructive text-content redaction and fails closed — it throws a typed exception — on coordinate-zone redaction it cannot truly fulfil, rather than painting a cosmetic overlay and reporting a region as removed.

  • 裝飾性覆蓋 — 一道繪圖操作,例如一個填滿的矩形,疊在內容之上以在視覺上將其藏起。它並不移除底下的內容,那些內容仍可選取、可複製。
  • 破壞性塗黑 — 從文件的位元組串流中、而非從圖像中移除內容。一旦完成,底下便沒有任何東西可供挽回。
  • 內容串流 — 繪製一頁的那份有序繪圖運算子清單,包括繪出字符的顯示文字運算子。疊在最上層的一個盒子並不會刪除它底下的文字運算子。
  • 殘留面 — 文件中一個保有頁面所不顯示之內容的地方:資訊字典、XMP 中介資料封包,以及內嵌或關聯檔案。一次完整的塗黑會清除它們全部。
  • 內嵌檔案串流 — 一份攜帶於 PDF 內部的整份檔案(ISO 32000-2 §7.11)。一個頁面上的標記永遠不會碰到一個附件。
  • 失敗封閉 — 當一項操作無法被真實地完成時,以一個型別化錯誤停下來,而非產生一個看似可信、實則錯誤的結果。企業版引擎對它無法完成的座標區域塗黑正是這麼做。