C2PA manifest embedding for AI/ML model container formats: GGUF, SafeTensors, and ONNX
Project description
c2pa-ml
C2PA manifest embedding for AI/ML model container formats: GGUF, SafeTensors, and ONNX
Overview
Associates a C2PA Manifest Store with an AI/ML model by writing it into the model container's own metadata slot, so the model stays loadable by its usual runtime. Three formats are supported:
| Format | Metadata slot | Manifest encoding |
|---|---|---|
| GGUF (llama.cpp) | typed key/value metadata | c2pa.manifest as a UINT8 array (raw bytes) |
| SafeTensors | JSON header __metadata__ |
c2pa.manifest as Base64 |
| ONNX | protobuf metadata_props |
c2pa.manifest as Base64 |
A remote (or side-car) manifest can instead be referenced by URI under c2pa.manifest.uri, or both an embedded store and a URI can be written together.
The C2PA Technical Specification defines no dedicated embedding method for model containers; a manifest embedded in a model declares what the asset is with the asset type assertion. This crate provides the canonical c2pa.types.model.* strings for that assertion.
Zero dependencies on native targets; the WebAssembly/npm build uses only wasm-bindgen.
Quick Start
[dependencies]
c2pa-ml = "0.1"
Embed a manifest
use c2pa_ml::{embed_manifest, ManifestSource};
let model: &[u8] = /* .gguf / .safetensors / .onnx bytes */;
let store: Vec<u8> = /* C2PA Manifest Store bytes */;
// Embed a Manifest Store directly (format is auto-detected)...
let signed = embed_manifest(model, &ManifestSource::embedded(store)).unwrap();
// ...or reference a remote manifest by URI...
let signed = embed_manifest(model, &ManifestSource::remote("https://example.com/m.c2pa")).unwrap();
// ...or both.
let signed = embed_manifest(model, &ManifestSource::both("https://example.com/m.c2pa", vec![/* ... */])).unwrap();
Read a manifest
use c2pa_ml::{read_manifest, read_manifest_uri};
let store = read_manifest(&signed).unwrap(); // embedded Manifest Store bytes
let uri = read_manifest_uri(&signed).unwrap(); // Option<String>: active manifest URI
Verify presence
use c2pa_ml::verify;
let report = verify(&signed).unwrap();
assert!(report.is_compliant());
// report.format, report.has_embedded_manifest, report.has_remote_uri
Declare the asset type
use c2pa_ml::Format;
let model_type = Format::detect(&signed).unwrap().model_type();
assert_eq!(model_type.as_str(), "c2pa.types.model.onnx"); // for an ONNX model
Explicit format
ONNX has no magic number, so auto-detection matches it last as a best-effort protobuf shape check. When the format is known in advance, use embed_manifest_as, or call the per-format module (gguf, safetensors, onnx) directly.
use c2pa_ml::{embed_manifest_as, Format, ManifestSource};
let signed = embed_manifest_as(model, Format::Onnx, &ManifestSource::embedded(store)).unwrap();
Other languages
The same API is published for JavaScript and Python from this crate, so it also serves Node, pnpm, and browser/bundler users.
npm / pnpm (WebAssembly)
npm install c2pa-ml # or: pnpm add c2pa-ml
import { embedManifest, readManifest, detectFormat } from "c2pa-ml";
const signed = embedManifest(model, store); // Uint8Array in, Uint8Array out
const manifest = readManifest(signed);
PyPI
pip install c2pa-ml
import c2pa_ml
signed = c2pa_ml.embed_manifest(model, store) # bytes in, bytes out
manifest = c2pa_ml.read_manifest(signed)
fmt = c2pa_ml.detect_format(model) # "GGUF" | "SafeTensors" | "ONNX" | None
Design
- The Manifest Store and/or manifest URI are stored under the reserved keys
c2pa.manifest/c2pa.manifest.uriin the format's native metadata slot - GGUF: metadata is re-serialized and the tensor-data region is re-padded to
general.alignment; tensor-info offsets are relative to that region, so tensor data is never rewritten - SafeTensors: only the JSON header is rewritten; each tensor's
data_offsetsare relative to the data block and stay valid - ONNX: only the top-level protobuf field stream is rewritten; every other field (
ir_version,graph,opset_import, …) is copied through verbatim - Embedding replaces any existing C2PA entries;
remove_manifestrestores the model to its unembedded bytes
Scope
This crate implements embedding and extraction only. Manifest construction, signing, and content (hard/soft) binding are out of scope; use the official C2PA SDK to build and sign manifests. The c2pa.hash.data assertion should exclude the metadata region carrying the Manifest Store.
Related Crates
| Crate | Description |
|---|---|
| c2pa-fonts | OpenType/TrueType (SFNT) font embedding |
| c2pa-warc | WARC web archive embedding (ISO 28500) |
| c2pa-zip | ZIP-based (OCF) document embedding: EPUB, DOCX, ODT |
| c2pa-structured-text | Structured text embedding via ASCII armour delimiters |
| c2pa-rs | Official C2PA SDK |
License
Licensed under either of Apache License, Version 2.0 or MIT License at your option.
Built by WritersLogic
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file c2pa_ml-0.1.0.tar.gz.
File metadata
- Download URL: c2pa_ml-0.1.0.tar.gz
- Upload date:
- Size: 31.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eeb013d18832b4bafbbafbb5abba27eb216311388aa835d59d414f6b23c39361
|
|
| MD5 |
5c4f6a3992cfad6c4fd90f8acef263ad
|
|
| BLAKE2b-256 |
b68e60f85208e329c11ee4d4f0a3e24755cd3e5aa07c0432bfbf80241d5270b2
|
Provenance
The following attestation bundles were made for c2pa_ml-0.1.0.tar.gz:
Publisher:
release.yml on writerslogic/c2pa-ml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
c2pa_ml-0.1.0.tar.gz -
Subject digest:
eeb013d18832b4bafbbafbb5abba27eb216311388aa835d59d414f6b23c39361 - Sigstore transparency entry: 2165090017
- Sigstore integration time:
-
Permalink:
writerslogic/c2pa-ml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/writerslogic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file c2pa_ml-0.1.0-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: c2pa_ml-0.1.0-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 134.2 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6f55b9f470bf3e2c70f0a38a39fa33c8478fb08e08f95950acaffb552fd569e
|
|
| MD5 |
5e45debcca530fa5b7f0c9166615217a
|
|
| BLAKE2b-256 |
d781fb4d5fc452f9f86e363550e43a0bc5d39e8623d643e0e4973a2e2b7b2cc8
|
Provenance
The following attestation bundles were made for c2pa_ml-0.1.0-cp39-abi3-win_amd64.whl:
Publisher:
release.yml on writerslogic/c2pa-ml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
c2pa_ml-0.1.0-cp39-abi3-win_amd64.whl -
Subject digest:
a6f55b9f470bf3e2c70f0a38a39fa33c8478fb08e08f95950acaffb552fd569e - Sigstore transparency entry: 2165090084
- Sigstore integration time:
-
Permalink:
writerslogic/c2pa-ml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/writerslogic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 268.5 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ff5ba4c04b254f0fe7711633d20975a37e1c8ee509485fbc8df11bd6b893b47
|
|
| MD5 |
213a701ef9754a1f45647f5dfbb11525
|
|
| BLAKE2b-256 |
4775247ad7fdc57daaad5e454a478c27375f74fa7e94eac1654d09c3e061c923
|
Provenance
The following attestation bundles were made for c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on writerslogic/c2pa-ml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
2ff5ba4c04b254f0fe7711633d20975a37e1c8ee509485fbc8df11bd6b893b47 - Sigstore transparency entry: 2165090059
- Sigstore integration time:
-
Permalink:
writerslogic/c2pa-ml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/writerslogic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 265.1 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4e937815358068d523444050494a8e5fe031aff337e21b59bc9b7e8bed434b3
|
|
| MD5 |
e853cdf25582e67c92079072cf15acc3
|
|
| BLAKE2b-256 |
c6f4794041cd6071ae9cbb0ae251071b274229e9cc00be4ba7437e8c3b92f256
|
Provenance
The following attestation bundles were made for c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on writerslogic/c2pa-ml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
c2pa_ml-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
a4e937815358068d523444050494a8e5fe031aff337e21b59bc9b7e8bed434b3 - Sigstore transparency entry: 2165090034
- Sigstore integration time:
-
Permalink:
writerslogic/c2pa-ml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/writerslogic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file c2pa_ml-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: c2pa_ml-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 239.1 kB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
797bb2b702a314121f91ace41a5fc62c743e898b53a7e41e88cd97c87b489b0f
|
|
| MD5 |
5f44ab26cf7ad7e6cd9e9f3518d08baa
|
|
| BLAKE2b-256 |
37857c2fcb608d78bedd0d111d37770de6fee59b307dc2b1317149a9ae72a579
|
Provenance
The following attestation bundles were made for c2pa_ml-0.1.0-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on writerslogic/c2pa-ml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
c2pa_ml-0.1.0-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
797bb2b702a314121f91ace41a5fc62c743e898b53a7e41e88cd97c87b489b0f - Sigstore transparency entry: 2165090048
- Sigstore integration time:
-
Permalink:
writerslogic/c2pa-ml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/writerslogic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file c2pa_ml-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: c2pa_ml-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 240.6 kB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e2a4103ea09a36db1084cfa936e66e629e5d29b102bbfe49cc65e2dd5e9a718
|
|
| MD5 |
43f64b4250ec79dc7b3633e544c74150
|
|
| BLAKE2b-256 |
d080f103b14d6331ef2f8177b1d93c6f718d5e63f7843d762c63dbcd54ebb16e
|
Provenance
The following attestation bundles were made for c2pa_ml-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on writerslogic/c2pa-ml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
c2pa_ml-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
4e2a4103ea09a36db1084cfa936e66e629e5d29b102bbfe49cc65e2dd5e9a718 - Sigstore transparency entry: 2165090069
- Sigstore integration time:
-
Permalink:
writerslogic/c2pa-ml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/writerslogic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12b663a78d7aa4fa94cde7c432839806bb08e43f -
Trigger Event:
workflow_dispatch
-
Statement type: