| // Copyright 2026 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| edition = "2024"; |
| |
| package credentio; |
| |
| import "cbor/tags.proto"; |
| |
| // A BMFF-based hash assertion. See |
| // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_bmff_based_hash. |
| message BmffBasedHashAssertion { |
| // Excludes certain boxes from the hash. |
| repeated BmffRange exclusions = 1 |
| [(cbor.tags) = { is_required: true, disallow_empty: true }]; |
| // A string identifying the cryptographic hash algorithm. |
| string alg = 2; |
| bytes hash = 3; |
| repeated BmffMerkle merkles = 4 [(cbor.tags) = { name: "merkle" }]; |
| // A human-readable description of what this hash covers. |
| string name = 5; |
| } |
| |
| message BmffRange { |
| // Location of box(es) of the hash starting from the root node as an xpath |
| // formatted string of version https://www.w3.org/TR/xpath-10/ with highly |
| // constrained syntax. |
| string xpath = 1 [(cbor.tags) = { is_required: true }]; |
| // Length of a leafmost box of the hash. |
| int64 length = 2; |
| // The data in the leafmost box. |
| repeated BmffData data = 3; |
| // Only subsets of the data in the leafmost box. |
| repeated BmffSubset subsets = 4 [(cbor.tags) = { name: "subset" }]; |
| int64 version = 5; |
| bytes flags = 6; |
| // Whether flags must be an exact match. |
| bool exact = 7; |
| } |
| |
| message BmffData { |
| int64 offset = 1 [(cbor.tags) = { is_required: true }]; |
| bytes value = 2 [(cbor.tags) = { is_required: true }]; |
| } |
| |
| message BmffSubset { |
| int64 offset = 1 [(cbor.tags) = { is_required: true }]; |
| int64 length = 2 [(cbor.tags) = { is_required: true }]; |
| } |
| |
| message BmffMerkle { |
| // Unique id that differentiates across files to determine which Merkle |
| // tree should be used to validate a given 'mdat' box. |
| int64 unique_id = 1 [(cbor.tags) = { is_required: true, name: "uniqueId" }]; |
| // Local id used to differentiate across multiple 'mdat' boxes within a single |
| // file to determine which Merkle tree should be used to validate that 'mdat' |
| // box. |
| int64 local_id = 2 [(cbor.tags) = { is_required: true, name: "localId" }]; |
| // Number of leaf nodes in the Merkle tree. |
| int64 count = 3 [(cbor.tags) = { is_required: true }]; |
| // A string identifying the cryptographic hash algorithm |
| string alg = 4; |
| // The hash of the entire initialization segment file for fragmented assets |
| // like MP4. |
| bytes init_hash = 5 [(cbor.tags) = { name: "initHash" }]; |
| // Representing a single row of the Merkle tree. |
| repeated bytes hashes = 6 |
| [(cbor.tags) = { is_required: true, disallow_empty: true }]; |
| // The following two fields are used to determine the block size of the |
| // Merkle tree and are only used for non-fragmented assets. Only one of them |
| // can be set. FixedBlockSize breaks the input string into fixed-size blocks, |
| // while VariableBlockSizes uses a list of block sizes to determine the block |
| // size of each block. |
| int64 fixed_block_size = 7 |
| [(cbor.tags) = { name: "fixedBlockSize", type: TYPE_UINT }]; |
| repeated int64 variable_block_sizes = 8 |
| [(cbor.tags) = { name: "variableBlockSizes" }]; |
| } |
| |
| // Auxiliary data for a Merkle map. See |
| // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_box_containing_the_merkle_auxiliary. |
| message BmffMerkleMap { |
| // Unique ID used in combination with the local ID to identify the BMFFMerkle |
| // map. |
| int64 unique_id = 1 [(cbor.tags) = { is_required: true, name: "uniqueId" }]; |
| int64 local_id = 2 [(cbor.tags) = { is_required: true, name: "localId" }]; |
| // The zero-based index of this leaf in the leaf row of the Merkle map. |
| int64 location = 3 [(cbor.tags) = { is_required: true }]; |
| // A series of hashes that are sequentially hashed against the leaf data hash |
| // via merkle proof to generate the final hash to be compared against the |
| // corresponding hash in the Merkle map. |
| repeated bytes hashes = 4 [(cbor.tags) = { disallow_empty: true }]; |
| } |