ContentAuthenticity 0.84.1
dotnet add package ContentAuthenticity --version 0.84.1
NuGet\Install-Package ContentAuthenticity -Version 0.84.1
<PackageReference Include="ContentAuthenticity" Version="0.84.1" />
<PackageVersion Include="ContentAuthenticity" Version="0.84.1" />
<PackageReference Include="ContentAuthenticity" />
paket add ContentAuthenticity --version 0.84.1
#r "nuget: ContentAuthenticity, 0.84.1"
#:package ContentAuthenticity@0.84.1
#addin nuget:?package=ContentAuthenticity&version=0.84.1
#tool nuget:?package=ContentAuthenticity&version=0.84.1
c2pa.net
.NET bindings for c2pa Rust library.
Description
This repository provides a .NET-friendly API surface over the native c2pa_c C ABI exposed by the upstream c2pa-rs project.
- Interop bindings are generated automatically: the build runs the
clangsharppinvokegenerator.NET tool (ClangSharp P/Invoke Generator) against thec2pa.hheader and emits platform-specific binding files underlib/Bindings/*. The dispatcher inlib/C2paBindings.csselects the correct platform/architecture implementation at runtime. - Typed models are generated from JSON Schema for safety: the
generator/project is a Roslyn incremental source generator that reads the C2PA JSON schemas (e.g., Builder/Reader/Settings) and emits strongly-typed C# models during compilation. This keeps the high-level API strongly typed (compile-time checks + IntelliSense) instead of relying on loosely-typed JSON strings.
Usage
The Reader and Builder classes have strongly-typed models generated from JSON Schema.
Reading and signing are now driven by an immutable Context, produced from a
ContextBuilder. The context owns shared configuration (settings, signer, HTTP
resolver, progress callback, etc.) and is then handed to a Reader or
Builder. This keeps per-operation classes thin and lets you reuse one
configured context across many reads/signs.
Read an asset and use the typed ManifestStore
using ContentAuthenticity;
var assetPath = "./my-image.jpg";
// Build a context. Settings/HTTP resolver are optional; defaults are fine for
// most reads.
using var contextBuilder = ContextBuilder.New();
// contextBuilder.SetHttpResolver(new HttpResolver()); // optional, for remote manifests
using var context = contextBuilder.Build();
// Attach the context to a Reader and feed it the asset.
using var reader = Reader.FromContext(context).WithFile(assetPath);
// Raw JSON (if you need it)
string json = reader.Json;
// Strongly-typed view of the manifest store
ManifestStore store = reader.Store;
Console.WriteLine($"Embedded: {reader.IsEmbedded}");
Console.WriteLine($"Active manifest: {store.ActiveManifest}");
if (store.Manifests.TryGetValue(store.ActiveManifest, out var manifest))
{
Console.WriteLine($"Title: {manifest.Title}");
Console.WriteLine($"Format: {manifest.Format}");
// Example: if the manifest has a thumbnail resource reference, fetch it.
if (manifest.Thumbnail is not null)
{
using var thumbOut = File.Create("./thumbnail.bin");
reader.ResourceToStream(new Uri(manifest.Thumbnail.Identifier), thumbOut);
}
}
// Round-trip back to JSON using the same schema-driven serializer options.
string roundTripped = store.ToJson();
Create a typed manifest definition and sign an asset
using ContentAuthenticity;
// Build a minimal typed manifest definition.
// The schema requires `NoEmbed` to be set.
var definition = new ManifestDefinition
{
NoEmbed = false,
Title = "my-image.jpg",
Format = "image/jpeg",
InstanceId = Builder.GenerateInstanceID(),
ClaimGeneratorInfo =
[
new ClaimGeneratorInfo { Name = "c2pa.net" }
],
Assertions =
[
new ActionAssertion(
[
new ActionV1("c2pa.edited"),
]),
],
};
// Provide an ISigner implementation (see `example/` projects for working signers,
// including local PEM/key signers and Azure Key Vault).
ISigner signer = /* new FileSigner(certPem, keyPem, tsaUrl) */ ...;
// Configure a context with the signer (and any other shared options).
using var contextBuilder = ContextBuilder.New();
contextBuilder.SetSigner(signer);
contextBuilder.SetHttpResolver(new HttpResolver()); // optional
using var context = contextBuilder.Build();
// Attach the context to a Builder and apply the typed manifest definition.
using var builder = Builder.FromContext(context).WithDefinition(definition);
// Optional: add extra resources that the manifest may reference (thumbnails, etc.)
builder.AddResource("thumbnail", "./thumbnail.jpg");
var input = "./my-image.jpg";
var output = "./my-image.signed.jpg";
// Sign using the signer configured on the context.
builder.Sign(input, output);
Prerequisites
- .NET 10.0 SDK or later
- Rust toolchain (for building the native c2pa-rs library)
- Git with submodule support
- ClangSharp
Development
1. Clone the Repository
git clone --recurse-submodules https://github.com/duggaraju/c2pa.net.git
cd c2pa.net
If you've already cloned the repository without submodules, initialize them:
git submodule update --init --recursive
2. Update Submodule to Specific Release Tag
The c2pa-rs submodule is automatically updated by a GitHub Actions workflow that monitors the upstream repository for new C FFI release tags matching the pattern c2pa-c-ffi-vx.x.x. When a new tag is detected, the workflow:
- Updates the submodule to point to the new tag
- Creates a pull request with the update details
- Includes the tag information and release notes link in the PR description
The workflow runs automatically every 6 hours, but can also be triggered manually:
# Go to Actions tab in GitHub UI
# Select "Update c2pa-rs Submodule" workflow
# Click "Run workflow"
# Optionally specify a specific tag (e.g., c2pa-c-ffi-v0.75.21)
Manual Update (if needed):
If you need to manually update the submodule to a specific release tag:
# Navigate to the submodule directory
cd c2pa-rs
# Fetch all tags from the remote repository
git fetch --tags
# List available c2pa-c-ffi tags
git tag -l 'c2pa-c-ffi-v*'
# Checkout to a specific release tag (replace with desired version)
git checkout c2pa-c-ffi-v0.75.21
# Return to the root directory
cd ..
# Commit the submodule update
git add c2pa-rs
git commit -m "Update c2pa-rs submodule to c2pa-c-ffi-v0.75.21"
3. Build the Project
Option 1: Using .NET CLI (Recommended)
# Build the entire solution
dotnet restore && dotnet tool restore
dotnet build
# Build
dotnet build
# or build in Release Mode.
dotnet build --configuration Release
Option 2: Using Visual Studio
- Open
c2pa.net.slnin Visual Studio - Select the desired configuration (Debug/Release) and platform (x64)
- Build → Build Solution (Ctrl+Shift+B)
4. Run Tests
# Run all tests
dotnet test
# Run tests with verbose output
dotnet test --verbosity normal
5. Run Example
# Navigate to the example CLI project
cd example/Cli
# Run the example
dotnet run
6. Package
Create a nuget package for publishing.
cd lib
dotnet pack
Project Structure
lib/- Main .NET bindings library (ContentAuthenticity.Bindings)tests/- Unit and integration testsexample/- Example CLI application demonstrating usagegenerator/- Code generator for creating .NET bindings from Rustc2pa-rs/- Git submodule containing the Rust c2pa library
Troubleshooting
Common Issues
Missing c2pa_c.dll: Ensure the Rust library is built first:
cd c2pa-rs cargo build --release -p c2pa-c-ffi --no-default-features --features "rust_native_crypto, file_io"Missing Rust Tooling: Ensure that you have cargo installed and right toolset present (e.g cross compiling for ARM64):
rustup target add aarch64-unknown-linux-gnuSubmodule not initialized: If you see build errors related to missing Rust code:
git submodule update --init --recursive
Contributing
- Fork the repository
- Create a feature branch
- Update the submodule to the appropriate c2pa-rs version if needed
- Make your changes
- Run tests to ensure everything works
- Submit a pull request
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.84.1 | 89 | 5/13/2026 |
| 0.84.0 | 110 | 5/12/2026 |
| 0.83.0 | 111 | 5/11/2026 |
| 0.82.1.1 | 197 | 5/5/2026 |
| 0.82.1 | 82 | 5/5/2026 |
| 0.82.0 | 116 | 5/3/2026 |
| 0.80.3.3 | 94 | 4/30/2026 |
| 0.80.3.2 | 87 | 4/30/2026 |
| 0.80.3.1 | 87 | 4/30/2026 |
| 0.80.3 | 99 | 4/29/2026 |
| 0.80.2 | 101 | 4/29/2026 |
| 0.80.1 | 94 | 4/28/2026 |
| 0.80.0 | 93 | 4/21/2026 |
| 0.79.5 | 92 | 4/16/2026 |
| 0.79.4 | 89 | 4/16/2026 |
| 0.79.3 | 144 | 4/10/2026 |
| 0.79.2 | 97 | 4/10/2026 |
| 0.79.0 | 99 | 4/8/2026 |
| 0.78.8 | 104 | 4/2/2026 |
| 0.78.7 | 104 | 3/30/2026 |