Validation

📘

Learn more

To learn more general, cross-platform concepts about C2PA validation, see Understand C2PA and Validate C2PA.

The ClaimValidator is used to extract a C2PA Manifest Store from a media file and validate all the Claims in that Manifest Store.

Create a ClaimValidator Instance

Instances of the ClaimValidator are created with the C2PAFactory:

#include "C2PA/C2PAFactory.hpp"

void main() {
  auto cv = c2pa::C2PAFactory::new_claim_validator(
    // no options specified yields default behavior
  );
}

The returned instance is wrapped in a std::unique_ptr, so it will be automatically destroyed when it goes out of scope.

If you need the ClaimValidator to persist beyond the scope in which it was created, you can do so by using the move_unique_to_shared() utility function to move it to a std::shared_ptr. For example:

#include "common/common_utils.hpp"

auto cv_shared = common_utils::move_unique_to_shared(cv);

Customizing ValidationOptions

The ClaimValidator's behavior may optionally be customized with a ValidationOptions structure:

auto cv_opt = c2pa::C2PAFactory::new_validation_options();
// Modify the options as desired before passing them to the "constructor".
auto cv = c2pa::C2PAFactory::new_claim_validator(cv_opt);

The following sections describe the most common options that can be configured with this structure, while some more obscure configuration options are described in the Advanced Workflows section.

Disable the built-in trust list

By default, the ClaimValidator uses a compiled-in trust list that contains root certificates for Truepic, Adobe, Microsoft, and others. This trust list can be disabled, if desired.

cv_opt->disable_builtin_trust_list = true;

Specify a user-defined trust list

The user_trust_list property allows the user to specify a set of trust roots that can be used (in addition to the built-in trust list) to establish trust in signer certificates. It is a list of ReadOnlyAssetPtr objects, and so can contain any mixture of files and data buffers, each containing a certificate in either DER or PEM format. In the case of PEM data, it is acceptable to pass in a certificate chain as a single Asset object.

cv_opt->user_trust_list.push_back(
  c2pa::C2PAFactory::new_read_only_file_asset("my_root_cert.pem"));
cv_opt->user_trust_list.push_back(
  c2pa::C2PAFactory::new_copy_buffer_asset(other_root_cert_der_buffer));
cv_opt->user_trust_list.push_back(
  c2pa::C2PAFactory::new_read_only_file_asset("a_cert_chain.pem"));

Disable OCSP check

By default, the ClaimValidator will always perform an OCSP check to determine if the signer certificate has been revoked (when there is an OCSP service specified in the AIA extension of the certificate.) It might be preferable to disable this check in situations where the network is unavailable, or where the increased time to contact an OCSP server for this check is undesirable. If the perfrom_ocsp_check property is set to false, then the certificate validation status will be WARNING, but the overall manifest validation will succeed if all other statuses are okay.

cv_opt->perform_ocsp_check = false;

Specify the minimum validation specification version

The minimum_spec_version field specifies the minimum specification version that the input file must adhere to in order to be considered valid. It selects the set of rules that will be used to validate the file. Valid values are 1.0, 1.1, 1.2, 1.3, 1.4, 2.0, and 2.1. The default value is 1.4.

cv_opt->minimum_spec_versioin = 2.1;

Perform Validation

The validate_media() method is used to perform validation on a media file.

validate_media()

This returns a ValidationResult structure providing details of the validation operation. If any portion of the validation fails, then this will return false. The validation_report output parameter will contain more details about the specific failure(s) that occurred.

  • c2pa::ReadOnlyAssetPtr media - An Asset object containing information about how to obtain the media data to use in the validation operation.
auto result = cv->validate_media(
  c2pa::C2PAFactory::new_read_only_file_asset("images/image.jpg));

ValidationResult structure

The validate_media() method returns a ValidationResult structure. This structure has the following form:

struct ValidationResult {
  bool is_valid;
  std::string validation_report;
  std::vector<c2pa::ThumbnailInfoPtr> thumbnails;
};
  • is_valid - If any portion of the validation fails, then this property will be false. The validation_report property will contain more details about the specific failure(s) that occurred.
  • validation_report - This property will be populated with a serialized JSON structure with detailed information about the C2PA Manifest Store and the status of its validation.
  • thumbnails - This property will be populated with an array of thumbnail info structures; one for each thumbnail assertion found in the C2PA Manifest Store.

Advanced Workflows

The ClaimValidator supports some advanced workflows that require more effort than the standard validation workflow, but provide more flexibility.

Partial validation

The buffer version of validate_media() can be called with just the beginning of the media file, and if the ClaimValidator is able to find the C2PA Manifest Store in the provided data, then it will go ahead and perform validation on it. The hard binding assertion, which relies on a hash of the entire file, is almost guaranteed to fail, but the rest of the validation_report might provide some valuable information about the media.

If no Manifest Store is found, or if only a part of the Manifest Store is found, then the validate_media() call will throw a common::runtime_error_with_context exception, and the structure returned by the manifest_parser_info() method of the exception may provide enough information to determine the size of the Manifest Store. The client can then use the update_media_data() method of the ClaimValidator to add more media data and attempt to revalidate. See libc2pa Exceptions

If update_media_data() is being called in a loop in one part of a program, to validate a media file in piecemeal chunks, then the progress_update_method property of the ValidationOptions structure can be set to a method to be used to notify another part of the program of the validation progress.

Custom OCSP send method

If a client application wants to perform an OCSP check, but doesn't want the libc2pa code to make network calls (for example if the network stack is complicated) then the client can provide its own method to perform the OCSP check. This is done by setting the ocsp_send_method property on the ValidationOptions structure.

If an OCSP send method has been provided, then the ClaimValidator will call that method when it gets to the OCSP check. Otherwise, if no send method has been provided, it will attempt to contact the OCSP server itself.

In some situations, it might not be convenient to perform an asynchronous network call at the time that the OCSP check is requested. In this case, the client can store off the OCSP check parameters for later use, and can perform the check at some other time. It can then call the ClaimValidator's update_ocsp_response() method to modify the validation_report with the results of the OCSP check.