| # Credentio | |
| C++ libraries to support validation and generation of C2PA Content Credentials | |
| (https://c2pa.org/). | |
| NOTE: We are actively developing this project and may introduce breaking changes | |
| without notice. | |
| ## Supported Media Formats | |
| The library supports C2PA provenance validation (extracting and verifying an | |
| embedded C2PA manifest store) and generation (embedding a newly generated and | |
| signed C2PA manifest store) for the following container formats: | |
| <!-- mdformat off(no multiline table cells) --> | |
| Format | Extensions | Validation | Generation | |
| :-------------------------- | :------------------------ | :--------- | :--------- | |
| JPEG | `.jpg`, `.jpeg` | Yes | [Yes](formats/jpeg/writer.h) | |
| PNG | `.png` | Yes | [Yes](formats/png/writer.h) | |
| MP4 | `.mp4` | Yes | [Yes](formats/bmff/writer.h) | |
| fMP4 (fragmented MP4) | | No | No | |
| RIFF (e.g., WebP, WAV, AVI) | `.webp`, `.wav`, `.avi` | Yes | [Yes](formats/riff/writer.h) | |
| TIFF (e.g., TIFF, DNG) | `.tif`, `.tiff`, `.dng` | Yes | [Yes](formats/tiff/writer.h) | |
| AVIF | `.avif` | Yes | [Yes](formats/bmff/writer.h) | |
| M4A | `.m4a` | Yes | [Yes](formats/bmff/writer.h) | |
| HEIF, HEIC | `.heif`, `.heic` | Yes | [Yes](formats/bmff/writer.h) | |
| MOV | `.mov` | Yes | [Yes](formats/bmff/writer.h) | |
| GIF | `.gif` | Yes | [Yes](formats/gif/writer.h) | |
| MP3 | `.mp3` | Yes | [Yes](formats/id3/writer.h) | |
| FLAC | `.flac` | Yes | [Yes](formats/id3/writer.h) | |
| PDF | `.pdf` | Yes | [Yes](formats/pdf/writer.h) | |
| SVG | | No | No | |
| OGG Vorbis | | No | No | |
| Text | | No | No | |
| Live stream video | | No | No | |
| ZIP-based containers | `.docx`, `.pptx`, `.xlsx` | Yes | [Yes](formats/zip/writer.h) | |
| Fonts | | No | No | |
| <!-- mdformat on --> | |
| ## Prerequisites | |
| * Clang with libc++ (tested with Clang 19). `.bazelrc` builds with `clang` and | |
| `clang++` against libc++, so both must be on `PATH` and the libc++ | |
| development packages must be installed. | |
| * [Bazelisk](https://github.com/bazelbuild/bazelisk), installed as `bazel`. It | |
| downloads the Bazel version pinned in `.bazelversion`. | |
| * Git | |
| On Ubuntu, CI sets these up as follows: | |
| ```shell | |
| # Clang 19, including libc++, from the LLVM apt repository. | |
| sudo apt-get install -y lsb-release wget software-properties-common gnupg | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh 19 all | |
| sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 | |
| sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100 | |
| # Bazelisk. | |
| curl -sLO https://github.com/bazelbuild/bazelisk/releases/latest/download/bazelisk-linux-amd64 | |
| chmod +x bazelisk-linux-amd64 | |
| sudo mv bazelisk-linux-amd64 /usr/local/bin/bazel | |
| ``` | |
| Bazel caches the detected C++ toolchain, so after installing or changing the | |
| compiler or libc++, run `bazel clean --expunge` before building again. | |
| ## Dependencies | |
| * [Abseil (`abseil-cpp`)](https://abseil.io/) | |
| * [Riegeli](https://github.com/google/riegeli) | |
| * [BoringSSL](https://github.com/google/boringssl) | |
| * [GoogleTest (`googletest`)](https://github.com/google/googletest) | |
| * [Google Tink (`tink_cc`)](https://github.com/tink-crypto/tink-cc) | |
| * [LibCppBor](https://android.googlesource.com/platform/system/libcppbor/) | |
| * [nlohmann_json](https://github.com/nlohmann/json) | |
| * [Protocol Buffers (`protobuf`)](https://github.com/protocolbuffers/protobuf) | |
| ## Quickstart | |
| Credentio includes fast standalone command-line tools for inspecting, verifying, | |
| and writing C2PA metadata embedded in media assets. | |
| ### Building the CLIs | |
| Build the tools once: | |
| ```bash | |
| bazel build tools:c2pa_validate tools:asset_write | |
| ``` | |
| The binaries are written to `bazel-bin/tools/c2pa_validate` and | |
| `bazel-bin/tools/asset_write`. | |
| ### Validating C2PA Metadata | |
| #### Validating with Trust Anchors | |
| You can validate assets against specific PEM-encoded trust anchors for claim | |
| signers and Time Stamping Authorities (TSA): | |
| ```bash | |
| bazel-bin/tools/c2pa_validate \ | |
| --asset=/path/to/asset.jpg \ | |
| --claim_signer_trust=/path/to/claim_signer_trust_anchors.pem \ | |
| --tsa_trust=/path/to/tsa_trust_anchors.pem | |
| ``` | |
| > **Note on Trust Lists:** Credentio does not distribute or provide trust anchor | |
| > lists. You can obtain the latest official C2PA trust lists from the C2PA | |
| > organization on GitHub | |
| > ([https://github.com/c2pa-org/conformance-public/tree/main/trust-list](https://github.com/c2pa-org/conformance-public/tree/main/trust-list)). | |
| ### Writing C2PA Metadata | |
| The `asset_write` tool generates a C2PA manifest store, signs it with the | |
| provided claim signer key, and embeds it into a copy of the input asset. The | |
| media type is inferred from the input file extension. | |
| #### Creating Test Keys and Certificates | |
| `asset_write` needs an EC P-256 key and certificate for the claim signer, and | |
| optionally another pair for the Time Stamping Authority (TSA). For local | |
| testing, [`tools/create_test_pki.sh`](tools/create_test_pki.sh) creates a | |
| private root CA and issues both certificates from it. It requires OpenSSL 1.1.1 | |
| or later: | |
| ```bash | |
| tools/create_test_pki.sh test_pki | |
| ``` | |
| The script refuses to overwrite existing keys. It produces: | |
| * `claim_signer_key.pem` and `claim_signer_cert.pem`: pass to | |
| `--claim_signer_key` and `--claim_signer_cert`. | |
| * `tsa_key.pem` and `tsa_cert.pem`: pass to `--tsa_key` and `--tsa_cert`. | |
| * `root_ca_cert.pem`: pass to `--claim_signer_trust` and `--tsa_trust` when | |
| validating. | |
| #### Writing a Manifest Store | |
| ```bash | |
| bazel-bin/tools/asset_write \ | |
| --input=/path/to/input.jpg \ | |
| --output=/path/to/output.jpg \ | |
| --claim_signer_key=/path/to/claim_signer_key.pem \ | |
| --claim_signer_cert=/path/to/claim_signer_cert_chain.pem \ | |
| --tsa_key=/path/to/tsa_key.pem \ | |
| --tsa_cert=/path/to/tsa_cert.pem | |
| ``` | |
| Flags: | |
| * `--claim_signer_key`: PEM-encoded EC P-256 private key of the claim signer. | |
| * `--claim_signer_cert`: PEM-encoded claim signer certificate chain, leaf | |
| first. | |
| * `--claim_signer_ocsp` (optional): DER-encoded OCSP response for the claim | |
| signer certificate. | |
| * `--tsa_key`, `--tsa_cert` (optional): PEM-encoded EC P-256 private key and | |
| certificate used to timestamp the claim signature locally. If omitted, | |
| timestamping is disabled. | |
| * `--disable_timestamping` (optional): Disables timestamping. | |
| * `--request_txtpb` (optional): Text-format | |
| [`GenerateManifestStoreRequest`](proto/generator.proto) describing the | |
| manifest to generate. Defaults to a single `c2pa.created` action. | |
| #### End-to-End Example | |
| Using the files from | |
| [Creating Test Keys and Certificates](#creating-test-keys-and-certificates), | |
| sign an asset and validate it against the test root CA. Run these commands from | |
| the repository root: | |
| ```bash | |
| tools/create_test_pki.sh test_pki | |
| bazel-bin/tools/asset_write \ | |
| --input=/path/to/input.jpg \ | |
| --output=signed.jpg \ | |
| --claim_signer_key=test_pki/claim_signer_key.pem \ | |
| --claim_signer_cert=test_pki/claim_signer_cert.pem \ | |
| --tsa_key=test_pki/tsa_key.pem \ | |
| --tsa_cert=test_pki/tsa_cert.pem | |
| bazel-bin/tools/c2pa_validate \ | |
| --asset=signed.jpg \ | |
| --claim_signer_trust=test_pki/root_ca_cert.pem \ | |
| --tsa_trust=test_pki/root_ca_cert.pem | |
| ``` | |
| The validation result should report `claimSignature.validated`, | |
| `signingCredential.trusted` and `timeStamp.trusted` with no failures. | |
| > **Note:** `asset_write` signs with locally supplied keys and is intended for | |
| > development and testing. Manifest stores it produces are only trusted by | |
| > validators that trust the supplied certificates. | |
| ## Building & Testing | |
| To build the entire project: | |
| ```bash | |
| bazel build ... | |
| ``` | |
| To execute all unit tests: | |
| ```bash | |
| bazel test ... | |
| ``` | |
| ## Support & Releases | |
| Credentio recommends that users **live-at-head** (updating to the latest commit | |
| on the main branch as often as possible). We are actively developing this | |
| project and may introduce breaking changes without notice. | |
| ## License & Disclaimer | |
| Credentio is licensed under the terms of the Apache 2.0 License. See | |
| [LICENSE](LICENSE) for more information. | |
| ### Disclaimer | |
| This is not an officially supported Google product. This project is not eligible | |
| for the | |
| [Google Open Source Software Vulnerability Rewards Program](https://bughunters.google.com/open-source-security). | |
| ## Contact | |
| For questions, feedback, or inquiries, please contact: | |
| `credentio-team@google.com`. |