ISCC C2PA Conformance#
| IEP: | 0020 |
|---|---|
| Title: | ISCC C2PA Conformance |
| Author: | Titusz Pan tp@iscc.io |
| Comments: | https://github.com/iscc/iscc-ieps/issues/28 |
| Status: | Draft |
| Type: | Core |
| Standard: | IEP |
| License: | CC-BY-4.0 |
| Created: | 2026-09-24 |
| Updated: | 2026-10-28 |
Note
This document is a DRAFT. It specifies the C2PA soft binding algorithm io.iscc.v0, entry 3 of
the C2PA Soft Binding Algorithm List.
1. Introduction#
A C2PA Manifest binds provenance information to an asset. Its hard binding is a cryptographic hash of the asset bytes. Platforms often remove the C2PA Manifest when they process an asset. A change to the bytes, for example by resizing or re-encoding, also breaks the hard binding.
A soft binding is a fingerprint or watermark that helps in both cases. A resolver uses it to find the C2PA Manifest of an asset that no longer carries it. A validator uses it to compare an asset with the content from which the soft binding was extracted or generated.
The io.iscc.v0 soft binding value is a sequence of ISCC-UNITs. Each ISCC-UNIT describes a
different aspect of an asset.
An equal Instance-Code shows that an asset has exactly the bytes from which the ISCC soft binding was generated. For each other ISCC-UNIT, the distance between two codes indicates how much that aspect has changed. A resolver uses these distances to select candidates from its catalog. A secondary check suited to the use case and media type confirms or rejects each candidate.
2. Scope#
This document specifies the C2PA soft binding algorithm io.iscc.v0.
3. Terminology#
The terms ISCC-UNIT, ISCC-HEADER, ISCC-BODY, ISCC-CODE, MainType, SubType, Version, Length, Meta-Code, Semantic-Code, Content-Code, Image-Code, Data-Code and Instance-Code apply as defined in ISO 24138:2024 and IEP-0001. The terms asset, assertion, soft binding, claim generator, validator, C2PA Manifest, C2PA Manifest Store, claim signature, hashed URI and hard binding apply as defined in the C2PA Technical Specification.
resolver : service that returns C2PA Manifests for a soft binding query
ISCC-SEQ : byte string formed by concatenating the byte representations of one or more ISCC-UNITs
ISCC soft binding : ISCC-SEQ in a blocks[].value of a c2pa.soft-binding assertion with alg
equal to io.iscc.v0
source : complete byte stream into which a claim generator embeds a C2PA Manifest Store, including any C2PA Manifest Store that the byte stream already contains
query asset : asset for which C2PA Manifests are searched by soft binding
exact match : equality of a 256-bit Instance-Code of an ISCC soft binding and an Instance-Code of another ISCC-SEQ
candidate match : similarity of a Semantic-Code, Content-Code or Data-Code of an ISCC soft binding and an ISCC-UNIT of another ISCC-SEQ, at or above the threshold that the validator or resolver applies to that MainType and SubType
featureless Image-Code : Image-Code whose ISCC-BODY, divided from its first bit into consecutive 64-bit segments, has at least one complete segment with fewer than 8 bits set to 1
4. Soft Binding Value#
4.1 ISCC-SEQ Format#
An ISCC-SEQ shall satisfy all of the following:
- It shall consist of one or more ISCC-UNITs of MainType META (0), SEMANTIC (1), CONTENT (2), DATA (3) or INSTANCE (4).
- Each ISCC-UNIT shall be coded as its ISCC-HEADER immediately followed by its ISCC-BODY.
- Each ISCC-HEADER shall use the variable-length nibble encoding of ISO 24138:2024.
- Each Length field shall have a value from 0 to 7, for an ISCC-BODY of 32 × (Length + 1) bits.
- The ISCC-UNITs shall be concatenated without separators, length prefixes or trailing bytes.
The order of the ISCC-UNITs is not significant. An ISCC-SEQ may contain several ISCC-UNITs with the same MainType, SubType and Version.
The canonical form of an ISCC-SEQ is ISCC: followed by the Base32 encoding of its bytes, as for
any ISCC (see IEP-0001). An ISCC soft binding contains the bytes. The Soft Binding
Resolution API uses their base64 encoding.
4.2 Decoding#
A decoder shall process an ISCC-SEQ from offset 0 as follows:
- Decode the ISCC-HEADER at the current offset. Reject the ISCC-SEQ if the bytes end before the ISCC-HEADER is complete, or if the ISCC-HEADER bytes are not the encoding of the decoded fields as specified in ISCC-SEQ Format, item C.
- Reject the ISCC-SEQ if ISCC-SEQ Format, item A does not permit the MainType, or if the Length field is greater than 7.
- Reject the ISCC-SEQ if fewer bytes remain than the ISCC-BODY requires.
- Output the ISCC-UNIT and move the offset to the end of its ISCC-BODY. If bytes remain, continue with step A.
A decoder shall not reject an ISCC-UNIT only because its SubType or Version is unknown to it. A decoder shall not alter, reorder or drop ISCC-UNITs.
4.3 Assertion#
A c2pa.soft-binding assertion that contains ISCC soft bindings shall satisfy Table 1.
Table 1 – c2pa.soft-binding fields for io.iscc.v0
| Field | Requirement |
|---|---|
alg |
shall be io.iscc.v0 |
blocks[].scope |
shall be an empty map; a validator or resolver shall ignore a block with a non-empty scope |
blocks[].value |
shall be a CBOR byte string (major type 2) whose content is the bytes of an ISCC-SEQ of 256-bit ISCC-UNITs, or a CBOR array of unsigned integers from 0 to 255 whose items are these bytes in order |
alg-params |
not defined for io.iscc.v0; a validator or resolver shall ignore it |
bindingMetadata |
shall contain the member io.iscc.generator |
A claim generator should write blocks[].value as a byte string. A validator or resolver shall
accept both forms. It shall ignore a block whose value has any other form. Neither form shall
contain a text encoding of the ISCC-SEQ, such as its canonical form.
NOTE
c2pa-rs up to at least version 0.91.7 writes the array form for a soft binding assertion given as
JSON in a manifest definition
(c2pa-rs issue 2689). JSON reports show a byte
string in two ways: c2pa-rs up to version 0.91.7 shows it as a list of numbers, like the array form,
and crJSON
shows it as a text string b64'…' that holds its base64 encoding.
The member io.iscc.generator shall be a map that contains at least these two text string members:
name: the name of the software that generated the ISCC-UNITs, for exampleiscc-sdk;version: the version of that software, for example0.9.7.
If bindingMetadata contains the member informationalUrl, its value should be
https://ieps.iscc.codes/iep-0020/.
A validator or resolver shall not reject an assertion because its bindingMetadata is absent or
because of its content.
A claim generator that computes an ISCC soft binding should list its c2pa.soft-binding assertion
in created_assertions. A validator or resolver shall not ignore or reject an ISCC soft binding
because it is listed in gathered_assertions.
A C2PA Manifest should contain at most one ISCC soft binding.
EXAMPLE
This is the assertion that iscc-sdk soft-binding --no-semantic prints for the file
image/demo.jpg of iscc-samples. It has the form of an assertion in a JSON manifest definition of
c2pa-rs, as used by c2patool and c2pa-python. value holds the 136 bytes of the ISCC-SEQ as
integers: Meta-Code, Content-Code, Data-Code and Instance-Code. "created": true makes c2pa-rs list
the assertion in created_assertions.
{
"label": "c2pa.soft-binding",
"created": true,
"data": {
"alg": "io.iscc.v0",
"blocks": [
{
"scope": {},
"value": [
0, 7, 104, 227, 117, 199, 163, 217, 54, 188, 109, 0, 98, 225, 117, 146,
118, 143, 170, 251, 253, 93, 231, 225, 98, 214, 134, 87, 54, 167, 209, 171,
148, 63, 33, 7, 195, 67, 48, 158, 60, 158, 142, 103, 104, 225, 249, 124,
134, 105, 26, 150, 198, 100, 50, 204, 114, 218, 229, 51, 71, 147, 201, 142,
225, 201, 147, 101, 48, 7, 236, 234, 169, 93, 249, 226, 143, 208, 172, 164,
43, 108, 46, 160, 17, 94, 154, 40, 108, 192, 116, 72, 30, 164, 16, 119,
174, 199, 222, 2, 96, 30, 64, 7, 85, 82, 155, 250, 229, 189, 179, 213,
48, 197, 47, 68, 209, 60, 205, 106, 124, 113, 15, 99, 98, 13, 194, 219,
28, 67, 197, 89, 42, 226, 220, 151
]
}
],
"bindingMetadata": {
"informationalUrl": "https://ieps.iscc.codes/iep-0020/",
"io.iscc.generator": {
"name": "iscc-sdk",
"version": "0.9.7"
}
}
}
}
5. Soft Binding Generation#
A claim generator shall generate each ISCC-UNIT of an ISCC soft binding from the source. It shall include the Data-Code and the Instance-Code of the source in each ISCC soft binding. It should include a Content-Code if the source contains text, image, audio or video content. It may include a Semantic-Code and a Meta-Code. It shall not include a featureless Image-Code.
NOTE 1
A Meta-Code is thus generated from metadata embedded in the source, such as its title, not from a file name. iscc-sdk leaves it out if the source has no embedded title.
NOTE 2
ISO 24138:2024 does not define an algorithm for the Semantic-Code. The Version 0 Semantic-Codes for text and image are those of iscc-sct and iscc-sci. They are generated with neural network models. Semantic-Codes generated from the same content on different platforms or by different implementations can therefore differ in some bits.
6. Matching#
A validator or resolver shall ignore, for matching, each ISCC-UNIT that it does not support or whose ISCC-BODY is shorter than 256 bits.
To verify an ISCC soft binding against an asset, a validator shall generate from the asset an ISCC-UNIT with the same MainType, SubType, Version and Length for each ISCC-UNIT of the ISCC soft binding that it does not ignore.
A validator or resolver shall compare two ISCC-SEQs by pairs of ISCC-UNITs, one from each, with the same MainType, SubType, Version and Length: Instance-Codes for equality, all others by their similarity in percent, S = ⌊100 × (n − d) / n⌋, where d is the number of bit positions in which the two ISCC-BODYs differ and n is the length of an ISCC-BODY in bits. It shall not compare a pair of Image-Codes if either is featureless.
NOTE 1
Featureless Image-Codes occur for uniform images, brightness gradients along one axis and plain stripes. Featureless Image-Codes of unrelated images can be as close as Image-Codes of the same image.
An ISCC soft binding and an ISCC-SEQ match if there is an exact match or a candidate match between them. A validator or resolver without thresholds of its own should apply a threshold of 80 (d ≤ 51).
NOTE 2
S is 100 for equal ISCC-BODYs and about 50 for unrelated inputs. Suitable thresholds depend on the MainType and SubType, the content and the catalog size.
A c2pa.soft-binding assertion with alg equal to io.iscc.v0 matches if one of its ISCC soft
bindings matches. This is the matching to which Validating Soft Binding Matches of the C2PA
Technical Specification refers.
The score of a match is 100 for an exact match. Otherwise, it is the highest similarity of a pair of Semantic-Codes, Content-Codes or Data-Codes, but at most 99. A validator should report for each match the similarity of every compared pair and whether the Instance-Codes are equal.
Validating a Match of the C2PA Technical Specification applies to each matching C2PA Manifest.
NOTE 3
An exact match shows that the query asset has the bytes from which the ISCC soft binding was generated. The hard binding of the C2PA Manifest can still fail for the query asset, because these bytes lack the C2PA Manifest Store that the claim generator embedded.
7. Soft Binding Resolution API#
In a query to the C2PA Soft Binding Resolution API with alg equal to io.iscc.v0, value shall
be the base64 encoding of an ISCC-SEQ with padding characters, as specified in RFC 4648, section 4.
A resolver shall return the score of each match (see Matching) as similarityScore. It should list
the matches in descending order of score.
8. Security Considerations#
The claim signature protects an ISCC soft binding through the hashed URI of its assertion. An ISCC-SEQ has no integrity protection of its own.
Only the Instance-Code is a cryptographic hash. A match of any other ISCC-UNIT shows that two inputs are similar, not that they are identical. Unrelated content can have similar ISCC-UNITs, and an attacker can alter content until its ISCC-UNITs come close to those of other content. A secondary check of each candidate match, suited to the media type, guards against both.
An Instance-Code in a C2PA Manifest is public, and anyone can copy it into another C2PA Manifest. An exact match therefore does not show that the other assertions of the matching C2PA Manifest apply to the query asset, or who created the content.
9. Reference Implementation#
iscc-core 1.5.0 encodes and decodes ISCC-SEQs (encode_seq,
decode_seq). Earlier versions generate 256-bit Image-Codes that differ from those of the test
vectors.
iscc-sdk 0.9.7 generates ISCC soft bindings as specified in this
document. The Python function iscc_sdk.soft_binding() returns the ISCC-UNITs and the ISCC-SEQ. The
command iscc-sdk soft-binding FILE prints the assertion, as in the EXAMPLE in Assertion. Its
option --no-semantic leaves out Semantic-Codes. The function is_featureless_image_code() tests
whether an Image-Code is featureless.
10. Test Vectors#
10.1 ISCC-SEQ#
Conforming encoders shall produce the ISCC-SEQ of the following ISCC-UNITs, in this order. Conforming decoders shall accept this ISCC-SEQ and return these ISCC-UNITs in this order.
ISCC:AADVPDD4R6733NMPFH3D57VTQ4KVH6VHL74XIWGUT37V5ZG56NV3NSI
ISCC:EAD2RASIYU5IKLENP2OFI4CHZGRWYQCSW2WKX3Y6FJGOCXSYNYGLGBI
ISCC:GADQLNA7GRZESMRF2J7NZPNWGI3II2ST5YUN5SS6GVQ2ZQGJXPPYDNI
ISCC:IAD2KIVPJIWJZP3KQCESJL6SVT5APEZUPOJWM6HVTAXCF7OT3VFA4NY
0007578c7c8fbfbdb58f29f63efeb3871553faa75ff97458d49eff5ee4ddf36bb6c92007a88248c53a852c8d7e9c547047c9a36c4052b6acabef1e2a4ce15e586e0cb305300705b41f3472493225d27edcbdb63236846a53ee28deca5e3561acc0c9bbdf81b54007a522af4a2c9cbf6a808924afd2acfa0793347b936678f5982e22fdd3dd4a0e37
ISCC:AADVPDD4R6733NMPFH3D57VTQ4KVH6VHL74XIWGUT37V5ZG56NV3NSJAA6UIESGFHKCSZDL6TRKHAR6JUNWEAUVWVSV66HRKJTQV4WDOBSZQKMAHAW2B6NDSJEZCLUT63S63MMRWQRVFH3RI33FF4NLBVTAMTO67QG2UAB5FEKXUULE4X5VIBCJEV7JKZ6QHSM2HXE3GPD2ZQLRC7XJ52SQOG4
AAdXjHyPv721jyn2Pv6zhxVT+qdf+XRY1J7/XuTd82u2ySAHqIJIxTqFLI1+nFRwR8mjbEBStqyr7x4qTOFeWG4MswUwBwW0HzRySTIl0n7cvbYyNoRqU+4o3speNWGswMm734G1QAelIq9KLJy/aoCJJK/SrPoHkzR7k2Z49ZguIv3T3UoONw==
Conforming decoders shall reject the byte strings in Table 2.
Table 2 – Byte strings that decoders shall reject
| Bytes (hex) | Reason |
|---|---|
| (empty) | no ISCC-UNIT |
28000100000000 |
nonzero header padding nibble (valid form 28000000000000) |
200800 followed by 36 zero bytes |
Length field 8 |
3000000000 |
ISCC-BODY truncated (32-bit Data-Code with 3 body bytes) |
30000000000000 |
trailing byte after a complete ISCC-UNIT |
5005578c7c8fbfbdb58fa88248c53a852c8d05b41f3472493225a522af4a2c9cbf6a |
ISCC-CODE (MainType 5) |
60100000000000000000 |
MainType 6 |
Conforming decoders shall accept 270000000000 (CONTENT, SubType 7, Version 0, 32 bits) and return
ISCC:E4AAAAAAAA, although ISO 24138:2024 does not define SubType 7.
NOTE
The 32-bit acceptance test exercises the ISCC-SEQ codec only. It is not a conforming ISCC soft binding, which requires 256-bit ISCC-UNITs that include a Data-Code and an Instance-Code.
10.2 Featureless Image-Codes#
Conforming claim generators, validators and resolvers shall identify featureless Image-Codes as shown in Table 3.
Table 3 – Featureless Image-Codes
| Image-Code | Bits set to 1 per segment | Featureless |
|---|---|---|
ISCC:EEDYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
1, 0, 0, 0 | yes |
ISCC:EED74AAAAAAAAAAAVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKQ |
7, 32, 32, 32 | yes |
ISCC:EED76AAAAAAAAAAAVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKQ |
8, 32, 32, 32 | no |
ISCC:EED2VKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKAAAAAAAAAAAAA |
32, 32, 32, 1 | yes |
ISCC:EED2VKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKVKQ |
32, 32, 32, 32 | no |
10.3 Sample Inputs#
The file
c2pa_vectors.json of
iscc-sdk gives, for each input, its SHA-256 hash, the expected ISCC-UNITs and the ISCC-SEQ in hex
and base64. An input is either a file of iscc-samples, given
by its path relative to the files/ directory, or an embedded image. One embedded image is
featureless, so its ISCC soft binding has no Image-Code. Four embedded images test the border trim.
For each of them, image_crop gives the box (left, upper, right, lower) to which the image is
cropped before Image-Code generation. One of these boxes is the full image, because the trim keeps
its gradient border.
A claim generator should generate the same Meta-Codes, Content-Codes, Data-Codes and Instance-Codes from these inputs. The vectors contain no Semantic-Codes (see NOTE 2 in Soft Binding Generation).
NOTE
IEP-0004 specifies Image-Code conformance for the pre-processed 32 × 32 pixel input
only. The Image-Codes of the vectors use the border trim of iscc-sdk 0.9.7 (image_trim_tolerant).
Their Meta-Codes use the metadata that iscc-sdk 0.9.7 extracts from each file.
11. References#
11.1 Normative#
- ISO 24138:2024 - International Standard Content Code
- IEP-0001 - ISCC Structure and Format
- C2PA Technical Specification 2.4, Soft Binding assertion
- C2PA Technical Specification 2.4, Validating a Match
- C2PA Soft Binding Resolution API 2.4
- RFC 4648 - The Base16, Base32, and Base64 Data Encodings
- RFC 8949 - Concise Binary Object Representation (CBOR)
11.2 Informative#
- IEP-0004 - ISCC-UNIT Content-Code Image
- C2PA Soft Binding Algorithm List
- C2PA Content Credentials JSON (crJSON) 2.4
- iscc-core - Reference implementation
- iscc-sdk - Soft binding generation and test vectors
- iscc-sct - Semantic-Code Text
- iscc-sci - Semantic-Code Image
- iscc-samples - Sample files for ISCC testing
- c2pa-rs issue 2689 - Soft binding value encoding from JSON