Bỏ qua để đến nội dung
getnextpdf.com

Pro phiên bảnđộ ổn định: Thử nghiệm

Bản xem trước C2PA — Tài liệu tham chiếu chuyên sâu

Trang này là tham chiếu cấp hợp đồng cho bề mặt xem trước C2PA (Content Credentials) trong NextPDF Pro. Nó bao quát năm ký hiệu công khai trong NextPDF\Pro\Compliance\C2pa: SPI C2paManifestEmbedder, đối tượng giá trị ManifestStore, JumbfBoxParser, bộ mô tả C2paCapabilityStatus, và Experimental\ExperimentalC2paEmbedder có cổng. Nó cũng ghi lại cổng Feature::PREVIEW_C2PA_DRAFT và biến môi trường của nó, NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT.

Bề mặt này là thử nghiệm và được chia thành hai lớp. Mối nối ổn định — ManifestStore, C2paManifestEmbedder, JumbfBoxParser — luôn tiếp cận được và mang byte của Manifest Store theo cả hai chiều. Việc tổng hợp manifest nháp chỉ nằm trong ExperimentalC2paEmbeddermặc định tắt. Hồ sơ C2PA-PDF chưa được nhóm công tác hoàn thiện; định dạng wire được tổng hợp được ghim vào một commit nháp. Không có tuyên bố tuân thủ nào được đưa ra, không có đường xác minh, và bật cờ xem trước cũng không thể tạo ra cả hai. Góc nhìn theo hướng tác vụ nằm trên trang năng lực.

Năng lực này được cung cấp trong NextPDF Pro (nextpdf/pro) và kích hoạt bằng một phong bì giấy phép cấp Pro. Một bản triển khai không có quyền đó sẽ không nạp các lớp của năng lực này. So sánh các phiên bản và nhận giấy phép.

Giấy phép kích hoạt toàn bộ bề mặt tuân thủ Pro. Bề mặt C2PA bên trong nó vẫn là một bản xem trước bất kể cấp giấy phép. Việc tổng hợp bản nháp còn đòi hỏi thêm cổng tiến trình được ghi lại ở đây; riêng một giấy phép Pro không bao giờ bật nó.

