一轉檔就全斷:C2PA 怎麼在位元組之外留第二條線索
最早那套設計是把來源資訊釘死在位元組上。算一段雜湊、簽名、把 manifest 塞進檔案,之後只要有一個 bit 被動過,驗章就過不了。密碼學上沒有破口。
然後你把那張圖上傳到某個平台。它重新壓一次、順手把不認得的中繼資料清掉,你的 manifest 就不見了。驗章這一步根本沒有東西可以驗,連「這張圖曾經有過來源資訊」這件事都查不出來。
這是 hard binding 的結構性下限,跟演算法強度無關。位元組變了,綁在位元組上的東西當然對不上;而平台剝掉中繼資料的理由可以完全無辜,有的是用了不支援的軟體,有的是轉檔流程順手清掉。剝的人沒有惡意,結果一樣是全斷。
那段時間能做的就是祈禱平台不要剝。講出來很扯,但那真的是唯一的湊合法:你把 manifest 簽好、上傳,然後等對方的管線給你面子。
2024 年 9 月,規格裡多了四個零件
C2PA 2.1 是 2024 年 9 月 20 日發的,soft binding 那一整套是在這一版進來的。
C2PA 規格版本
2.1(2024-09-20)
Soft Binding Assertion、C2PA Watermarked Action、Soft Binding Resolution API、Soft Binding Algorithm List 四個零件在這一版引入。
2.2(2025-05-01)
這一版的實作指引裡,有浮水印被搬家的風險與對應的緩解手段。
2.4(2026-04)
我這次讀的版本。soft binding 的定義、數量規則、不可混用那條都在裡面。
先看規格怎麼定義它,原文一句話:
“A content identifier that is either (a) not statistically unique, such as a fingerprint, or (b) embedded as an invisible watermark in the identified digital content.”
括號 (a) 那半句值得停一下。一份談內容來源的規格,主動引進了一種不具備統計唯一性的識別碼。這跟大家對「證明」這個詞的直覺是反著走的:你會預期一份講來源可信度的標準去要求更強的唯一性、更低的碰撞率,結果它承認這東西本來就不唯一,然後照樣把它寫進標準。
因為它要回答的問題已經換了。hard binding 問的是「這份內容有沒有被改過」,soft binding 問的是「這份內容是不是那一份」。第二個問題不需要唯一,只需要找得到。
manifest 沒有跟著檔案走,它躺在某個 repository 裡,soft binding 的工作是當那把搜尋用的鑰匙。規格給這件事取了名字,叫 durable Content Credential,定義裡的動詞是 discovery:
“A Content Credential for which there exists one or more soft bindings that enable its discovery in a manifest repository.”
Content Authenticity Initiative 的開發者文件講得更白:如果 manifest 有一份存在線上資料庫,你可以用浮水印或指紋把它找回來。
一個 manifest 只能有一個 hard binding,soft binding 隨便你放幾個
規格裡有一條數量規則,我認為它是整個設計的骨架:
“A single manifest shall not contain more than one assertion defining a hard binding but may contain zero or more assertions defining soft bindings.”
這條規則是一對多,而且不對稱。想通它為什麼長這樣,整件事就通了。
「這份內容有沒有被改過」的答案只能有一個。你放兩個 hard binding,它們要嘛說同一件事(多餘),要嘛互相矛盾(那你要信哪個)。所以規格把上限封死在一。
「這份內容是不是那一份」剛好相反。多留一條線索只會更容易找到,不會更容易出錯——前提是你清楚每條線索都只是線索。
換個場景想。hard binding 像信封上的封蠟:撕開就知道被動過,可是封蠟本身沒辦法幫你找到那封信在哪裡。soft binding 像你在圖書館要找一本被撕掉書名頁的書,你記得封面偏綠、記得第三十頁有一圈咖啡漬。這兩件事都不唯一,可是足夠讓你把候選從架上抽出來,抽出來之後再翻開確認是不是它。
既然 hard binding 一剝就斷,那拿 soft binding 當備援不是剛好嗎。不行,規格特地補了一句擋這個念頭:
“Because they serve a different purpose, a soft binding shall not be used as a hard binding.”
讀起來像廢話,擋的卻是一種很自然的產品衝動。用近似比對查回來的 manifest 只能告訴你「大概是這一份」,沒辦法告訴你「這份內容沒有被改過」。把第二個結論說出口的那一刻,你已經超出這條線索能承擔的範圍。
把 soft binding 當成 hard binding 的容錯機制來用,是這套規格最容易被誤用的地方,這是我的立場。漏做 soft binding 只是少一條線索,不痛;拿指紋比對的結果去下真偽判斷,才會真的害到人。什麼情況會讓我改口?如果有實作能證明「用指紋查回來的 manifest」跟「手上這串位元組」之間還存在一條可以密碼學驗證的關係,而不只是一個相似度分數,那這條界線就該重畫。
| hard binding | soft binding | |
|---|---|---|
| 回答的問題 | 有沒有被改過 | 是不是那一份 |
| 一份 manifest 能放幾個 | 最多 1 個 | 0 到任意多個 |
| 2.4 定義的形式 | data hash(位元組範圍)、general box hash(非 BMFF 格式)、BMFF-based hash(ISO BMFF 格式)、collection data hash(多資產) | fingerprint(從內容算出)、invisible watermark(埋進內容) |
| 位元組被改過還能用嗎 | 不能 | 可以,近似比對 |
左欄那四種形式在做同一件事:把「哪些位元組要進雜湊」這個問題,在不同容器格式裡各回答一次。容器格式的差異被處理得很細,而四種形式共用的那個前提,就是前面講的下限——位元組會不會活著抵達對面,沒有任何一種形式能處理。
浮水印會被搬走,所以再存一份指紋
浮水印是一段能被偵測、能被讀出來的訊號,這件事有另一面:有人能把它從一份內容上取出來、貼到另一份內容上,讓一張假圖冒用一份真的 Content Credential。
兩種 soft binding 的差別在這裡要補一下。一種是從內容算出來的指紋,內容改動大一點就對不上;一種是主動埋進內容裡的隱形浮水印,帶得走,重新壓縮也還在。浮水印看起來明顯比較強,直到你想到上一段那件事。
2.2 的實作指引把這個風險叫 transference,給的緩解手段是:
“In order to mitigate spoofing (transference) of the invisible watermark, a claim generator may optionally store a fingerprint of their asset as a soft binding assertion within the active manifest.”
於是流程變成兩段。浮水印裡的識別碼負責當搜尋鍵,把 manifest 撈出來;撈出來的那份 manifest 裡另外存著一份指紋,拿去跟手上這份內容現算的指紋比對。對不上,就知道浮水印被搬過。
同一份指引對這個指紋的定位講得非常節制:
“the search key is the unique identifier within the invisible watermark and the fingerprint is used only as an automated form of visual check.”
an automated form of visual check。這份指紋不是證據,它是一雙自動化的眼睛,代替人去掃一眼「這兩份看起來像不像同一份」。規格自己用的動詞也只是 mitigate。浮水印搬不走的那個版本,規格沒有給;它給的是第二條線索,用來抓第一條線索的破口。
兩個 optional 決定了這套東西實際有沒有用
讀到這裡我才注意到一件事:規格把該封死的都用 shall 封死了,而整套機制真正靠的那兩件事,用的動詞是 may。脆弱點不在密碼學,在這裡。
數量規則的原文寫的是 zero or more。一份 manifest 可以一個 soft binding 都不放,完全合規。durable Content Credential 因此從來就不是預設值,得有人願意多做那一步才會存在。第二個 optional 藏在緩解手段那句裡:claim generator may optionally store a fingerprint。要不要多存那份指紋防搬家,同樣是自由心證。
兩個都是選配,接下來會發生什麼事其實很好猜。趕上線的時候,多算一份指紋、多接一個 repository、多打一次 API,這些全部會被歸到「之後再說」那一格,而那一格在這一行是什麼意思大家都很熟。等到位元組被剝乾淨的那天才會知道當初少做的是哪一步,那時候已經沒有東西可以查回來了。
規格能規定的只有「你這樣做才算合規」,規定不了「你想不想做」。這也是我對這套東西的判斷跟對浮水印技術的判斷分開的原因:演算法再強,上面那兩個 optional 沒被勾起來,強度就只存在於規格文件裡。
誠實邊界:我只讀了 C2PA 2.4 技術規格、2.2 實作指引,以及 Content Authenticity Initiative 的開發者文件。沒有實際跑過任何一套 soft binding 實作,沒有埋過浮水印、沒有算過指紋,也沒有對任何 manifest repository 發過一次查詢。這篇裡所有關於精度與可靠性的敘述都來自規格自己的用字,不是我量出來的。
怎麼查是統一的,怎麼埋交給市場
C2PA 沒有指定要用哪一家的浮水印演算法或哪一種指紋。它維護一份 C2PA Soft Binding Algorithm List,Soft Binding Assertion 裡的 alg 欄位就是指向這份清單的識別碼;另外定義一個 Soft Binding Resolution API,讓查詢可以跨 repository 互通。
這樣分也合理。如果每家的查詢介面都長得不一樣,「manifest 躺在某個 repository 裡」這個前提根本站不住,你連要去哪裡問都不知道。
順著這個分工往下想,會浮出幾個規格管不到的問題。演算法清單要收哪幾家、每一次查詢會留在誰的 log 裡,都還有得吵;我認為最先出事的會是 repository 的存續。一家服務收掉,裡面躺著的 manifest 跟著消失,所有指向它的 soft binding 會在同一天變成死鍵。規格能定義查詢介面,定義不了對面那台機器明年還在不在。
這條線最後接到的是人眼
用指紋查回來的 Content Credential,指引建議拿給使用者人工複核,不要當成確定答案直接採用。理由它寫在同一句裡:
“As algorithms used for fingerprinting typically offer near- rather than exact- matching, it is recommended that the Content Credentials retrieved using a fingerprint as a search key are presented to the user for manual review.”
這是我讀完整套機制之後覺得最誠實的一句。一份講來源可信度的規格,在最後一步主動承認自己給不出確定答案,而且把這件事寫進了建議做法。
繞一圈,這件事走到了起點的對面。hard binding 那一端是純機器的:雜湊對就是對,不對就是不對,沒有人需要做判斷。soft binding 這一端把判斷還給人,系統只負責把候選找出來,最後那一下由看的人按下去。
從 2024 年 9 月那四個零件,到 2026 年 4 月的 2.4,這條線索的機制長齊了。沒長齊的是最後那一段:願意在使用者面前老實顯示「這是近似比對的結果,你自己看一眼」的那個介面。這一件規格寫不出來。









