### Install Dependencies and Build SDK Source: https://github.com/contentauth/c2pa-node/blob/main/docs/project-contributions.md Install pnpm, then install project dependencies and build the SDK. Ensure the correct Node.js version is active. ```sh # Switch to the supported version of Node.js for building $ nvm use # Install pnpm $ npm install -g pnpm # Install dependencies $ pnpm install # Build the SDK $ pnpm run build ``` -------------------------------- ### Install c2pa-node using npm Source: https://github.com/contentauth/c2pa-node/blob/main/README.md Use this command to install the c2pa-node package in your client application via npm. ```sh $ npm install c2pa-node ``` -------------------------------- ### Install c2pa-node using pnpm Source: https://github.com/contentauth/c2pa-node/blob/main/README.md Use this command to install the c2pa-node package in your client application via pnpm. ```sh $ pnpm add c2pa-node ``` -------------------------------- ### Install c2pa-node using Yarn Source: https://github.com/contentauth/c2pa-node/blob/main/README.md Use this command to install the c2pa-node package in your client application via Yarn. ```sh $ yarn add c2pa-node ``` -------------------------------- ### Verifying C2PA_LIBRARY_PATH at Runtime Source: https://context7.com/contentauth/c2pa-node/llms.txt Provides a TypeScript example for checking if the C2PA_LIBRARY_PATH environment variable is set at runtime. If not set, a warning is logged, and the bundled binary will be used. ```typescript // The library reads this at startup: // const bindings = require(process.env.C2PA_LIBRARY_PATH ?? '../generated/c2pa.node'); // Verify the environment variable is set before starting if (!process.env.C2PA_LIBRARY_PATH) { console.warn('C2PA_LIBRARY_PATH not set; using bundled binary'); } ``` -------------------------------- ### Setting Custom Binary Path with C2PA_LIBRARY_PATH Source: https://context7.com/contentauth/c2pa-node/llms.txt Explains how to set the C2PA_LIBRARY_PATH environment variable to specify a custom path for the c2pa.node native module. This is necessary when targeting platforms without precompiled binaries and must be set during installation and at runtime. ```bash # Build the Rust native module on the target machine cd c2pa-node pnpm install pnpm build:rust # Copy the output binary to your application cp generated/c2pa.node /my-app/resources/c2pa.node # Set during install and runtime export C2PA_LIBRARY_PATH=resources/c2pa.node npm install c2pa-node node server.js ``` -------------------------------- ### Conventional Commit Example Source: https://github.com/contentauth/c2pa-node/blob/main/CONTRIBUTING.md Example of a pull request title and body following conventional commit specifications. Use this format for PRs targeting long-lived branches. ```text feat(api): Introduce a new API to validate 1.0 claims Repurpose existing v2 API for 0.8 compatibility (read: no validation) mode. ``` -------------------------------- ### RemoteSigner Interface Source: https://context7.com/contentauth/c2pa-node/llms.txt Implement the `RemoteSigner` interface to delegate cryptographic signing to an external web service or KMS. This involves providing `reserveSize()` to get the signature box size and `sign()` to sign the claim bytes. ```APIDOC ## RemoteSigner ### Description Interface for delegating the cryptographic signing step to a remote web service or KMS. The `reserveSize()` method must return the size of the signature box in bytes; `sign()` receives the claim bytes and must return the COSE_Sign1 signature bytes. This is the recommended approach for production deployments to keep private keys off the application server. ### Methods #### `reserveSize()` - **Description**: Returns the required size for the signature box in bytes. - **Returns**: `Promise` - The size of the signature box. #### `sign(input: SignInput)` - **Description**: Signs the provided claim bytes. - **Parameters**: - **input** (`SignInput`) - An object containing `reserveSize` and `toBeSigned` bytes. - **reserveSize** (`number`) - The reserved size for the signature box. - **toBeSigned** (`Buffer`) - The claim bytes to be signed. - **Returns**: `Promise` - The COSE_Sign1 signature bytes. ### Example Usage ```typescript import { createC2pa, ManifestBuilder } from 'c2pa-node'; import type { RemoteSigner, SignInput } from 'c2pa-node'; import fetch, { Headers } from 'node-fetch'; import { readFile } from 'node:fs/promises'; const remoteSigner: RemoteSigner = { type: 'remote', async reserveSize(): Promise { const res = await fetch('https://signing.example.com/box-size'); const { boxSize } = (await res.json()) as { boxSize: number }; return boxSize; // e.g. 10248 }, async sign({ reserveSize, toBeSigned }: SignInput): Promise { const res = await fetch( `https://signing.example.com/sign?boxSize=${reserveSize}`, { method: 'POST', headers: new Headers({ 'Content-Type': 'application/octet-stream' }), body: toBeSigned, }, ); if (!res.ok) throw new Error(`Signing service error: ${res.status}`); return res.buffer(); // returns CBOR-encoded COSE_Sign1 bytes }, }; const c2pa = createC2pa({ signer: remoteSigner }); const manifest = new ManifestBuilder({ claim_generator: 'my-app/1.0.0', format: 'image/jpeg' }); const buffer = await readFile('photo.jpg'); const { signedAsset } = await c2pa.sign({ asset: { buffer, mimeType: 'image/jpeg' }, manifest }); ``` ``` -------------------------------- ### Build SDK (if tests fail) Source: https://github.com/contentauth/c2pa-node/blob/main/docs/project-contributions.md Run this command if the test suite does not execute correctly, as a build might be required first. ```sh $ pnpm build ``` -------------------------------- ### createC2pa Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/README.md Creates an instance of the SDK that encompasses a set of global options. ```APIDOC ## createC2pa ### Description Creates an instance of the SDK that encompasses a set of global options. ### Method createC2pa ### Parameters #### Parameters - **options** (C2paOptions) - Optional - Global options for the C2PA instance ### Returns - **C2pa** - An instance of the C2PA SDK ``` -------------------------------- ### Run Test Suite Source: https://github.com/contentauth/c2pa-node/blob/main/docs/project-contributions.md Execute the project's test suite. If tests fail to run, a prior build may be necessary. ```sh $ pnpm test ``` -------------------------------- ### Asset Types: BufferAsset and FileAsset Source: https://context7.com/contentauth/c2pa-node/llms.txt Demonstrates the usage of BufferAsset and FileAsset for handling media content. BufferAsset is suitable for in-memory operations with JPEG/PNG, while FileAsset handles various formats without loading the entire file into memory. ```APIDOC ## Asset Types: `BufferAsset` and `FileAsset` All read, sign, and createIngredient operations accept either an in-memory `BufferAsset` or an on-disk `FileAsset`. Buffer-based signing is limited to `image/jpeg` and `image/png`. File-based operations work with all C2PA-supported formats (JPEG, PNG, MP4, etc.) and avoid loading the full asset into memory. ```typescript import type { BufferAsset, FileAsset, Asset } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; import { resolve } from 'node:path'; // In-memory buffer asset (JPEG/PNG only for signing) const bufferAsset: BufferAsset = { buffer: await readFile('photo.jpg'), mimeType: 'image/jpeg', // required }; // File path asset (all supported formats) const fileAsset: FileAsset = { path: resolve('video.mp4'), mimeType: 'video/mp4', // optional; inferred from extension if omitted }; // Union type accepted by all C2PA operations const asset: Asset = bufferAsset; // or fileAsset // Discriminate at runtime function describeAsset(a: Asset) { if ('buffer' in a) { console.log(`Buffer asset: ${a.mimeType}, ${a.buffer.byteLength} bytes`); } else { console.log(`File asset: ${a.path}${a.mimeType ? ` (${a.mimeType})` : ''}`); } } ``` ``` -------------------------------- ### Local Signing with Certificate and Key Source: https://github.com/contentauth/c2pa-node/blob/main/docs/usage.md Sign assets locally using your own signing certificate and private key. This is recommended for development but consider KMS or HSM for production security. Ensure file paths for the certificate and key are correct. ```typescript import { readFile } from 'node:fs/promises'; import { SigningAlgorithm } from 'c2pa-node'; // create a local signer async function createLocalSigner() { // make sure to update file paths to read from to match locations where you keep them const [certificate, privateKey] = await Promise.all([ readFile('.pem'), readFile('.pub'), ]); return { type: 'local', certificate, privateKey, algorithm: SigningAlgorithm.ES256, tsaUrl: 'http://timestamp.digicert.com', }; } // read the asset const buffer = await readFile('to-be-signed.jpg'); // asset mimetype must match the asset type being read const asset: Asset = { buffer, mimeType: 'image/jpeg' }; // create a signing function async function sign(asset, manifest) { const signer = await createLocalSigner(); const c2pa = createC2pa({ signer, }); const { signedAsset, signedManifest } = await c2pa.sign({ asset, manifest, }); } // build a manifest to use for signing const manifest = new ManifestBuilder( { claim_generator: 'my-app/1.0.0', format: 'image/jpeg', title: 'buffer_signer.jpg', assertions: [ { label: 'c2pa.actions', data: { actions: [ { action: 'c2pa.created', }, ], }, }, { label: 'com.custom.my-assertion', data: { description: 'My custom test assertion', version: '1.0.0', }, }, ], }, { vendor: 'cai' }, ); // sign await sign(asset, manifest); ``` -------------------------------- ### Using BufferAsset and FileAsset in c2pa-node Source: https://context7.com/contentauth/c2pa-node/llms.txt Demonstrates the creation and usage of BufferAsset and FileAsset for C2PA operations. Buffer-based signing is limited to JPEG and PNG, while file-based operations support all C2PA formats and avoid loading assets into memory. ```typescript import type { BufferAsset, FileAsset, Asset } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; import { resolve } from 'node:path'; // In-memory buffer asset (JPEG/PNG only for signing) const bufferAsset: BufferAsset = { buffer: await readFile('photo.jpg'), mimeType: 'image/jpeg', // required }; // File path asset (all supported formats) const fileAsset: FileAsset = { path: resolve('video.mp4'), mimeType: 'video/mp4', // optional; inferred from extension if omitted }; // Union type accepted by all C2PA operations const asset: Asset = bufferAsset; // or fileAsset // Discriminate at runtime function describeAsset(a: Asset) { if ('buffer' in a) { console.log(`Buffer asset: ${a.mimeType}, ${a.buffer.byteLength} bytes`); } else { console.log(`File asset: ${a.path}${a.mimeType ? ` (${a.mimeType})` : ''}`); } } ``` -------------------------------- ### Create Ingredient from Buffer and Sign Source: https://context7.com/contentauth/c2pa-node/llms.txt Create a storable ingredient record from a buffer, compute its hash, and optionally generate a thumbnail. This ingredient can then be attached to a manifest and used during the signing process. ```typescript import { createC2pa, ManifestBuilder, createTestSigner } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; import { resolve } from 'node:path'; const c2pa = createC2pa(); // ── Create an ingredient from a buffer ─────────────────────────────────────── const ingredientBuffer = await readFile('source-image.jpg'); const storableIngredient = await c2pa.createIngredient({ asset: { buffer: ingredientBuffer, mimeType: 'image/jpeg' }, title: 'source-image.jpg', // thumbnail: false // optionally disable thumbnail for this ingredient // hash: 'sha384-' // optionally supply a pre-computed hash }); const { ingredient, resources } = storableIngredient; console.log('Ingredient title:', ingredient.title); // 'source-image.jpg' console.log('Format:', ingredient.format); // 'image/jpeg' console.log('Hash:', ingredient.hash); // 'sha384-sVINtK1arjyLR617Ta85vNXO7X3uVpsFAKI/9Us4MWL7pDF51cTbfA55KH2BxJYh.jpeg' console.log('Active manifest:', ingredient.active_manifest); // 'contentauth:urn:uuid:699750af-...' (if source had a C2PA manifest) console.log('Resource keys:', Object.keys(resources)); // e.g. ['self#jumbf=...c2pa.thumbnail.claim.jpeg', 'manifest_data.c2pa'] // ── Create an ingredient from a file path ──────────────────────────────────── const ingredientFromFile = await c2pa.createIngredient({ asset: { path: resolve('source-image.jpg') }, title: 'source-image.jpg', }); // ── Attach ingredient to a manifest and sign ───────────────────────────────── const signer = await createTestSigner(); const signingC2pa = createC2pa({ signer }); const manifest = new ManifestBuilder({ claim_generator: 'compositor/1.0.0', format: 'image/jpeg', title: 'composite.jpg', assertions: [{ label: 'c2pa.actions', data: { actions: [{ action: 'c2pa.placed' }] } }], }); // Deduplicated by hash: calling addIngredient twice with the same hash is a no-op manifest.addIngredient(storableIngredient); const compositeBuffer = await readFile('composite.jpg'); const { signedAsset } = await signingC2pa.sign({ asset: { buffer: compositeBuffer, mimeType: 'image/jpeg' }, manifest, }); ``` -------------------------------- ### Sign Asset Buffer with Local Signer Source: https://github.com/contentauth/c2pa-node/blob/main/docs/usage.md Sign an asset using its buffer representation and a local manifest. This method is supported for 'image/jpeg' and 'image/png'. It requires creating a signer, initializing c2pa with the signer, and then calling the sign method. ```typescript import { readFile } from 'node:fs/promises'; import { createC2pa, createTestSigner } from 'c2pa-node'; // read an asset into a buffer const buffer = await readFile('to-be-signed.jpg'); const asset: Asset = { buffer, mimeType: 'image/jpeg' }; // build a manifest to use for signing const manifest = new ManifestBuilder( { claim_generator: 'my-app/1.0.0', format: 'image/jpeg', title: 'buffer_signer.jpg', assertions: [ { label: 'c2pa.actions', data: { actions: [ { action: 'c2pa.created', }, ], }, }, { label: 'com.custom.my-assertion', data: { description: 'My custom test assertion', version: '1.0.0', }, }, ], }, { vendor: 'cai' }, ); // create a signing function async function sign(asset, manifest) { const signer = await createTestSigner(); const c2pa = createC2pa({ signer, }); const { signedAsset, signedManifest } = await c2pa.sign({ asset, manifest, }); } // sign await sign(asset, manifest); ``` -------------------------------- ### Build custom Rust binary for c2pa-node Source: https://github.com/contentauth/c2pa-node/blob/main/README.md Commands to build a custom binary for the c2pa-node library on a target system or VM. This is required for platforms or architectures not supported by precompiled binaries. ```sh cd c2pa-node pnpm install pnpm build:rust ``` -------------------------------- ### createTestSigner(options?) Source: https://context7.com/contentauth/c2pa-node/llms.txt A convenience factory function to create a local test signer. It loads a certificate and private key from disk and configures the signer with ES256 and a DigiCert timestamp authority. This is intended for development and testing purposes. ```APIDOC ## createTestSigner(options?) ### Description Convenience factory that loads a certificate and private key from disk and returns a `LocalSigner` configured with ES256 and the DigiCert timestamp authority. Intended for development and testing; for production, use a KMS or HSM via a `RemoteSigner`. ### Parameters * `options` (object, optional) - Configuration options for the test signer. * `certificatePath` (string, optional) - Path to the custom certificate file. * `privateKeyPath` (string, optional) - Path to the custom private key file. ### Returns * `Promise` - A promise that resolves to a configured `LocalSigner` object. ### Example (default) ```typescript import { createTestSigner } from 'c2pa-node'; const defaultSigner = await createTestSigner(); ``` ### Example (custom paths) ```typescript import { createTestSigner } from 'c2pa-node'; const customSigner = await createTestSigner({ certificatePath: 'path/to/my-cert.pub', privateKeyPath: 'path/to/my-key.pem', }); ``` ``` -------------------------------- ### ManifestBuilder Constructor Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/classes/ManifestBuilder.md Initializes a new instance of the ManifestBuilder class. It takes a base manifest definition and optional options. ```APIDOC ## new ManifestBuilder(baseDefinition, options?) ### Description Initializes a new instance of the ManifestBuilder class. ### Parameters #### Parameters - **baseDefinition** (`BaseManifestDefinition`) - The base definition for the manifest. - **options?** (`ManifestBuilderOptions`) - Optional configuration options for the builder. ``` -------------------------------- ### Copy custom binary and set environment variable Source: https://github.com/contentauth/c2pa-node/blob/main/README.md Steps to copy the generated c2pa.node binary to your application's resources and set the C2PA_LIBRARY_PATH environment variable. This variable must be set during installation/addition and when running the application. ```sh cd /path/to/my/application mkdir resources cp /path/to/c2pa-node/generated/c2pa.node resources/c2pa.node ``` ```sh export C2PA_LIBRARY_PATH=resources/c2pa.node npm install c2pa-node npm start ``` -------------------------------- ### ManifestBuilder.asSendable Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/classes/ManifestBuilder.md Converts the current manifest builder state into a sendable format. ```APIDOC ## asSendable() ### Description Converts the current manifest builder state into a sendable format, including ingredients, manifest, and resource store. ### Returns - `Object` - An object containing the sendable ingredients, manifest, and resource store. ``` -------------------------------- ### ManifestStore Interface Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/modules/types.md Manages a collection of C2PA manifests. ```APIDOC ## Interface: ManifestStore ### Description An interface for managing and accessing a collection of C2PA manifests associated with a digital object. ### Fields - **manifests** (Array) - An array of manifests stored. - **addManifest** (function) - Adds a manifest to the store. - **getManifest** (function) - Retrieves a manifest by its ID or label. - **removeManifest** (function) - Removes a manifest from the store. ``` -------------------------------- ### Create Test Signer with Default and Custom Paths Source: https://context7.com/contentauth/c2pa-node/llms.txt Generate a local test signer using default bundled certificates or by specifying custom paths for your certificate and private key. ```typescript import { createTestSigner, SigningAlgorithm } from 'c2pa-node'; // Default: loads bundled test certificates from the package const defaultSigner = await createTestSigner(); // Custom certificate paths const customSigner = await createTestSigner({ certificatePath: 'path/to/my-cert.pub', privateKeyPath: 'path/to/my-key.pem', }); // Returns: { type: 'local', certificate: Buffer, privateKey: Buffer, algorithm: 'es256', tsaUrl: '...' } ``` -------------------------------- ### c2pa.createIngredient(props) Source: https://context7.com/contentauth/c2pa-node/llms.txt Creates a storable ingredient record by extracting provenance data, computing a content hash, and optionally generating a thumbnail. The returned record can be persisted and used later to add the ingredient to a derivative manifest. ```APIDOC ## c2pa.createIngredient(props) — Create a storable ingredient record ### Description Extracts provenance data, computes a content hash, and optionally generates a thumbnail for a source asset so it can be declared as an ingredient in a derivative manifest. The returned `StorableIngredient` (`{ ingredient, resources }`) is serializable and can be persisted, then passed to `manifest.addIngredient()` at signing time even if the original asset is no longer available. ### Parameters * `props` (object) - Properties for creating the ingredient. * `asset` (object) - The asset to create an ingredient from. * `buffer` (Buffer) - The asset content as a Buffer. * `mimeType` (string) - The MIME type of the asset. * `path` (string) - The file path to the asset. * `title` (string) - The title for the ingredient. * `thumbnail` (boolean, optional) - Whether to generate a thumbnail for the ingredient. Defaults to true. * `hash` (string, optional) - A pre-computed hash of the asset. ### Returns * `Promise` - A promise that resolves to a `StorableIngredient` object containing the ingredient data and associated resources. ### Example (from buffer) ```typescript import { createC2pa } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; const c2pa = createC2pa(); const ingredientBuffer = await readFile('source-image.jpg'); const storableIngredient = await c2pa.createIngredient({ asset: { buffer: ingredientBuffer, mimeType: 'image/jpeg' }, title: 'source-image.jpg' }); const { ingredient, resources } = storableIngredient; console.log('Ingredient title:', ingredient.title); console.log('Format:', ingredient.format); console.log('Hash:', ingredient.hash); ``` ### Example (from file path) ```typescript import { createC2pa } from 'c2pa-node'; import { resolve } from 'node:path'; const c2pa = createC2pa(); const storableIngredient = await c2pa.createIngredient({ asset: { path: resolve('source-image.jpg') }, title: 'source-image.jpg' }); ``` ``` -------------------------------- ### c2pa.sign(props) Source: https://context7.com/contentauth/c2pa-node/llms.txt Signs a manifest and embeds it into a media asset. Works with both in-memory buffers (JPEG and PNG only) and file paths (all supported C2PA formats including MP4). Returns `signedAsset` (the output asset of the same type as input) and optionally `signedManifest` (the raw manifest bytes). A per-call `signer` can override the global signer. ```APIDOC ## `c2pa.sign(props)` — Sign an asset and embed a C2PA manifest Signs a manifest and embeds it into a media asset. Works with both in-memory buffers (JPEG and PNG only) and file paths (all supported C2PA formats including MP4). Returns `signedAsset` (the output asset of the same type as input) and optionally `signedManifest` (the raw manifest bytes). A per-call `signer` can override the global signer. ### Example 1: Sign a JPEG from a buffer ```typescript import { createC2pa, createTestSigner, ManifestBuilder } from 'c2pa-node'; import { readFile, writeFile } from 'node:fs/promises'; import { resolve } from 'node:path'; const signer = await createTestSigner({ certificatePath: 'certs/es256.pub', privateKeyPath: 'certs/es256.pem', }); const c2pa = createC2pa({ signer }); const buffer = await readFile('original.jpg'); const asset = { buffer, mimeType: 'image/jpeg' }; const manifest = new ManifestBuilder({ claim_generator: 'my-app/1.0.0', format: 'image/jpeg', title: 'signed.jpg', assertions: [{ label: 'c2pa.actions', data: { actions: [{ action: 'c2pa.created' }] } }], }); const { signedAsset, signedManifest } = await c2pa.sign({ asset, manifest }); // signedAsset: { buffer: Buffer, mimeType: 'image/jpeg' } await writeFile('signed.jpg', signedAsset.buffer); console.log('Manifest bytes:', signedManifest?.byteLength); ``` ### Example 2: Sign an MP4 file from disk ```typescript const videoManifest = new ManifestBuilder({ claim_generator: 'my-app/1.0.0', format: 'video/mp4', title: 'signed-video.mp4', assertions: [{ label: 'c2pa.actions', data: { actions: [{ action: 'c2pa.created' }] } }], }); const { signedAsset: signedVideo } = await c2pa.sign({ asset: { path: resolve('original.mp4') }, manifest: videoManifest, thumbnail: false, // disable thumbnail for video options: { outputPath: resolve('signed.mp4') }, }); // signedVideo: { path: '/abs/path/signed.mp4', mimeType: undefined } ``` ### Example 3: Append a claim to an already-signed JPEG ```typescript const existingBuffer = await readFile('already-signed.jpg'); const updateManifest = new ManifestBuilder({ claim_generator: 'editor-app/3.0.0', format: 'image/jpeg', title: 'updated.jpg', assertions: [ { label: 'c2pa.actions', data: { actions: [{ action: 'c2pa.color_adjustments', parameters: { name: 'curves' } }] } }, ], }); const { signedAsset: updatedAsset } = await c2pa.sign({ asset: { buffer: existingBuffer, mimeType: 'image/jpeg' }, manifest: updateManifest, signer: await createTestSigner(), // override global signer for this call }); ``` ``` -------------------------------- ### Add Ingredient to Manifest Source: https://github.com/contentauth/c2pa-node/blob/main/docs/usage.md Create and add an ingredient to a manifest. Ingredients can be loaded from a file buffer or a file path. The ingredient is then added to the manifest using `manifest.addIngredient()`. ```typescript // Create the ingredient asset from a buffer const ingredientAssetFromBuffer = { buffer: await readFile('my-ingredient.jpg'), mimeType: 'image/jpeg', }; // Or load from a file const ingredientAssetFromFile = { path: resolve('my-ingredient.jpg'), }; // Create the ingredient const ingredient = await c2pa.createIngredient({ asset: ingredientAssetFromBuffer, title: 'ingredient.jpg', }); // Add it to the manifest manifest.addIngredient(ingredient); ``` -------------------------------- ### Create c2pa-node SDK Instance Source: https://context7.com/contentauth/c2pa-node/llms.txt Factory function to create a C2pa object. Accepts optional global defaults for signer and thumbnail behavior. Use this to initialize the SDK for read, sign, or create ingredient operations. ```typescript import { createC2pa, createTestSigner, SigningAlgorithm } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; // Minimal instance (read-only, no signer needed) const c2paReadOnly = createC2pa(); // Instance with a local signer and custom thumbnail settings const [certificate, privateKey] = await Promise.all([ readFile('./certs/es256.pub'), readFile('./certs/es256.pem'), ]); const c2pa = createC2pa({ signer: { type: 'local', certificate, privateKey, algorithm: SigningAlgorithm.ES256, tsaUrl: 'http://timestamp.digicert.com', }, thumbnail: { maxSize: 512, // max width/height in px (default: 1024) quality: 0.75, // 0–1 or 0–100 (default: 0.8) }, }); // Instance with thumbnail generation disabled const c2paNoThumb = createC2pa({ thumbnail: false }); ``` -------------------------------- ### SignOptions Properties Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/SignOptions.md The SignOptions interface allows customization of the signing process. You can specify whether to embed manifest data, define an output path for the signed file, or provide a URL for a remote manifest. ```APIDOC ## Interface: SignOptions ### Properties - **embed** (Optional `boolean`): Determines if the manifest data should be embedded within the signed output. - **outputPath** (Optional `string`): Specifies the file path where the signed output should be saved. - **remoteManifestUrl** (Optional ``null` | `string`): Provides a URL to a remote manifest that can be referenced. ``` -------------------------------- ### ThumbnailOptions Interface Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/ThumbnailOptions.md Defines the options available for generating thumbnails. ```APIDOC ## Interface: ThumbnailOptions ### Properties - **maxSize**: `number` - The maximum dimension (width or height) of the thumbnail in pixels. - **quality**: `number` - The quality of the generated thumbnail, a value between 0 and 100. ``` -------------------------------- ### ResourceStore Interface Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/modules/types.md Manages a collection of resources referenced within C2PA manifests. ```APIDOC ## Interface: ResourceStore ### Description Manages a collection of resources that are referenced within C2PA manifests. ### Fields - **resources** (Array) - An array of resource references. - **addResource** (function) - Adds a resource reference to the store. - **getResource** (function) - Retrieves a resource reference by its URI. - **removeResource** (function) - Removes a resource reference from the store. ``` -------------------------------- ### Sign File Using File Path Source: https://github.com/contentauth/c2pa-node/blob/main/docs/usage.md Sign an asset by providing its file path. This method is suitable for large files or unsupported formats for in-memory signing. Ensure the asset path is correctly resolved. ```typescript import { resolve } from 'node:path'; import { createC2pa, createTestSigner } from 'c2pa-node'; // get the asset full path const asset = { path: resolve('to-be-signed.jpg'), }; // define a location where to place the signed asset const outputPath = resolve('signed.jpg'); // create a signing function async function sign(asset, manifest) { const signer = await createTestSigner(); const c2pa = createC2pa({ signer, }); const { signedAsset, signedManifest } = await c2pa.sign({ manifest, asset, options: { outputPath, }, }); } // build a manifest to use for signing const manifest = new ManifestBuilder( { claim_generator: 'my-app/1.0.0', format: 'image/jpeg', title: 'buffer_signer.jpg', assertions: [ { label: 'c2pa.actions', data: { actions: [ { action: 'c2pa.created', }, ], }, }, { label: 'com.custom.my-assertion', data: { description: 'My custom test assertion', version: '1.0.0', }, }, ], }, { vendor: 'cai' }, ); // sign await sign(asset, manifest); ``` -------------------------------- ### ManifestStore Properties Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/types.ManifestStore.md This snippet details the properties available on the ManifestStore interface. ```APIDOC ## Interface: ManifestStore A Container for a set of Manifests and a ValidationStatus list ### Properties - **active_manifest** (`string` | `null`): Optional. A label for the active (most recent) manifest in the store. - **manifests** (`Object`): A HashMap of Manifests. The index signature is `[key: string]: Manifest`. - **validation_status** (`ValidationStatus`[] | `null`): Optional. ValidationStatus generated when loading the ManifestStore from an asset. ``` -------------------------------- ### Supported Signing Algorithms with c2pa-node Source: https://context7.com/contentauth/c2pa-node/llms.txt Illustrates the use of the SigningAlgorithm enum to specify cryptographic algorithms for local signing. Available algorithms include ECDSA variants (ES256, ES384, ES512), RSASSA-PSS variants (PS256, PS384, PS512), and Ed25519. ```typescript import { SigningAlgorithm } from 'c2pa-node'; // Available values: SigningAlgorithm.ES256 // 'es256' — ECDSA with SHA-256 SigningAlgorithm.ES384 // 'es384' — ECDSA with SHA-384 SigningAlgorithm.ES512 // 'es512' — ECDSA with SHA-512 SigningAlgorithm.PS256 // 'ps256' — RSASSA-PSS / SHA-256 SigningAlgorithm.PS384 // 'ps384' — RSASSA-PSS / SHA-384 SigningAlgorithm.PS512 // 'ps512' — RSASSA-PSS / SHA-512 SigningAlgorithm.Ed25519 // 'ed25519' — Edwards-Curve DSA // Usage in a LocalSigner const signer = { type: 'local' as const, certificate: Buffer.from('...'), privateKey: Buffer.from('...'), algorithm: SigningAlgorithm.Ed25519, }; ``` -------------------------------- ### c2pa.read(asset) Source: https://context7.com/contentauth/c2pa-node/llms.txt Reads and resolves all C2PA manifests embedded in or remotely referenced by a media asset. Returns a `ResolvedManifestStore` with the active manifest, all manifests keyed by label, thumbnails decoded to `Buffer`, signature timestamps parsed to `Date`, and a validation status array. Returns `null` if no provenance is present in the asset. ```APIDOC ## c2pa.read(asset) ### Description Reads and resolves all C2PA manifests embedded in or remotely referenced by a media asset. Returns a `ResolvedManifestStore` with the active manifest, all manifests keyed by label, thumbnails decoded to `Buffer`, signature timestamps parsed to `Date`, and a validation status array. Returns `null` if no provenance is present in the asset. ### Parameters #### Request Body - **asset** (object) - Required - The asset to read provenance from. Can be a buffer or a file path. - **buffer** (Buffer) - Required if `path` is not provided - The media asset as a Buffer. - **path** (string) - Required if `buffer` is not provided - The file path to the media asset. - **mimeType** (string) - Required - The MIME type of the asset (e.g., 'image/jpeg', 'video/mp4'). ### Response #### Success Response (200) - **ResolvedManifestStore** (object) - Contains C2PA manifest data. - **active_manifest** (Manifest) - The primary manifest for the asset. - **manifests** (object) - All manifests keyed by label. - **validation_status** (array) - An array of validation status objects. - **thumbnail** (object) - Decoded thumbnail data. - **format** (string) - MIME type of the thumbnail. - **data** (Buffer) - Thumbnail image data. - **signature_info** (object) - Information about the signature. - **issuer** (string) - The issuer of the signature certificate. - **timeObject** (Date) - The timestamp of the signature. - **assertions** (array) - An array of assertion objects. - **label** (string) - The label of the assertion. - **data** (object) - The assertion data. ### Request Example ```typescript import { createC2pa } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; import { resolve } from 'node:path'; const c2pa = createC2pa(); // --- Read from a buffer --- const buffer = await readFile('photo.jpg'); const resultFromBuffer = await c2pa.read({ buffer, mimeType: 'image/jpeg' }); if (resultFromBuffer) { const { active_manifest, manifests, validation_status } = resultFromBuffer; console.log('Active manifest label:', active_manifest?.label); // e.g. 'contentauth:urn:uuid:699750af-e07b-4c45-9d24-a131442111b8' console.log('Claim generator:', active_manifest?.claim_generator); // e.g. 'Adobe_Photoshop/24.5.0 c2pa-rs/0.13.0' console.log('Title:', active_manifest?.title); // 'photo.jpg' console.log('Format:', active_manifest?.format); // 'image/jpeg' // Signature info const sig = active_manifest?.signature_info; console.log('Issuer:', sig?.issuer); // 'C2PA Test Signing Cert' console.log('Signed at:', sig?.timeObject); // Date object // Thumbnail as a Buffer const thumb = active_manifest?.thumbnail; if (thumb) { console.log('Thumbnail MIME:', thumb.format); // 'image/jpeg' console.log('Thumbnail size (bytes):', thumb.data?.byteLength); } // Assertions const actions = active_manifest?.assertions?.find(a => a.label === 'c2pa.actions'); console.log('Actions:', actions?.data.actions); // Validation (empty array = valid) if (validation_status.length > 0) { validation_status.forEach(s => console.warn('Validation issue:', s.code, s.explanation)); } // All manifests in the store console.log('All manifest labels:', Object.keys(manifests)); } else { console.log('No C2PA provenance found in this asset.'); } // --- Read from a file path (avoids loading full asset into memory) --- const resultFromFile = await c2pa.read({ path: resolve('video.mp4'), mimeType: 'video/mp4' }); ``` ``` -------------------------------- ### Sign a JPEG from a buffer with c2pa.sign Source: https://context7.com/contentauth/c2pa-node/llms.txt Signs a manifest and embeds it into a JPEG asset provided as a buffer. Requires a signer configuration and the asset buffer with its MIME type. Returns the signed asset buffer and optionally the raw manifest bytes. ```typescript import { createC2pa, createTestSigner, ManifestBuilder } from 'c2pa-node'; import { readFile, writeFile } from 'node:fs/promises'; import { resolve } from 'node:path'; // ── Example 1: Sign a JPEG from a buffer ────────────────────────────────────── const signer = await createTestSigner({ certificatePath: 'certs/es256.pub', privateKeyPath: 'certs/es256.pem', }); const c2pa = createC2pa({ signer }); const buffer = await readFile('original.jpg'); const asset = { buffer, mimeType: 'image/jpeg' }; const manifest = new ManifestBuilder({ claim_generator: 'my-app/1.0.0', format: 'image/jpeg', title: 'signed.jpg', assertions: [{ label: 'c2pa.actions', data: { actions: [{ action: 'c2pa.created' }] } }], }); const { signedAsset, signedManifest } = await c2pa.sign({ asset, manifest }); // signedAsset: { buffer: Buffer, mimeType: 'image/jpeg' } await writeFile('signed.jpg', signedAsset.buffer); console.log('Manifest bytes:', signedManifest?.byteLength); ``` -------------------------------- ### ManifestBuilder.createLabel Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/classes/ManifestBuilder.md A static method to create a label, optionally with vendor information. ```APIDOC ## createLabel(vendor?) ### Description Creates a label string, optionally including vendor information. ### Parameters #### Parameters - **vendor?** (`string`) - Optional vendor name to include in the label. ### Returns - `string` - The generated label. ``` -------------------------------- ### ResourceStore Properties Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/types.ResourceStore.md This interface defines properties for storing binary resources, including an optional base path and a map of resource identifiers to their data. ```APIDOC ## Interface: ResourceStore Resource store to contain binary objects referenced from JSON serializable structures ### Properties - **base_path** (`Optional` `null` | `string`): An optional path to the base directory for resources. - **resources** (`Object`): An object where keys are strings representing resource identifiers and values are arrays of numbers (likely indices or references to the binary data). ``` -------------------------------- ### Manifest Properties Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/types.Manifest.md This section details the properties available within the Manifest interface. Each property is optional and has a specific type and description. ```APIDOC ## Manifest Properties ### assertions - **Type**: `ManifestAssertion[]` - **Description**: A list of assertions. ### claim_generator - **Type**: `string` - **Description**: A User Agent formatted string identifying the software/hardware/system that produced this claim. Spaces are not allowed in names, versions can be specified with product/1.0 syntax. ### claim_generator_hints - **Type**: `null` | `{ [key: string]: any }` - **Description**: Hints for the claim generator. ### credentials - **Type**: `null` | `any[]` - **Description**: A list of verified credentials. ### format - **Type**: `string` - **Description**: The format of the source file as a MIME type. ### ingredients - **Type**: `Ingredient[]` - **Description**: A list of ingredients. ### instance_id - **Type**: `string` - **Description**: Instance ID from `xmpMM:InstanceID` in XMP metadata. ### label - **Type**: `null` | `string` - **Description**: Label for the manifest. ### redactions - **Type**: `null` | `string[]` - **Description**: A list of redactions - URIs to a redacted assertions. ### resources - **Type**: `ResourceStore` - **Description**: Container for binary assets (like thumbnails). ### signature_info - **Type**: `null` | `SignatureInfo` - **Description**: Signature data (only used for reporting). ### thumbnail - **Type**: `null` | `ResourceRef` - **Description**: Thumbnail reference. ### title - **Type**: `null` | `string` - **Description**: A human-readable title, generally the source filename. ### vendor - **Type**: `null` | `string` - **Description**: Optional prefix added to the generated Manifest Label. This is typically the Internet domain name for the vendor (i.e. `adobe`). ``` -------------------------------- ### createC2pa(options?) Source: https://context7.com/contentauth/c2pa-node/llms.txt Factory function that returns a C2pa object combining read, sign, signClaimBytes, and createIngredient. Accepts optional global defaults for the signer and thumbnail behavior. ```APIDOC ## createC2pa(options?) ### Description Factory function that returns a `C2pa` object combining `read`, `sign`, `signClaimBytes`, and `createIngredient`. Accepts optional global defaults for the signer and thumbnail behavior. All subsequent operations on the returned object use these defaults unless overridden per-call. ### Usage ```typescript import { createC2pa, createTestSigner, SigningAlgorithm } from 'c2pa-node'; import { readFile } from 'node:fs/promises'; // Minimal instance (read-only, no signer needed) const c2paReadOnly = createC2pa(); // Instance with a local signer and custom thumbnail settings const [certificate, privateKey] = await Promise.all([ readFile('./certs/es256.pub'), readFile('./certs/es256.pem'), ]); const c2pa = createC2pa({ signer: { type: 'local', certificate, privateKey, algorithm: SigningAlgorithm.ES256, tsaUrl: 'http://timestamp.digicert.com', }, thumbnail: { maxSize: 512, // max width/height in px (default: 1024) quality: 0.75, // 0–1 or 0–100 (default: 0.8) }, }); // Instance with thumbnail generation disabled const c2paNoThumb = createC2pa({ thumbnail: false }); ``` ``` -------------------------------- ### Create Manifest with Assertions Source: https://github.com/contentauth/c2pa-node/blob/main/docs/usage.md Create a new C2PA manifest using the ManifestBuilder. This allows you to define the format, title, and custom assertions, including actions and custom data. ```typescript import { ManifestBuilder } from 'c2pa-node'; const manifest = new ManifestBuilder({ claim_generator: 'my-app/1.0.0', format: 'image/jpeg', title: 'node_test_local_signer.jpg', assertions: [ { label: 'c2pa.actions', data: { actions: [ { action: 'c2pa.created', }, ], }, }, { label: 'com.custom.my-assertion', data: { description: 'My custom test assertion', version: '1.0.0', }, }, ], }); ``` -------------------------------- ### FileAsset Properties Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/FileAsset.md This snippet details the properties available on the FileAsset interface. ```APIDOC ## Interface: FileAsset ### Properties - **mimeType** (string, Optional): The MIME type of the file. - **path** (string, Required): The file path. ``` -------------------------------- ### ManifestBuilder.addIngredient Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/classes/ManifestBuilder.md Adds an ingredient to the manifest. This method is chainable. ```APIDOC ## addIngredient(input) ### Description Adds an ingredient to the manifest. ### Parameters #### Parameters - **input** (`StorableIngredient`) - The ingredient to add. ### Returns - [`ManifestBuilder`](ManifestBuilder.md) - The ManifestBuilder instance for chaining. ``` -------------------------------- ### ResolvedManifestStore Properties Source: https://github.com/contentauth/c2pa-node/blob/main/api-docs/interfaces/ResolvedManifestStore.md This snippet details the properties available on the ResolvedManifestStore interface. ```APIDOC ## Interface: ResolvedManifestStore ### Properties - **active_manifest**: `null` | `ResolvedManifest` - Description: The currently active manifest. - Defined in: bindings.ts:59 - **manifests**: `Record` - Description: A record mapping manifest IDs to ResolvedManifest objects. - Defined in: bindings.ts:60 ```