Skip to main content

Reference implementation for embedding C2PA manifests in text using Unicode variation selectors

Project description

Encypher Corporation Logo

c2pa-text

A Reference Implementation for C2PA Text Embedding

Preview License: MIT C2PA Compliant Python NPM Rust Go


⚠️ Preview Release: This library is in preview for C2PA working group review. The API is stable but not yet published to package registries. Install directly from GitHub (see below).

This library allows you to embed and extract C2PA manifests in unstructured text (UTF-8) using invisible Unicode Variation Selectors. It is compliant with the Manifests_Text.adoc specification.

Overview

C2PA manifests are typically embedded in binary files (JPEG, PNG, MP4). For plain text, this library implements a standard wrapper structure (C2PATextManifestWrapper) that encodes the binary C2PA Manifest Store (JUMBF) into invisible characters that persist through copy-paste operations.

This repository contains implementations for:

  • Python: For backend services and data processing.
  • TypeScript: For browser extensions, web apps, and Node.js.
  • Rust: For high-performance CLI tools and Wasm.
  • Go: For backend microservices.

Specification

The wrapper structure is defined as:

Container Type: C2PATextManifestWrapper
Magic: "C2PATXT\0" (0x4332504154585400)
Version: 1
Encoding: Unicode Variation Selectors (U+FE00..U+FE0F, U+E0100..U+E01EF)
Placement: End of text, prefixed with ZWNBSP (U+FEFF)

Maintenance & Support

This library is the official reference implementation maintained by Encypher (encypherai.com), authors of the C2PA Text Specification and active contributors to the C2PA standard.

While this library is free and permissively licensed (MIT), Encypher offers an Enterprise API for:

  • Managing cryptographic keys at scale (HSM)
  • Analytics and tracking for embedded content
  • Automated verification and revocation
  • Content production workflows

Learn more about Encypher Enterprise

Installation

Preview Installation (from GitHub)

During the preview period, install directly from GitHub:

Python

pip install "git+https://github.com/encypherai/c2pa-text.git#subdirectory=python"

TypeScript / JavaScript

npm install github:encypherai/c2pa-text#path:typescript

Rust

# In Cargo.toml
[dependencies]
c2pa-text = { git = "https://github.com/encypherai/c2pa-text", subdirectory = "rust" }

Go

go get github.com/encypherai/c2pa-text/go@v1.0.0-preview.1

After 1.0 Release (Package Registries)

Once published to registries:

# Python
pip install c2pa-text

# TypeScript
npm install c2pa-text

# Rust
cargo add c2pa-text

# Go
go get github.com/encypherai/c2pa-text/go

Generating Manifests

This library handles the embedding layer (text steganography). To generate the valid C2PA JUMBF manifest bytes (manifest_bytes), you have two options:

1. Use Encypher API (Recommended)

The Encypher Enterprise API automatically handles key management, signing, and manifest generation. It returns the fully signed JUMBF bytes or the final watermarked text directly.

2. Use C2PA Tooling

Since standard tools (like c2patool) do not natively support .txt files, you cannot embed directly using the CLI.

Instead, you must use the C2PA Rust or Python SDKs to generate a detached manifest (treating the text as a generic byte stream). You can then pass the resulting binary JUMBF data to this library for embedding.

Usage (Python)

from c2pa_text import embed_manifest, extract_manifest

# 1. You have a binary C2PA manifest (JUMBF)
manifest_bytes = b"..." 

# 2. Embed it into text
text = "Hello World"
watermarked_text = embed_manifest(text, manifest_bytes)

# 3. Extract it back
extracted_bytes, clean_text = extract_manifest(watermarked_text)

Validation (Python)

Validate manifest structure before embedding to catch issues early:

from c2pa_text import validate_manifest, embed_manifest

# Validate before embedding
result = validate_manifest(manifest_bytes)
if result.valid:
    watermarked = embed_manifest(text, manifest_bytes)
