blob: 1c97e9f45476221753629006b91c9b1c0fe8a38b [file]
// 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 }];
}