跳到內容
getnextpdf.com

Pro 版本穩定性: 實驗性

C2PA 預覽 — 深入參考

本頁是 NextPDF Pro 中 C2PA(Content Credentials)預覽介面的合約層級參考。它涵蓋 NextPDF\Pro\Compliance\C2pa 中的五個公開符號:C2paManifestEmbedder SPI、ManifestStore 值物件、JumbfBoxParserC2paCapabilityStatus 描述子,以及受閘門控制的 Experimental\ExperimentalC2paEmbedder。它也記載了 Feature::PREVIEW_C2PA_DRAFT 閘門及其環境變數 NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT

此介面屬於實驗性質,並分為兩層。穩定接縫——ManifestStoreC2paManifestEmbedderJumbfBoxParser——始終可達,並雙向承載 Manifest Store 位元組。草案 manifest 合成僅存在於 ExperimentalC2paEmbedder,且預設關閉。C2PA-PDF 設定檔尚未由工作組定案;合成後的線路格式被釘選至某個草案提交。它不主張任何符合性,沒有驗證路徑,啟用預覽旗標也無法創造出兩者中的任何一個。以任務為導向的說明位於能力頁面

此能力隨 NextPDF Pronextpdf/pro)出貨,並以 Pro 等級的授權封套啟用。缺少該權利的部署不會載入此能力的類別。比較各版本並取得授權

授權會整體啟用 Pro 符合性介面。無論授權等級為何,其內部的 C2PA 介面始終維持預覽狀態。草案合成另需本頁所記載的行程閘門;單憑 Pro 授權永遠不會啟用它。

