blob: 6f79162a6befaf3fe90da7900e5bc768b55b976b [file] [view]
# 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`.