Ký hiệuTham sốHành vi mặc địnhTrả vềNém ra hoặc thất bại vớiGhi chú
C2paManifestEmbedderSPI nhúng/trích xuất chỉ dùng byte; không I/O; không tổng hợp claimGiao diện mối nối đã đóng băng, trung lập với nhà cung cấp.
C2paManifestEmbedder::embed()string $pdfBytes, ManifestStore $storeNhúng $store->toBytes() tại vị trí do hồ sơ khai báo; một Store rỗng CÓ THỂ round-trip như một no-opstring byte PDF mớiC2paException khi bất kỳ lỗi nhúng nào (Store quá lớn, PDF không hợp lệ, va chạm vị trí hồ sơ)Các triển khai không bao giờ biến đổi hay giữ lại byte đầu vào.
C2paManifestEmbedder::extract()string $pdfBytesThăm dò phát hiện rẻ; trường hợp không có Store cấp phát gần như không đáng kể?ManifestStore (null khi không có)Lớp con C2paException khi một Store hiện diện nhưng vi phạm một bất biến gia cốMột Store khác null đã vượt qua khâu gia cố JumbfBoxParser.
ManifestStore::fromBoxes()array $boxes (list<JumbfBox>)Bọc một danh sách box có thứ tự đã được trình phân tích xác thựcselfBản thân không ném; việc dựng JumbfBox thủ công thực thi cùng mức gia cốHàm dựng là private; thứ tự box mang tính quyết định cho tính bằng nhau khi round-trip.
ManifestStore::empty()không cóStore với không có box gốc nàoselfKhông némtoBytes() của một Store rỗng là chuỗi rỗng.
ManifestStore::isEmpty()không cóKiểm tra không có box gốc nàoboolKhông ném
ManifestStore::toBytes()không cóNối các chuỗi hóa của box gốcstringKhông némChuỗi byte này là thứ mà một trình nhúng ghi ra.
ManifestStore::size()không cóĐộ dài byte của toBytes()int (>= 0)Không ném
JumbfBoxParser::__construct()ba ghi đè giới hạn tùy chọnGiới hạn sản xuất: 64 MiB mỗi box, 128 MiB tổng, 4096 con mỗi superboxJumbfBoxParserKhông némGiới hạn độ sâu cố định tại MAX_DEPTH (8) và không tinh chỉnh được qua hàm dựng.
JumbfBoxParser::parse()string $bytesXác thực và hiện thực hóa các box gốc; đầu vào rỗng cho []list<JumbfBox>JumbfBombException, JumbfCycleDetectedException, JumbfDepthExceededException, MalformedJumbfExceptionVô trạng thái; không bao giờ trả về đồ thị một phần; các lời gọi đồng thời trên một thực thể là an toàn.
C2paCapabilityStatus::__construct()sáu trường readonly có tênDựng một thực thể mô tả tùy ýC2paCapabilityStatusKhông némcurrent() là hàm dựng chính tắc.
C2paCapabilityStatus::current()không cóĐọc cổng trực tiếp; mã hóa cứng các boolean claimC2paCapabilityStatusKhông némgenerallyAvailableconformanceClaimed luôn là false.
C2paCapabilityStatus::summary()không cóVăn bản trạng thái một dòngstringKhông némĐược diễn đạt để không mang tuyên bố GA hay tuân thủ nào.
Featureenum backed bằng chuỗi, 1 caseCase đơn PREVIEW_C2PA_DRAFT; hằng ENV_PREVIEW_C2PA_DRAFTcase enumKhông có gì khi truy cập caseCổng ổn định có phạm vi; khác với quyền của giấy phép.
Feature::isEnabled()không cóĐọc getenv() trực tiếp; so sánh nghiêm ngặt với chuỗi 1boolKhông némVắng mặt biến hoặc bất kỳ giá trị nào khác, kể cả 0, true, yes, đều là tắt.
ExperimentalC2paEmbedder::__construct()không cóKiểm tra cổng fail-closed tại thời điểm dựngExperimentalC2paEmbedderLogicException khi Feature::PREVIEW_C2PA_DRAFT tắtKhông tồn tại dự phòng âm thầm.
ExperimentalC2paEmbedder::buildManifestStore()string $sourceBytes, string $producer (không rỗng)Dựng một Store có hình dạng nháp ràng buộc $sourceBytes qua SHA-256ManifestStore\JsonException khi mã hóa payload thất bại; các lớp con C2paException từ việc dựng boxBỏ qua box Claim Signature c2cs; đầu ra không được ký theo cấu trúc.
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
  • Chia hai lớp. Mối nối ổn định (ManifestStore, C2paManifestEmbedder, JumbfBoxParser) luôn tiếp cận được. Việc tổng hợp bản nháp chỉ tồn tại trong NextPDF\Pro\Compliance\C2pa\Experimental\ExperimentalC2paEmbedder phía sau cổng mặc định tắt. Việc trích xuất và mang byte không bao giờ đòi hỏi cổng; việc tổng hợp thì luôn đòi hỏi.
  • Bất biến của mối nối. Hợp đồng C2paManifestEmbedder chỉ dùng byte: không có đối tượng PDF trong bộ nhớ nào băng qua mối nối, các triển khai không thực hiện I/O mạng hay hệ thống tệp, và mối nối không bao giờ tự lắp ráp các claim assertion. extract() trả về null để báo hiệu vắng mặt; nó không bao giờ ném vì vắng mặt.
  • Ngữ nghĩa của Store. ManifestStore là một danh sách bất biến, có thứ tự các thực thể JumbfBox gốc, theo mô hình Manifest Store của C2PA 2.1 §11.1.1: một container JUMBF gộp một hoặc nhiều manifest, có thể định địa chỉ bằng URI. Nó không phơi bày bộ truy cập cấp claim nào. Thứ tự box được bảo toàn và mang tính quyết định cho tính bằng nhau khi round-trip.
  • Giới hạn gia cố. JumbfBoxParser từ chối vô điều kiện các đầu vào vượt bất kỳ giới hạn nào: kích thước mỗi box trên 64 MiB, store tích lũy trên 128 MiB, lồng sâu quá 8 cấp, hoặc hơn 4096 con trong một superbox. Không có cờ chính sách nào vô hiệu hóa các giới hạn này. Có thể tiêm giới hạn chặt hơn qua hàm dựng cho các tiến trình hạn chế bộ nhớ.
  • Từ chối theo cấu trúc. Trình phân tích cũng từ chối, fail-closed: LBox = 0 (BMFF đến-EOF), LBox = 1 (XLBox độ dài 64-bit), một LBox nhỏ hơn tiêu đề 8 byte, cắt cụt vượt quá đầu vào còn lại, byte TBox nằm ngoài ASCII in được (0x20–0x7E), tái nhập offset (chu trình), và việc lát con của payload superbox không khớp chính xác. Nó không bao giờ trả về một đồ thị được dựng một phần.
  • Định tuyến superbox. Các giá trị TBox trong SUPERBOX_TBOXES phân tích đệ quy thành các chuỗi con; mọi TBox khác là một lá với payload không rõ nội dung. cbor được cố ý xử lý như một lá vì an toàn của trình phân tích; các lớp phía trên phân tích lại payload của nó khi cần.
  • Cổng tiến trình. Feature::PREVIEW_C2PA_DRAFT mặc định tắt. isEnabled() trả về true chỉ khi NEXTPDF_FEATURE_PREVIEW_C2PA_DRAFT bằng đúng chuỗi 1. Việc đọc là trực tiếp trên mỗi lời gọi; không có gì được ghi nhớ.
  • Dựng fail-closed. new ExperimentalC2paEmbedder() ném LogicException khi cổng tắt. Thông điệp nêu tên cờ, biến môi trường, và SHA cùng ngày của bản nháp đã ghim. Người gọi không thể vô tình chạm tới việc tổng hợp bản nháp.
  • Hình dạng tổng hợp. buildManifestStore() phát ra một superbox c2pa chứa một manifest c2ma, vốn giữ một assertion store c2as (một assertion c2pa.hash.data) và một claim c2cl. Assertion ghi lại một hash assertion SHA-256 trên $sourceBytes; vì box Claim Signature c2cs bị bỏ qua và đầu ra không được ký, đây KHÔNG phải là một hard binding C2PA hay một phán quyết về nguồn gốc — nó chỉ đi theo hình dạng cấu trúc mà §9.1 mô tả. Payload của Description-box mang một type UUID, các toggle 0x03, và một nhãn UTF-8 kết thúc bằng null, theo C2PA 2.1 §11.1.4.1.1–11.1.4.1.2.
  • Không có Claim Signature. Box c2cs — theo C2PA 2.1 §11.1.4.4 là một box nội dung CBOR đơn lẻ được gán nhãn c2pa.signature — bị cố ý bỏ qua khỏi Store được tổng hợp. Đầu ra không được ký theo cấu trúc. Đây là vùng hồ sơ được đánh giá có khả năng trôi dạt cao nhất trước khi nhóm công tác đóng băng.
  • Ghim bản nháp, không bảo đảm BC. Định dạng wire được tổng hợp được ghim vào SPEC_PIN_SHA (4e2afed8…, ngày 2026-04-26) của c2pa-org/specifications. Nó có thể thay đổi mà không báo trước và không mang bảo đảm tương thích ngược nào.
  • Bất biến trung thực. C2paCapabilityStatus::current() mã hóa cứng generallyAvailableconformanceClaimed thành false. Không có cấu hình hay cờ môi trường nào lật một trong hai boolean đó. Chỉ previewEnabled phản ánh cổng; maturity là token không tuyên bố preview-draft.