符號參數預設行為回傳拋出或失敗於備註
C2paManifestEmbedder僅位元組的嵌入/擷取 SPI;無 I/O;不合成 claim凍結、供應商中立的接縫介面。
C2paManifestEmbedder::embed()string $pdfBytesManifestStore $store在設定檔宣告的位置嵌入 $store->toBytes();空的 Store 可以以無操作方式往返string 新的 PDF 位元組任何嵌入失敗時拋出 C2paException(Store 過大、PDF 無效、設定檔位置衝突)實作絕不變更或保留輸入位元組。
C2paManifestEmbedder::extract()string $pdfBytes廉價的偵測探針;無 Store 的情形幾乎不配置記憶體?ManifestStore(未命中回傳 null存在 Store 但違反強化不變量時拋出 C2paException 子類別非 null 的 Store 已通過 JumbfBoxParser 強化。
ManifestStore::fromBoxes()array $boxeslist<JumbfBox>包裝一份經剖析器驗證的有序 box 清單self本身不拋出;手工建構 JumbfBox 會執行相同的強化建構子為私有;box 順序對往返相等性具有承載作用。
ManifestStore::empty()具有零個根 box 的 Storeself不拋出空 Store 的 toBytes() 為空字串。
ManifestStore::isEmpty()檢測是否為零個根 boxbool不拋出
ManifestStore::toBytes()串接各根 box 的序列化結果string不拋出這串位元組即嵌入器所寫入的內容。
ManifestStore::size()toBytes() 的位元組長度int(>= 0)不拋出
JumbfBoxParser::__construct()三個選填的上限覆寫生產上限:每 box 64 MiB、總計 128 MiB、每個 superbox 4096 個子項JumbfBoxParser不拋出深度上限固定為 MAX_DEPTH(8),無法由建構子調整。
JumbfBoxParser::parse()string $bytes驗證並具現化根 box;空輸入產生 []list<JumbfBox>JumbfBombExceptionJumbfCycleDetectedExceptionJumbfDepthExceededExceptionMalformedJumbfException無狀態;絕不回傳部分圖;對單一實例的並行呼叫是安全的。
C2paCapabilityStatus::__construct()六個具名的 readonly 欄位建立一個任意的描述子實例C2paCapabilityStatus不拋出current() 是規範建構子。
C2paCapabilityStatus::current()即時讀取閘門;將 claim 布林值硬編碼C2paCapabilityStatus不拋出generallyAvailableconformanceClaimed 永遠為 false
C2paCapabilityStatus::summary()單行狀態文字string不拋出措辭不帶任何 GA 或符合性主張。
Feature字串支撐的列舉,1 個 case單一 case PREVIEW_C2PA_DRAFT;常數 ENV_PREVIEW_C2PA_DRAFT列舉 case存取 case 時不拋出任何東西範疇化的穩定性閘門;有別於授權權利。
Feature::isEnabled()即時讀取 getenv();與字串 1 嚴格比較bool不拋出變數不存在或為任何其他值(包含 0trueyes)皆為關閉。
ExperimentalC2paEmbedder::__construct()建構時的失敗即關閉閘門檢查ExperimentalC2paEmbedderFeature::PREVIEW_C2PA_DRAFT 關閉時拋出 LogicException不存在任何無聲退回。
ExperimentalC2paEmbedder::buildManifestStore()string $sourceBytesstring $producer(非空)建立一個草案形狀的 Store,透過 SHA-256 綁定 $sourceBytesManifestStorepayload 編碼失敗時拋出 \JsonException;box 建構拋出 C2paException 子類別省略 c2cs Claim Signature box;輸出依建構即為未簽署。
interface C2paManifestEmbedder
public function embed(string $pdfBytes, ManifestStore $store): string;
public function extract(string $pdfBytes): ?ManifestStore;
final readonly class ManifestStore
public static function fromBoxes(array $boxes): self
public static function empty(): self
public function isEmpty(): bool
public function toBytes(): string
public function size(): int
final class JumbfBoxParser
public const int MAX_DEPTH = 8;
public const int MAX_PER_BOX_BYTES = 64 * 1024 * 1024;
public const int MAX_TOTAL_BYTES = 128 * 1024 * 1024;
public const int MAX_CHILDREN_PER_SUPERBOX = 4096;
public const array SUPERBOX_TBOXES = ['jumb', 'c2pa', 'c2ma', 'c2as', 'c2cl', 'c2cs', 'c2vc'];
public function __construct(
private readonly int $maxPerBoxBytes = self::MAX_PER_BOX_BYTES,
private readonly int $maxTotalBytes = self::MAX_TOTAL_BYTES,
private readonly int $maxChildrenPerSuperbox = self::MAX_CHILDREN_PER_SUPERBOX,
)
public function parse(string $bytes): array
final readonly class C2paCapabilityStatus
public const string MATURITY_PREVIEW_DRAFT = 'preview-draft';
public function __construct(
public bool $previewEnabled,
public bool $generallyAvailable,
public bool $conformanceClaimed,
public string $maturity,
public string $specPin,
public string $envGate,
)
public static function current(): self
public function summary(): string
enum Feature: string
case PREVIEW_C2PA_DRAFT = 'preview_c2pa_draft';
public const string ENV_PREVIEW_C2PA_DRAFT = 'NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT';
public function isEnabled(): bool
final class ExperimentalC2paEmbedder
public const string SPEC_PIN_SHA = '4e2afed8f3ace20d41317e2e386c9340d2959d55';
public const string SPEC_PIN_DATE = '2026-04-26';
public function __construct()
public function buildManifestStore(string $sourceBytes, string $producer): ManifestStore
  • 兩層切分。 穩定接縫(ManifestStoreC2paManifestEmbedderJumbfBoxParser)始終可達。草案合成僅存在於 NextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedder,位於預設關閉的閘門之後。擷取與位元組承載從不需要閘門;合成則始終需要。
  • 接縫不變量。 C2paManifestEmbedder 合約僅處理位元組:沒有記憶體內的 PDF 物件跨越接縫,實作不執行任何網路或檔案系統 I/O,且接縫本身絕不組裝 claim 主張。extract() 以回傳 null 表示不存在;它絕不因不存在而拋出。
  • Store 語意。 ManifestStore 是一份不可變的有序根 JumbfBox 實例清單,依循 C2PA 2.1 §11.1.1 的 Manifest Store 模型:一個 JUMBF 容器聚合一或多個 manifest,可依 URI 定址。它不暴露任何 claim 層級的存取器。box 順序被保留,並對往返相等性具有承載作用。
  • 強化上限。 JumbfBoxParser 無條件拒絕超過任一上限的輸入:單一 box 大小超過 64 MiB、累計 store 超過 128 MiB、巢狀深度超過 8 層,或單一 superbox 內子項超過 4096 個。沒有任何政策旗標能停用這些上限。針對記憶體受限的行程,更緊的上限可經由建構子注入。
  • 結構性拒絕。 剖析器也以失敗即關閉的方式拒絕:LBox = 0(BMFF 直到 EOF)、LBox = 1(XLBox 64 位元長度)、比 8 位元組標頭還小的 LBox、超出剩餘輸入的截斷、落在可列印 ASCII(0x20–0x7E)之外的 TBox 位元組、位移重入(循環),以及 superbox payload 的非精確子項排布。它絕不回傳部分建構的圖。
  • Superbox 路由。 位於 SUPERBOX_TBOXES 中的 TBox 值會遞迴剖析為子序列;其他所有 TBox 都是帶有不透明 payload 的葉節點。cbor 刻意被當作葉節點以維護剖析器安全;上游各層在需要時再重新剖析其 payload。
  • 行程閘門。 Feature::PREVIEW_C2PA_DRAFT 預設關閉。唯有當 NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT 精確等於字串 1 時,isEnabled() 才回傳 true。每次呼叫都是即時讀取;不做任何記憶化。
  • 失敗即關閉的建構。 當閘門關閉時,new ExperimentalC2paEmbedder() 拋出 LogicException。訊息會指名該旗標、環境變數,以及釘選的草案 SHA 與日期。呼叫者無法意外抵達草案合成。
  • 合成形狀。 buildManifestStore() 產出一個 c2pa superbox,其中含有一個 c2ma manifest,該 manifest 持有一個 c2as 主張儲存區(一個 c2pa.hash.data 主張)與一個 c2cl claim。該主張記錄一個針對 $sourceBytes 的 SHA-256 雜湊主張;由於 c2cs Claim Signature box 被省略且輸出未簽署,這不是 C2PA 硬綁定,也不是溯源裁決——它僅僅依循 §9.1 所描述的結構形狀。Description box 的 payload 依 C2PA 2.1 §11.1.4.1.1–11.1.4.1.2,帶有一個型別 UUID、切換位元 0x03,以及一個以 null 結尾的 UTF-8 標籤。
  • 無 Claim Signature。 c2cs box——依 C2PA 2.1 §11.1.4.4 是一個標籤為 c2pa.signature 的單一 CBOR content box——被刻意從合成的 Store 中省略。輸出依建構即為未簽署。這是被判斷在工作組凍結前最可能漂移的設定檔區域。
  • 草案釘選,無 BC 保證。 合成後的線路格式被釘選至 c2pa-org/specificationsSPEC_PIN_SHA4e2afed8…,日期 2026-04-26)。它可能在不預告的情況下變更,且不帶任何向後相容保證。
  • 誠實不變量。 C2paCapabilityStatus::current()generallyAvailableconformanceClaimed 硬編碼為 false。沒有任何組態或環境旗標能翻轉任一布林值。只有 previewEnabled 反映閘門;maturity 是不主張任何東西的權杖 preview-draft
  • 將閘門變數設為 0trueyeson 或空字串,都會使閘門維持關閉。唯有精確的字串 1 才能啟用它。
  • putenv() 的變更會在下一次 isEnabled() 呼叫時生效,因為讀取是即時的。行程中途切換的閘門會被立即觀察到。
  • extract() 區分兩種結果:無 Store 存在時回傳 null(廉價、無例外),以及存在 Store 但具敵意或格式錯誤時拋出 C2paException 子類別。不存在永遠不是錯誤;存在加上格式錯誤則永遠是錯誤。
  • JumbfBoxParser::parse('') 回傳空清單。一個空但存在的 ManifestStore 會往返回自身;接縫不會將它塌縮為 null
  • 嵌入一個空的 Store 可以原封不動地回傳輸入。接縫合約允許此無操作,但不強制。
  • 手工建構的 JumbfBox 圖在建構時執行相同的強化:TBox 長度與 ASCII 檢查、深度上限、子項深度不變量、payload 或 children 互斥規則,以及單一 box 大小上限。手工建構的炸彈會在建構時失敗,而非在嵌入時。
  • 每個剖析器例外都攜帶結構化欄位——capKind/observed/capoffsetkind——因此遙測不需刮取訊息字串。所有子類別都擴充 C2paException(其本身是 RuntimeException),也就是那個總括的攔截型別。
  • 剖析器 docblock 禁止無聲吞掉這些例外;消費者應將它們浮現出來,或帶著意圖重新映射它們。
  • buildManifestStore()JSON_THROW_ON_ERROR 編碼 JSON payload;一個非有效 UTF-8 的 $producer 字串會在任何 box 被建立之前先以 \JsonException 失敗。
  • 一個格式正確的 extract() 結果僅是一個結構性陳述。此介面上任何地方都沒有 claim 驗證、沒有簽章驗證,也沒有信任評估。辨識不等於溯源裁決。
  • 此介面不處理任何簽署金鑰、憑證或 COSE 結構。唯一的密碼學運算是受閘門控制的合成路徑內部的一個 SHA-256 內容雜湊。
