| // 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. | |
| // | |
| #ifndef THIRD_PARTY_CREDENTIO_CLAIM_MANIFEST_BOX_ENCODER_H_ | |
| #define THIRD_PARTY_CREDENTIO_CLAIM_MANIFEST_BOX_ENCODER_H_ | |
| #include <cstddef> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/base/nullability.h" | |
| #include "absl/container/flat_hash_map.h" | |
| #include "absl/functional/any_invocable.h" | |
| #include "absl/log/die_if_null.h" | |
| #include "absl/status/status.h" | |
| #include "absl/status/statusor.h" | |
| #include "absl/strings/cord.h" | |
| #include "assertion/assertion_encoder.h" | |
| #include "assertion/assertion_referencer.h" | |
| #include "claim/claim_cbor_encoder.h" | |
| #include "claim/manifest_box.h" | |
| #include "claim/signer.h" | |
| #include "constants/labels.h" | |
| #include "crypto/algorithms.h" | |
| #include "google/protobuf/repeated_ptr_field.h" | |
| #include "jumbf/box_builder.h" | |
| #include "proto/assertion.pb.h" | |
| #include "proto/generator_info.pb.h" | |
| #include "proto/hashed_uri.pb.h" | |
| #include "proto/multi_asset_hash_assertion.pb.h" | |
| namespace credentio { | |
| struct ManifestEncoderResult { | |
| // Generated JUMBF manifest store superbox. | |
| jumbf::BuiltSuperBox box; | |
| }; | |
| class ManifestBoxEncoder { | |
| public: | |
| ManifestBoxEncoder( | |
| const AssertionReferencer* absl_nonnull assertion_reference, | |
| const GeneratorInfo* absl_nonnull generator_info, | |
| const ClaimSigner* absl_nonnull claim_signer, | |
| const AssertionEncoder* absl_nonnull assertion_cbor_encoder, | |
| const ClaimCborEncoder* absl_nonnull claim_cbor_encoder, | |
| ManifestBox* absl_nonnull manifest, HashAlgorithm hash_algorithm) | |
| : assertion_reference_(*ABSL_DIE_IF_NULL(assertion_reference)), | |
| generator_info_(*ABSL_DIE_IF_NULL(generator_info)), | |
| claim_signer_(*ABSL_DIE_IF_NULL(claim_signer)), | |
| manifest_builder_(kStandardManifestUuid, | |
| {.label = absl::Cord(manifest->label)}), | |
| manifest_(*ABSL_DIE_IF_NULL(manifest)), | |
| hash_algorithm_(hash_algorithm), | |
| assertion_encoder_(*ABSL_DIE_IF_NULL(assertion_cbor_encoder)), | |
| claim_cbor_encoder_(*ABSL_DIE_IF_NULL(claim_cbor_encoder)) {} | |
| // Encodes the manifest to a JUMBF-type box. | |
| // Consumes the provided ManifestBox. | |
| // Encodings are done in the following order: | |
| // 1. Build all assertions, resolving references between them. | |
| // 2. Encode the claim and signature. | |
| // 3. Encode the assertion store. | |
| void Encode( | |
| const ClaimSigner::Options& options, | |
| absl::AnyInvocable<void(absl::StatusOr<ManifestEncoderResult>) &&> cb); | |
| private: | |
| // Encodes the given assertion and adds it to assertion_boxes_, | |
| // assertion_hashed_uris_, and assertion_url_to_index_. | |
| absl::Status AddAssertion(Assertion& assertion); | |
| // Populates hashes for hashed URIs in the given actions assertion, then adds | |
| // it via AddAssertion. | |
| absl::Status AddActionsAssertion(Assertion assertion); | |
| // Builds all assertions in the manifest and resolves references between | |
| // them, populating assertion_boxes_, assertion_hashed_uris_, and | |
| // assertion_url_to_index_. | |
| absl::Status AddAssertions(); | |
| // Encodes and signs the claim, adding claim and claim signature boxes to | |
| // manifest_builder_. | |
| void EncodeClaimAndSignature( | |
| const ClaimSigner::Options& options, | |
| absl::AnyInvocable<void(absl::StatusOr<ManifestEncoderResult>) &&> cb); | |
| // Adds the assertion store box to manifest_builder_. | |
| absl::Status EncodeAssertionStore(); | |
| // Populates hashed URIs in the given multi-asset hash assertion. | |
| // Assumes that the referenced part hash assertions have already been added. | |
| absl::Status PopulateMultiAssetPartHashes( | |
| MultiAssetHashAssertion* assertion) const; | |
| // Encodes a gathered assertion as a JSON content superbox, generates its | |
| // hashed URI, adds the box to assertion_boxes_, and adds the hashed URI to | |
| // gathered_assertion_hashed_uris_. | |
| absl::Status AddGatheredAssertion( | |
| const GatheredAssertion& gathered_assertion); | |
| const AssertionReferencer& assertion_reference_; | |
| const GeneratorInfo& generator_info_; | |
| const ClaimSigner& claim_signer_; | |
| jumbf::SuperBoxBuilder manifest_builder_; | |
| ManifestBox& manifest_; | |
| // Redacted assertions to be added to the claim. | |
| std::vector<std::string> redacted_assertions_; | |
| std::vector<jumbf::BuiltSuperBox> assertion_boxes_; | |
| google::protobuf::RepeatedPtrField<HashedUri> assertion_hashed_uris_; | |
| google::protobuf::RepeatedPtrField<HashedUri> gathered_assertion_hashed_uris_; | |
| // Map from relative assertion URL (e.g. | |
| // "self#jumbf=c2pa.assertions/c2pa.actions.v2") to index in assertion_uris_. | |
| // Needed for resolving references between assertions. | |
| absl::flat_hash_map<std::string, size_t> assertion_url_to_index_; | |
| HashAlgorithm hash_algorithm_; | |
| const AssertionEncoder& assertion_encoder_; | |
| const ClaimCborEncoder& claim_cbor_encoder_; | |
| }; | |
| } // namespace credentio | |
| #endif // THIRD_PARTY_CREDENTIO_CLAIM_MANIFEST_BOX_ENCODER_H_ |