Các trường hợp biên & chế độ thất bại

Phần tiêu đề “Các trường hợp biên & chế độ thất bại”
  • Đặt biến cổng thành 0, true, yes, on, hoặc một chuỗi rỗng để cổng tắt. Chỉ đúng chuỗi 1 mới bật nó.
  • Thay đổi bằng putenv() có hiệu lực ở lời gọi isEnabled() kế tiếp vì việc đọc là trực tiếp. Một cổng được bật/tắt giữa tiến trình được quan sát ngay lập tức.
  • extract() phân biệt hai kết cục: null khi không có Store nào (rẻ, không có ngoại lệ), và một lớp con C2paException được ném khi một Store hiện diện nhưng thù địch hoặc dị dạng. Vắng mặt không bao giờ là lỗi; hiện diện cộng với dị dạng thì luôn là lỗi.
  • JumbfBoxParser::parse('') trả về danh sách rỗng. Một ManifestStore rỗng nhưng hiện diện round-trip về chính nó; mối nối không thu gọn nó thành null.
  • Nhúng một Store rỗng CÓ THỂ trả về đầu vào không đổi. Hợp đồng của mối nối cho phép no-op này nhưng không bắt buộc nó.
  • Các đồ thị JumbfBox dựng thủ công chạy cùng mức gia cố tại thời điểm dựng: kiểm tra độ dài và ASCII của TBox, giới hạn độ sâu, bất biến độ sâu của con, quy tắc loại trừ payload-hoặc-con, và giới hạn kích thước mỗi box. Một bomb dựng thủ công thất bại lúc dựng, không phải lúc nhúng.
  • Mọi ngoại lệ của trình phân tích mang các trường có cấu trúc — capKind/observed/cap, offset, hoặc kind — nên đo lường không cần cào chuỗi thông điệp. Tất cả lớp con kế thừa C2paException (bản thân là một RuntimeException), vốn là loại catch bao trùm.
  • Docblock của trình phân tích cấm âm thầm nuốt các ngoại lệ này; người tiêu thụ phải phơi bày chúng hoặc ánh xạ lại chúng có chủ đích.
  • buildManifestStore() mã hóa payload JSON với JSON_THROW_ON_ERROR; một chuỗi $producer không phải UTF-8 hợp lệ sẽ thất bại với \JsonException trước khi bất kỳ box nào được dựng.
  • Một kết quả extract() đúng dạng chỉ là một tuyên bố về cấu trúc. Không có xác thực claim, không có xác minh chữ ký, và không có đánh giá tin cậy nào ở bất cứ đâu trên bề mặt này. Nhận diện không phải là một phán quyết về nguồn gốc.
  • Không có khóa ký, chứng chỉ, hay cấu trúc COSE nào được bề mặt này xử lý. Phép mật mã duy nhất là một hash nội dung SHA-256 bên trong đường tổng hợp có cổng.