else:
    print(result)  # Shows detailed validation issues
    # Example output:
    # Validation failed:
    #   - [manifest.jumbf.truncated] JUMBF truncated: declared size 100, actual 8

Available validation functions:

  • validate_manifest(bytes) - Validate JUMBF structure before embedding
  • validate_jumbf_structure(bytes, strict=True) - Strict C2PA compliance checks
  • validate_wrapper_bytes(bytes) - Validate pre-encoded wrapper bytes

Validation codes follow the C2PA specification (e.g., manifest.text.corruptedWrapper).

Usage (TypeScript)

import { embedManifest, extractManifest, validateManifest } from 'c2pa-text';

// 1. You have a binary C2PA manifest (JUMBF) as a Uint8Array
const manifestBytes = new Uint8Array([/* ... */]);

// 2. Validate before embedding (optional but recommended)
const validation = validateManifest(manifestBytes);
if (!validation.valid) {
  console.error(validation.issues);
  throw new Error('Invalid manifest');
}

// 3. Embed it into text
const text = "Hello World";
const watermarkedText = embedManifest(text, manifestBytes);

// 4. Extract it back
const result = extractManifest(watermarkedText);
if (result) {
  console.log(result.manifest);   // Uint8Array
  console.log(result.cleanText);  // "Hello World"
}

Usage (Rust)

use c2pa_text::{embed_manifest, extract_manifest, validate_manifest};

// 1. Binary manifest
let manifest_bytes = b"...";

// 2. Validate before embedding (optional but recommended)
let validation = validate_manifest(manifest_bytes, true, false);
if !validation.valid {
    eprintln!("{}", validation);
    return Err("Invalid manifest");
}

// 3. Embed
let text = "Hello World";
let watermarked = embed_manifest(text, manifest_bytes);

// 4. Extract
if let Ok(result) = extract_manifest(&watermarked) {
    if let Some(bytes) = result.manifest {
        println!("Extracted {} bytes", bytes.len());
    }
}

Usage (Go)

import "github.com/encypherai/c2pa-text/go/c2pa_text"

// 1. Binary manifest
manifestBytes := []byte("...")

// 2. Validate before embedding (optional but recommended)
validation := c2pa_text.ValidateManifest(manifestBytes, true, false)
if !validation.Valid {
    fmt.Println(validation)
    return errors.New("invalid manifest")
}

// 3. Embed
text := "Hello World"
watermarked := c2pa_text.EmbedManifest(text, manifestBytes)

// 4. Extract
extractedBytes, cleanText, _, _, err := c2pa_text.ExtractManifest(watermarked)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

c2pa_text-1.0.2.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

c2pa_text-1.0.2-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file c2pa_text-1.0.2.tar.gz.

File metadata

  • Download URL: c2pa_text-1.0.2.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for c2pa_text-1.0.2.tar.gz
Algorithm Hash digest
SHA256 660494d7d41a284f698a15283c29f8b57b486d3b992c617ff58e71519b51336c
MD5 5ee301a7641dbd989976beeb9f745a04
BLAKE2b-256 17bf1d8c7a58cf7ecbfecbb42e6dd3e75af453f2fd72be63fc543c09935d4b4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for c2pa_text-1.0.2.tar.gz:

Publisher: c2pa-text.yaml on encypherai/c2pa-text

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file c2pa_text-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: c2pa_text-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for c2pa_text-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2f5d87d3228725c586a424c2b3c421101e63d06369cb5e57c27fb43511f3009c
MD5 aa0c69a2e7eeb6b8aa5a96e0720792b2
BLAKE2b-256 370e268fd5077450aaffb86668da1e32c77b0ed493ad516660098f108d057101

See more details on using hashes here.

Provenance

The following attestation bundles were made for c2pa_text-1.0.2-py3-none-any.whl:

Publisher: c2pa-text.yaml on encypherai/c2pa-text

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page