C2PA Python

raw JSON →
0.32.6 verified Sat May 09 auth: no python

Python bindings for the C2PA Content Authenticity Initiative (CAI) library (v0.32.6, pre-1.0, monthly releases). Provides signing and verification of C2PA manifests for media provenance.

pip install c2pa-python
error c2pa.ValidationException: InvalidSignature
cause The signer certificate chain is incomplete or the private key does not match the certificate.
fix
Provide the full cert chain in sign_cert and ensure the private key matches the leaf certificate.
error ModuleNotFoundError: No module named 'c2pa'
cause The c2pa-python package is not installed or installed in a different environment.
fix
Run pip install c2pa-python and verify Python version >=3.10.
error TypeError: from_file() missing required positional argument: 'path'
cause Using `Reader.from_file` without a path string, or passing a file object.
fix
Use Reader.from_file('image.jpg') with a string file path.
breaking The `SignerInfo` API changed in v0.30.0: old `from_certs` removed, use `from_settings` with `private_key` and `sign_cert` keys.
fix Use `SignerInfo.from_settings({'alg': 'es256', 'private_key': '...', 'sign_cert': '...'})`.
deprecated `Reader.from_buffer` is deprecated in v0.32.0; use `Reader.from_bytes` instead.
fix Replace `Reader.from_buffer(data)` with `Reader.from_bytes(data)`.
gotcha The `Builder` requires the full chain of intermediate CA certificates in `sign_cert`; missing intermediates causes a validation error on verification.
fix Include the full certificate chain in the `sign_cert` value (PEM).

Verify C2PA manifest from file, then create and sign a new manifest using environment variables for credentials.

import os
from c2pa import Reader, Builder, SignerInfo
# Verify an image's C2PA manifest
reader = Reader.from_file('test_image.jpg')
print(reader.json())
# Sign an image
signer = SignerInfo.from_settings({
    'alg': 'es256',
    'private_key': os.environ.get('C2PA_PRIVATE_KEY', ''),
    'sign_cert': os.environ.get('C2PA_SIGN_CERT', '')
})
builder = Builder(signer)
manifest = {'claim_generator': 'my_app/1.0'}
output = builder.sign('input.jpg', 'output.jpg', manifest)
print(output)