主張標準條款
Manifest 序列化為一個持有多個 manifest、可依 URI 定址的 JUMBF store。C2PA 2.1§11.1.1 (p63.b)
Description box 標籤是以 null 結尾、帶有排除範圍的 UTF-8;所有 Description box 都定義了切換位元。C2PA 2.1§11.1.4.1.1–11.1.4.1.2 (p63.a)
Claim Signature box 標籤為 c2pa.signature、型別為 c2cs,且持有一個單一 CBOR content box。C2PA 2.1§11.1.4.4 (p63.c)
硬綁定在密碼學上將 manifest 綁定至其資產並揭露被修改——預覽的未簽署雜湊主張達此門檻。C2PA 2.1§9.1 (p57)

所有條款皆為改寫轉述。NextPDF 不重製規範性文字。NextPDF 不持有任何認證,也不授予任何認證。 上述陳述是關於 box 佈局、標籤與綁定的結構對齊陳述——它們不是符合性測試結果、不是第三方認證,也不是 C2PA 或 ISO 符合性主張。C2PA-PDF 設定檔尚未定案;合成後的線路格式追蹤一個釘選的草案提交。C2paCapabilityStatus 在程式碼中編碼此姿態:generallyAvailableconformanceClaimed 在每一種組態中都是 false。此介面的輸出不是可驗證的 Content Credential,且 NextPDF 中不存在任何驗證路徑。

  • 剖析器所實作的 JUMBF box 文法(4 位元組大端序 LBox、4 位元組 ASCII TBox、payload;superbox 巢狀包含子 box)依循 ISO 19566-5;該標準不在所引用的語料範圍內,因此剖析器行為是以產品原始碼為基礎,而非引用規範。

  • 在生產環境中保持閘門關閉。草案合成不增添任何持久能力;產出的位元組是暫時性的,應在穩定的轉接器出貨後重新嵌入。

  • ExperimentalC2paEmbedder::SPEC_PIN_SHA 對照你的管線所預期的草案提交進行斷言。在 CI 中執行 composer c2pa:draft-status(新鮮時退出 0、軟警告 1、硬失敗 2)以偵測釘選過時。

  • 在工具或 UI 中呈現 C2PA 狀態時,將 C2paCapabilityStatus::current() 視為唯一真實來源。不要手動重述它的布林值;summary() 對日誌與狀態端點是安全的。

  • 消費 extract()parse() 時,以 C2paException 作為總括型別來攔截。使用四個子類別的結構化欄位,將它們映射到各自不同的遙測計數器。

  • 針對記憶體受限的驗證器行程,透過 JumbfBoxParser 建構子注入更緊的上限;預設值是寬裕的生產上限。

  • C2paCapabilityStatus::__construct() 是公開的,因此手工建構的實例可以攜帶任意布林值。這樣的實例僅是一個值物件;它不改變任何行為。

本頁僅記載外部可觀察的行為與受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表格、runbook 檔名,以及工單前綴皆不在範圍內。