Skip to content

Commit 3343416

Browse files
committed
feat: migrate to ISO 19566-5 conformant JUMBF manifest store
Replace the legacy JSON-in-fake-JUMB-box approach with a proper C2PA v2 binary manifest store format. New modules jumbf.py (ISO 19566-5 serializer/parser) and c2pa_claim.py (claim v2 CBOR builder) produce spec-conformant JUMBF superbox hierarchies with correct type UUIDs, CBOR assertion boxes, and COSE_Sign1 signatures. The signing pipeline in unicode_metadata.py now uses deterministic wrapper padding to break hash-avalanche circularity, builds proper assertion boxes with hashed references, and stores signer_id and context in dedicated CBOR assertions. Verification supports both new and legacy formats with graceful fallback. Deprecates serialize_jumbf_payload() and deserialize_jumbf_payload() with runtime warnings. Existing tests updated; new unit and integration tests cover JUMBF structure, claim hashes, hard/soft binding, tamper detection, and round-trip sign/verify.
1 parent 3e35877 commit 3343416

11 files changed

Lines changed: 1789 additions & 205 deletions

File tree

encypher/core/payloads.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import struct
3+
import warnings
34
from typing import Any, Literal, Optional, TypedDict, Union, cast
45

56
import cbor2
@@ -110,6 +111,7 @@ class OuterPayload(TypedDict, total=False):
110111
payload: Union[BasicPayload, ManifestPayload, str]
111112
signature: str # Base64 encoded signature string
112113
cose_sign1: str
114+
cbor_payload: str # Base64-encoded CBOR payload for detached COSE_Sign1 verification
113115

114116

115117
# --- End TypedDict Definitions ---
@@ -177,12 +179,16 @@ def deserialize_c2pa_payload_from_cbor(cbor_bytes: bytes) -> C2PAPayload:
177179
def serialize_jumbf_payload(payload: dict[str, Any]) -> bytes:
178180
"""Serializes a payload dictionary into a minimal JUMBF box.
179181
180-
The function creates a single JUMBF box with a 4 byte length field and a
181-
4 byte box type (``b"jumb"``). The payload is encoded as canonical JSON and
182-
stored as the box contents. This is **not** a full implementation of
183-
ISO/IEC 19566‑5 but provides a deterministic binary representation suitable
184-
for signing and unit tests.
182+
.. deprecated::
183+
Use ``encypher.interop.c2pa.jumbf.build_manifest_store`` for
184+
conformant C2PA JUMBF output. This function wraps JSON in a
185+
bare ``jumb`` box, which is not ISO 19566-5 conformant.
185186
"""
187+
warnings.warn(
188+
"serialize_jumbf_payload is deprecated. Use encypher.interop.c2pa.jumbf.build_manifest_store instead.",
189+
DeprecationWarning,
190+
stacklevel=2,
191+
)
186192
logger.debug("Attempting to serialize payload to JUMBF bytes.")
187193
try:
188194
json_bytes = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
@@ -196,7 +202,18 @@ def serialize_jumbf_payload(payload: dict[str, Any]) -> bytes:
196202

197203

198204
def deserialize_jumbf_payload(jumbf_bytes: bytes) -> dict[str, Any]:
199-
"""Deserializes bytes produced by :func:`serialize_jumbf_payload`."""
205+
"""Deserializes bytes produced by :func:`serialize_jumbf_payload`.
206+
207+
.. deprecated::
208+
Use ``encypher.interop.c2pa.jumbf.parse_manifest_store`` for
209+
conformant C2PA JUMBF parsing. This function only handles the
210+
legacy JSON-in-jumb format.
211+
"""
212+
warnings.warn(
213+
"deserialize_jumbf_payload is deprecated. Use encypher.interop.c2pa.jumbf.parse_manifest_store instead.",
214+
DeprecationWarning,
215+
stacklevel=2,
216+
)
200217
logger.debug(f"Attempting to deserialize {len(jumbf_bytes)} bytes from JUMBF.")
201218
try:
202219
if len(jumbf_bytes) < 8:

0 commit comments

Comments
 (0)