塗黑不是一個黑色矩形
Spec: ISO 32000-2, §7.11ISO 32000-2 §7.11Spec: ISO 32000-2, §14.13.5ISO 32000-2 §14.13.5
一個畫在名字上的黑色矩形什麼也沒藏。頁面看起來像是塗黑了,但底下的文字仍在那裡,仍可選取、仍可複製。真正的塗黑不會蓋住內容。它會刪除內容。
本頁說明一層裝飾性覆蓋與真正內容移除之間的落差、為何中介資料與內嵌檔案能在一份天真的處理下倖存,以及 NextPDF 企業版 RedactionEngine 在無法真正移除某個區域時,為何拒絕假裝它已不復存在。
為何這很重要
標題為「為何這很重要」的區段最常被引用的 PDF 資料外洩事件並不是什麼巧妙的攻擊。它們是黑色矩形。有人在一段敏感的段落上畫了一個填滿的盒子、匯出檔案,然後就把它送了出去。收件者按下那個盒子、橫向拖曳,原始的文字便直接從文件複製到了剪貼簿上。
原因是結構性的。一個 PDF 頁面是一組依序疊放的繪圖運算子。畫上一個不透明的矩形,是在最上層多加一個運算子;它並不會移除底下那個顯示文字的運算子。在眼中文字被藏起來了。在機器看來,它就在它一直所在之處。那層覆蓋是一套戲服,而戲服是會被脫下的。
這之所以代價高昂,是因為失敗既無聲又無可挽回。文件看起來正確、通過了目視審查,便被發布了。外洩在事後才被某個選取了文字的人發現,而到那時,每一份副本都早已流出。
簡短版本
標題為「簡短版本」的區段- 一個黑盒子是一次疊在文字之上的繪圖操作,而非對它的一次刪除。位元組倖存了下來。
- 可選取的文字之所以倖存,是因為頁面內容串流仍攜帶著繪出那些字詞的字符。
- 文件中介資料之所以倖存,是因為它住在一個各別的地方——文件資訊字典與 XMP 封包——那是頁面上任何矩形都搆不著的。
- 內嵌檔案之所以倖存,是因為 PDF 能把整份檔案以內嵌檔案串流的形式攜帶在內部。Spec: ISO 32000-2, §7.11ISO 32000-2 §7.11 一個頁面上的標記永遠不會碰到一個附件。
- 真正的塗黑是破壞性的。 它從位元組串流中移除內容,而非從圖像中移除。消失的就是消失了,而那些殘留面也一併被清理乾淨。
NextPDF 如何處理
標題為「NextPDF 如何處理」的區段裝飾性對破壞性,精確地說
標題為「裝飾性對破壞性,精確地說」的區段一層裝飾性覆蓋改變的是一頁看起來像什麼。破壞性塗黑改變的是文件含有什麼。前者任何握著文字游標的人都能還原。後者則什麼都不留給人挽回。
NextPDF 企業版 RedactionEngine 是為文字內容層級的破壞性情形而打造的。它的 redact() 方法接受內容、一份描述要找什麼以及如何替換的 RedactionPolicy,並回傳一個 RedactionResult。在內部,它偵測敏感的跨距、把任何彼此重疊者合併成不相交的涵蓋範圍,接著以 substr_replace改寫內容字串,讓每一個被涵蓋的位元組恰好被移除一次。敏感文字並非被蓋住。它從結果所帶回的緩衝區中消失了。
結果對所發生之事是誠實的:它記錄原始內容的 SHA-256 雜湊值、改寫後的 redactedContent、一份載明每一處發現的稽核報告,以及一個 wasModified 旗標。你可以證明位元組變了,也可以證明變的是哪些。
你必須追緝的殘留
標題為「你必須追緝的殘留」的區段移除可見的文字是必要的,卻不充分。同樣的字詞,以及你在頁面上從未見過的字詞,藏身於頁面層級的編輯永遠搆不著的地方。
一份文件攜帶中介資料兩遍:一份舊有的資訊字典,以及一個 XMP 封包,兩者之中任一個都可能保有一個作者姓名、一個標題,或一段工具指紋。它能把整份檔案以內嵌檔案串流的形式攜帶。Spec: ISO 32000-2, §7.11ISO 32000-2 §7.11 它能把那些酬載繫結到頁面結構,作為關聯檔案,這是一條頁面不會繪製、但文件仍持有的相關產物通道。Spec: ISO 32000-2, §14.13.5ISO 32000-2 §14.13.5 這些都不在你所塗黑的頁面上,因此它們都不會被一個矩形碰到。關於這方面的經典指引——NSA 的「Hidden Data and Metadata in Adobe PDF Files」報告——之所以存在,正是因為太多真實外洩來自殘留,而非可見的頁面。
一次塗黑若刪除了頁面上的字詞、卻留下 XMP 封包中的作者姓名以及作為附件的原始試算表,那它並沒有塗黑這份文件。它塗黑的是其中的一個檢視。
- DetectFind every sensitive span — visible text, and the entity types a policy targets — not just the region you happen to see.
- 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.
- Clear the residueStrip the information dictionary and XMP metadata, and remove embedded and associated files that carry the same payload off-page.
- VerifyConfirm no selectable text, metadata field, or attachment reproduces the redacted content before the file leaves the building.
失敗封閉,而非假裝完成
標題為「失敗封閉,而非假裝完成」的區段有兩種塗黑的方式:依內容(找到這個名字、刪除它)以及依區域(把頁面的這個矩形塗掉,不論它底下是什麼)。企業版引擎真實地做到了前者。它刻意不假裝做到後者。
redact() 方法接受第三個引數,一份 ZoneRedaction 座標區域的清單。文字內容引擎沒有頁面內容覆蓋的接收端——沒有辦法真正移除坐落在一個座標盒子內的東西。所以當那份清單非空時,它不會畫一個矩形然後把那個區域稱為「已塗黑」。它擲出一個型別化的 RuntimeException,並告訴你改為把該區域導向一條頁面內容塗黑管線。
那次拒絕,正是本頁的全部要旨化為程式碼的樣子。引擎寧可停下來、點明它做不到的事,也不願為一個它完全沒動過的區域回傳一個「已塗黑」的發現。一次被當作移除來回報的無聲裝飾性覆蓋,正是那種會釀成外洩的虛假保證。失敗封閉把那場外洩,轉成一則你在送出之前就會看到的錯誤訊息。
常見的誤解
標題為「常見的誤解」的區段「我在它上面畫了一個黑盒子,所以它被塗黑了。」
這就是陷阱,而且是整個格式中最常見的一個。一個填滿的矩形是一道堆疊在文字之上的繪圖指令。顯示文字的運算子仍在內容串流之中、字符仍會繪出,而一次選取或一次複製便會原封不動地把它們讀出來。你藏起了一張圖像;你並沒有改變一份文件。
第二個更細微的陷阱:「我刪除了頁面上的文字,所以文件乾淨了。」還沒。同樣的內容,以及你從未顯示過的內容,可以留存在中介資料與內嵌檔案中。唯有當每一個面——頁面內容、中介資料與附件——都清除了你打算移除的東西時,塗黑才算完成。
限制與邊界
標題為「限制與邊界」的區段依版本劃分,NextPDF 在這方面所做之事的誠實範圍:
- 核心完全沒有文件塗黑。 它隨附一個針對稽核日誌 PII 的隱私清理器——把敏感的值排除在你自己的診斷記錄之外——而那與塗黑一份已交付的 PDF 完全是兩回事。如果你在用核心、而你需要塗黑一份文件,你所要的能力並不存在。別畫一個盒子就假設引擎移除了任何東西。
- 企業版
RedactionEngine破壞性地塗黑文字內容。 它改寫內容緩衝區以移除敏感位元組,並回報一個雜湊值、一份稽核報告,以及一個wasModified旗標,讓那次移除可被證明。 - 座標區域塗黑失敗封閉。 傳入一份非空的
ZoneRedaction清單,引擎便會擲出例外,而非假造一層覆蓋。那是一項刻意的安全性質,而非一個缺失的功能:一個它無法真正清除的區域,就是一個它拒絕稱為已清除的區域。 - 清除每一個殘留面也是操作者的責任。 移除可見文字只是一步。一次完整的工作還會剝除資訊字典、XMP 封包,以及任何攜帶同樣酬載而離開頁面的內嵌或關聯檔案(Spec: ISO 32000-2, §7.11ISO 32000-2 §7.11、Spec: ISO 32000-2, §14.13.5ISO 32000-2 §14.13.5)。
| Edition | Availability |
|---|---|
| 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. |
| Pro | Not 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. |
相關文件
標題為「相關文件」的區段- PDF 加密實際如何運作 — 為何加密一個檔案與從中移除內容並不是同一回事,以及兩者各自在何處保護你。
- 中介資料與 XMP 封包 — 頁面層級塗黑永遠搆不著的那個殘留面,詳述之。
- 拒絕猜測的 API — 塗黑引擎對一個它無法完成的區域,所套用的同一套失敗封閉立場。
詞彙表
標題為「詞彙表」的區段- 裝飾性覆蓋 — 一道繪圖操作,例如一個填滿的矩形,疊在內容之上以在視覺上將其藏起。它並不移除底下的內容,那些內容仍可選取、可複製。
- 破壞性塗黑 — 從文件的位元組串流中、而非從圖像中移除內容。一旦完成,底下便沒有任何東西可供挽回。
- 內容串流 — 繪製一頁的那份有序繪圖運算子清單,包括繪出字符的顯示文字運算子。疊在最上層的一個盒子並不會刪除它底下的文字運算子。
- 殘留面 — 文件中一個保有頁面所不顯示之內容的地方:資訊字典、XMP 中介資料封包,以及內嵌或關聯檔案。一次完整的塗黑會清除它們全部。
- 內嵌檔案串流 — 一份攜帶於 PDF 內部的整份檔案(ISO 32000-2 §7.11)。一個頁面上的標記永遠不會碰到一個附件。
- 失敗封閉 — 當一項操作無法被真實地完成時,以一個型別化錯誤停下來,而非產生一個看似可信、實則錯誤的結果。企業版引擎對它無法完成的座標區域塗黑正是這麼做。