Tuyên bốTiêu chuẩnĐiều khoản
Manifest chuỗi hóa vào một store JUMBF giữ nhiều manifest, định địa chỉ được bằng URI.C2PA 2.1§11.1.1 (p63.b)
Nhãn Description-box là UTF-8 kết thúc bằng null với các dải bị loại trừ; các toggle được định nghĩa cho mọi Description box.C2PA 2.1§11.1.4.1.1–11.1.4.1.2 (p63.a)
Box Claim Signature được gán nhãn c2pa.signature, kiểu c2cs, và giữ một box nội dung CBOR đơn lẻ.C2PA 2.1§11.1.4.4 (p63.c)
Một hard binding ràng buộc bằng mật mã một manifest với asset của nó và phơi bày sự sửa đổi — hash assertion không được ký của bản xem trước KHÔNG đạt mức này.C2PA 2.1§9.1 (p57)

Tất cả điều khoản đều được diễn giải lại. NextPDF không sao chép nguyên văn quy phạm. NextPDF không nắm giữ chứng nhận nào và không cấp chứng nhận nào. Các tuyên bố trên là các tuyên bố về căn chỉnh cấu trúc đối với bố cục box, nhãn, và ràng buộc — chúng không phải là kết quả kiểm thử tuân thủ, không phải chứng thực của bên thứ ba, và không phải một tuyên bố tuân thủ C2PA hay ISO. Hồ sơ C2PA-PDF chưa được hoàn thiện; định dạng wire được tổng hợp bám theo một commit nháp đã ghim. C2paCapabilityStatus mã hóa lập trường này trong mã: generallyAvailableconformanceClaimedfalse trong mọi cấu hình. Đầu ra từ bề mặt này không phải là một Content Credential xác minh được, và không có đường xác minh nào tồn tại trong NextPDF.

  • Ngữ pháp box JUMBF mà trình phân tích triển khai (LBox big-endian 4 byte, TBox ASCII 4 byte, payload; các superbox lồng các box con) tuân theo ISO 19566-5; tiêu chuẩn đó nằm ngoài kho trích dẫn, nên hành vi của trình phân tích được lấy từ mã nguồn sản phẩm, không phải một trích dẫn spec.

  • Giữ cổng tắt trong sản xuất. Việc tổng hợp bản nháp không thêm năng lực bền vững nào; các byte phát ra là tạm thời và nên được nhúng lại một khi một bộ điều hợp ổn định ra mắt.

  • Xác nhận ExperimentalC2paEmbedder::SPEC_PIN_SHA đối với commit nháp mà pipeline của bạn mong đợi. Chạy composer c2pa:draft-status trong CI (thoát 0 khi mới, 1 cảnh báo mềm, 2 thất bại cứng) để phát hiện ghim đã cũ.

  • Coi C2paCapabilityStatus::current() là nguồn sự thật duy nhất khi phơi bày trạng thái C2PA trong công cụ hoặc UI. Đừng phát biểu lại các boolean của nó bằng tay; summary() an toàn cho log và các endpoint trạng thái.

  • Bắt C2paException như loại bao trùm khi tiêu thụ extract() hoặc parse(). Ánh xạ bốn lớp con thành các bộ đếm đo lường riêng biệt dùng các trường có cấu trúc của chúng.

  • Tiêm giới hạn chặt hơn qua hàm dựng JumbfBoxParser cho các tiến trình xác minh hạn chế bộ nhớ; mặc định là các giới hạn sản xuất rộng rãi.

  • C2paCapabilityStatus::__construct() là public, nên một thực thể dựng thủ công có thể mang các boolean tùy ý. Một thực thể như vậy chỉ là một đối tượng giá trị; nó không thay đổi hành vi nào.

Trang này chỉ ghi lại hành vi quan sát được từ bên ngoài và bề mặt API công khai được hỗ trợ. Các đường dẫn namespace nội bộ, lớp trợ giúp, bảng cơ chế, tên tệp runbook, và tiền tố ticket nằm ngoài phạm vi.