CAI Node.js 图书馆
@contentauth/c2pa-node 是一个节点Js 库 c2pa - js (英语) 可:
- 以所支持的格式读取并验证媒体文件中的C2PA数据.
- 在支持格式的媒体文件中添加签名的列表 .
先决条件
要使用 C2pa-node 库,您需要Node.js 22 或 later. 使用补丁放出:v22.23.4+于v22上;v24.22.1+于v24上;或v26.12.1+于v26上. 二进制安装器和 JavaScript 获取路径独立于 Rust SDK 使用节点的 TLS 堆栈; 见 TLS 信托基金。如果需要在机器上管理多个版本的节点,请使用诸如 数字。 。 。 .
正常安装软件包时不需要 Rust : 预编译二进制 自动下载。 关于源建筑,见 为 C2pa- 节点作出贡献。 。 。 .
安装
安装用于应用程序
使用 npm :
npm install @contentauth/c2pa-node
使用 Yarn :
yarn add @contentauth/c2pa-node
使用 pnpm :
pnpm add @contentauth/c2pa-node
此命令将下载以下系统的预编译二进制 :
- Linux x86 64 (英语)
- Linux arch64 (亚美尼亚语)
- macOS arch64 (阿普尔硅)
- macOS x86 64 (英特尔麦克)
- 视窗 x86
- 窗口ARM
文档
这个 节点.js API 文档 实值
生成方式 类型文件 发表宣言
版本 @contentauth/c2pa-node。使用版本选择器来切换发布.
这个 多包装文件 遗 物
可在现有的根 URL 中找到.
关于文件构建和版本列表维护,见 构建 API 文档。 。 。 .
构成部分
阅读器
这个 Reader 类用于从媒体文件中读取和验证 C2PA 运单。 它可以解析嵌入式运算表或获取远程运算表. 参见 (原始内容存档于2018-03-21) (英语). Rust SDK 用于设置列表及其效果.
import { Reader, Context } from '@contentauth/c2pa-node';
// Read from an asset file
const reader = await Reader.fromAsset(inputAsset);
// Read with a Context — the recommended way to configure settings
// (see "Using a Context" under "Settings and configuration" below)
const context = new Context({
verify: {
verifyAfterReading: false,
verifyTrust: true
}
});
const reader = await Reader.fromAsset(inputAsset, context);
// Read from manifest data and asset
const reader = await Reader.fromManifestDataAndAsset(manifestData, asset);
// Get the manifest store as JSON
const manifestStore = reader.json();
// Get the active manifest
const activeManifest = reader.getActive();
// Check if manifest is embedded
const isEmbedded = reader.isEmbedded();
// Get remote URL if applicable
const remoteUrl = reader.remoteUrl();
[注]
Reader.fromAsset编号 :Reader.fromManifestDataAndAsset并接受替换 a 的原始设置对象Context(例如:.Reader.fromAsset(inputAsset, { verify: { verify_trust: true } })但这是堕落的 个人设置( 折旧)。 。 。 .
Reader.fromAsset 财务报告和审定财务报表 Reader.fromManifestDataAndAsset 拒绝大于10GB的资产,丢弃 AssetTooLargeError (从 @contentauth/c2pa-node) (中文(简体) ). 请注意: SourceBufferAsset,这只有在缓冲器已经完全分配到内存后才会拒绝。 通过 a FileAsset 而对于大型或不信任的资产,如此过大的文件在被读入内存之前被否决.
[尖叫声]
mimeType在输入资产上为Reader.fromAsset编号 :Reader.fromManifestDataAndAsset。如果它被省略,并且无法从文件扩展名中推断出来,则本地库会回归到检测资产字节中的格式. 这不是一个需要依靠的特征. 总是供应mimeType当它被称作"以字节为基础的检测"时,因为比起直接的找寻速度要慢并可能不可靠,这在后期可能会被表出为更混乱的错误. 只有在呼叫者无法确定资产格式时才省略.Builder方法总是需要mimeType将予提供.
构建器
这个 Builder class 是创建和签署 C2PA 运算表的主要组件。 它提供了在表单中添加断言、资源和成份的方法,并处理签字过程。 使用 Signer 同学们在名单上签名 参见 (原始内容存档于2018-03-21) (英语). Rust SDK 用于设置列表及其效果.
import { Builder, Context } from '@contentauth/c2pa-node';
// Create a new builder
const builder = await Builder.newAsync();
// Create with a Context — the recommended way to configure settings
// (see "Using a Context" under "Settings and configuration" below)
const context = new Context({
builder: {
generateC2paArchive: true
}
});
const builder = await Builder.newAsync(context);
// Or create from an existing manifest definition
const builder = await Builder.withJsonAsync(manifestDefinition);
// Or create with both a manifest definition and a Context
const builder = await Builder.withJsonAsync(manifestDefinition, context);
// Add assertions to the manifest
builder.addAssertion('c2pa.actions', actionsAssertion);
// Add resources
await builder.addResource('resource://example', resourceAsset);
// Sign the manifest
const manifest = builder.sign(signer, inputAsset, outputAsset);
[注]
Builder.new编号 :Builder.withJson(同步,取一个原始设置对象取而代之)Context)仍在工作,但已贬值——见 个人设置( 折旧)。 。 。 .
设置构建者意图
建造者意图说明在资产上进行的作业类型。 这影响到清单的结构以及自动增加的断言。 使用其中一项意图:
create:表示资产是新的数字创建,aDigitalSourceType需要时间。 清单中不得有母成分。 A 类c2pa.created如果不提供,将添加动作.edit:表示该资产是对已存在母资产的编辑. 清单必须有母成分。 如果不另行提供,则从源流中生成母成分。 A 类c2pa.opened动作将被绑定在母成分上.update: 限制版本edit非编辑改动。 作为父母,一定只有一个成分。 无法更改父方的散列内容 。 对可以作出的改变的类型还有额外的限制.
const builder = await Builder.newAsync();
builder.setIntent({
create: 'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia',
});
builder.setIntent('edit');
builder.setIntent('update');
这个 create 意图接受一个 DigitalSourceType 说明资产的来源。 共同价值包括:
'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia'- AI生成的内容'http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture'- 数码相机捕获'http://cv.iptc.org/newscodes/digitalsourcetype/composite'- 多种来源的综合
数字源类型完整列表,参见 C2PA 规格 财务报告和审定财务报表 IPTC 数字源类型词汇。 。 。 .
关于建造者意图的更详细情况,见 c2pa-rs 构建器文档。 。 。 .
从资产中添加成分
当您有机会获得该成分资产时,请使用 addIngredient 包括元数据和资产数据的资产:
import * as fs from "node:fs/promises";
// Load the ingredient asset
const ingredientBuffer = await fs.readFile('path/to/source-image.jpg');
// Create a builder
const builder = await Builder.newAsync();
// Add the ingredient with its asset
await builder.addIngredient(
JSON.stringify({
title: 'source-image.jpg',
format: 'image/jpeg',
instance_id: 'ingredient-123',
relationship: 'parentOf',
}),
{
buffer: ingredientBuffer,
mimeType: 'image/jpeg',
}
);
const definition = builder.getManifestDefinition();
console.log(definition.ingredients); // Contains the ingredient with embedded data
添加多种成分
您可以在文档复合出处链中添加多个成分 :
const builder = await Builder.newAsync();
// Load ingredient assets
const background = await fs.promises.readFile('background.jpg');
const overlay = await fs.promises.readFile('overlay.png');
// Add first ingredient
await builder.addIngredient(
JSON.stringify({
title: 'background.jpg',
format: 'image/jpeg',
instance_id: 'background-001',
relationship: 'componentOf',
}),
{
buffer: background,
mimeType: 'image/jpeg',
}
);
// Add second ingredient
await builder.addIngredient(
JSON.stringify({
title: 'overlay.png',
format: 'image/png',
instance_id: 'overlay-002',
relationship: 'componentOf',
}),
{
buffer: overlay,
mimeType: 'image/png',
}
);
const definition = builder.getManifestDefinition();
console.log(definition.ingredients.length); // 2
从读者中添加成分
您也可以直接从 a 添加成分 Reader 对象,自动包括 C2PA 数据 :
// Read an existing C2PA asset
const sourceReader = await Reader.fromAsset({
path: 'source-image.jpg',
});
// Create a builder
const builder = await Builder.newAsync();
// Add ingredient from reader
const ingredient = builder.addIngredientFromReader(sourceReader);
console.log(ingredient.title); // Contains ingredient metadata
从归档文件添加组件
您可以从 .c2pa 存档文件 。 档案为二进制文件,包含有成分及其相关资源(hum,表列数据等)的表列存储. 要与他们合作,阅读档案 Reader 使用 application/c2pa MIME 类型,然后取出成分并将其二进制资源转移到新的 Builder。 。 。 .
有两种档案共享相同的二进制格式:
- 构建文件 (工作仓库档案): 序列式快照a
Builder,由builder.toArchive()。它们可以包含多种成分. - 材料档案: 含有来源资产中的一种成分。 它们携带出处历史,用于在其他清单中再利用.
读取归档并添加其成分
import { Reader, Builder, Context } from '@contentauth/c2pa-node';
import * as fs from 'node:fs/promises';
// Read the archive using the application/c2pa MIME type
const archiveBuffer = await fs.readFile('ingredients.c2pa');
const reader = await Reader.fromAsset(
{ buffer: archiveBuffer, mimeType: 'application/c2pa' },
new Context({ verify: { verifyAfterReading: false } })
);
// Get the ingredients from the active manifest
const activeManifest = reader.getActive();
const ingredients = activeManifest.ingredients;
// Create a new builder with the ingredients from the archive
const builder = await Builder.withJsonAsync({
claim_generator_info: [{ name: 'my-app', version: '1.0.0' }],
ingredients: ingredients,
});
// Transfer binary resources (thumbnails, manifest_data) for each ingredient
for (const ingredient of ingredients) {
if (ingredient.thumbnail) {
const resource = await reader.resourceToAsset(ingredient.thumbnail.identifier, { buffer: null });
await builder.addResource(ingredient.thumbnail.identifier, {
buffer: resource.buffer,
mimeType: ingredient.thumbnail.format,
});
}
if (ingredient.manifest_data) {
const resource = await reader.resourceToAsset(ingredient.manifest_data.identifier, { buffer: null });
await builder.addResource(ingredient.manifest_data.identifier, {
buffer: resource.buffer,
mimeType: 'application/c2pa',
});
}
}
// Sign the manifest
const signer = LocalSigner.newSigner(cert, key, 'es256');
builder.sign(signer, inputAsset, outputAsset);
从归档中选择特定成分
当归档包含多个成分时,您可以过滤到仅包含您需要的成分 :
const reader = await Reader.fromAsset(
{ buffer: archiveBuffer, mimeType: 'application/c2pa' },
new Context({ verify: { verifyAfterReading: false } })
);
const activeManifest = reader.getActive();
const allIngredients = activeManifest.ingredients;
// Select only the ingredients you want (e.g., by title or instance_id)
const selected = allIngredients.filter(
(ing) => ing.title === 'photo_1.jpg' || ing.instance_id === 'catalog:logo'
);
// Build with only the selected ingredients
const builder = await Builder.withJsonAsync({
claim_generator_info: [{ name: 'my-app', version: '1.0.0' }],
ingredients: selected,
});
// Transfer resources only for selected ingredients
for (const ingredient of selected) {
if (ingredient.thumbnail) {
const resource = await reader.resourceToAsset(ingredient.thumbnail.identifier, { buffer: null });
await builder.addResource(ingredient.thumbnail.identifier, {
buffer: resource.buffer,
mimeType: ingredient.thumbnail.format,
});
}
if (ingredient.manifest_data) {
const resource = await reader.resourceToAsset(ingredient.manifest_data.identifier, { buffer: null });
await builder.addResource(ingredient.manifest_data.identifier, {
buffer: resource.buffer,
mimeType: 'application/c2pa',
});
}
}
建立组件归档
要创建成份归档,请将成份添加到 Builder 并保存为档案
const builder = await Builder.newAsync();
// Add ingredients with stable instance_id for later catalog lookups
await builder.addIngredient(
JSON.stringify({
title: 'photo-A.jpg',
relationship: 'componentOf',
instance_id: 'catalog:photo-A',
}),
{ path: 'photo-A.jpg' }
);
// Save as a .c2pa archive
await builder.toArchive({ path: 'ingredient-catalog.c2pa' });
创建和再利用构建者档案
构建者档案允许您保存构建者状态(包括成份), 并在稍后重新使用:
// Create a builder with ingredients
const builder = await Builder.newAsync();
const ingredientBuffer = await fs.promises.readFile('source.jpg');
await builder.addIngredient(
JSON.stringify({
title: 'source.jpg',
format: 'image/jpeg',
instance_id: 'source-123',
}),
{
buffer: ingredientBuffer,
mimeType: 'image/jpeg',
}
);
// Save as an archive
await builder.toArchive({ path: 'builder-archive.zip' });
// Later, recreate the builder from the archive
const restoredBuilder = await Builder.fromArchive({ path: 'builder-archive.zip' });
// The ingredients are preserved
const definition = restoredBuilder.getManifestDefinition();
console.log(definition.ingredients); // Contains the ingredient
完整的类型定义见 @ contentauth/ c2pa 类型 软件包.
签名人
图书馆为不同用途的大小写提供几种类型的签名:
本地符号
本地证书和私人密钥签名 :
import { LocalSigner } from '@contentauth/c2pa-node';
// Create a local signer with certificate and private key
const signer = LocalSigner.newSigner(
certificateBuffer,
privateKeyBuffer,
'es256', // signing algorithm
'https://timestamp.example.com' // optional TSA URL
);
// Sign data
const signature = signer.sign(dataBuffer);
回调符号
对于使用回调的自定义签名执行 :
import { CallbackSigner } from '@contentauth/c2pa-node';
// Create a callback signer
const signer = CallbackSigner.newSigner(
{
alg: 'es256',
certs: [certificateBuffer],
reserveSize: 1024, // Reserved size in bytes for the C2PA Claim Signature box.
tsaUrl: 'https://timestamp.example.com'
},
async (data) => {
// Custom signing logic
return await customSigningFunction(data);
}
);
身份断言部分
与身份断言和CAWG(身份工作组)身份有关的工作:
身份确认 构建器
以角色构建身份断言和引用断言:
import { IdentityAssertionBuilder, CallbackCredentialHolder } from '@contentauth/c2pa-node';
// Create a credential holder
const credentialHolder = CallbackCredentialHolder.newCallbackCredentialHolder(
1024, // reserveSize
'es256', // sigType
async (payload) => {
// Custom signing logic for identity assertions
return await signIdentityPayload(payload);
}
);
// Create an identity assertion builder
const identityBuilder = await IdentityAssertionBuilder.identityBuilderForCredentialHolder(
credentialHolder
);
// Add roles and referenced assertions
identityBuilder.addRoles(['photographer', 'editor']);
identityBuilder.addReferencedAssertions(['c2pa.actions']);
身份识别符号
标志有身份证明:
import { IdentityAssertionSigner } from '@contentauth/c2pa-node';
// Create an identity assertion signer
const identitySigner = IdentityAssertionSigner.new(callbackSigner);
// Add identity assertion
identitySigner.addIdentityAssertion(identityBuilder);
// Use with Builder for signing
const manifest = await builder.signAsync(identitySigner, inputAsset, outputAsset);
信任标记
这个 Trustmark 类为图像中的编码和解码信任标记提供功能:
import { Trustmark } from '@contentauth/c2pa-node';
// Create a trustmark instance
const trustmark = await Trustmark.newTrustmark({
// trustmark configuration
});
// Encode a trustmark into an image
const encodedImage = await trustmark.encode(
imageBuffer,
0.5, // strength
'watermark-text' // optional watermark
);
// Decode a trustmark from an image
const decodedData = await trustmark.decode(imageBuffer);
设置和配置
库提供全面的设置管理,可以通过一个 Context,或者使用助手函数。 参见 (原始内容存档于2018-03-21) (英语). Rust SDK 用于设置列表及其效果.
使用上下文
A 类 Context (从) c2pa-utilities,直接从 @contentauth/c2pa-node 所以,你不需要添加 包裹自己) Settings 并是建议配置 Reader 或者说 Builder数字 :
import { Reader, Builder, Context } from '@contentauth/c2pa-node';
const context = new Context({
verify: {
verifyAfterReading: false,
verifyAfterSign: false,
verifyTrust: true,
ocspFetch: true
},
trust: {
verifyTrustList: true,
trustAnchors: "path/to/anchors.pem"
}
});
// Pass a Context to Reader
const reader = await Reader.fromAsset(inputAsset, context);
// Builder has async, Context-aware counterparts to its synchronous factories below
const builder = await Builder.newAsync(context);
const builder2 = await Builder.withJsonAsync(manifestDefinition, context);
const builder3 = await Builder.fromArchive(archiveAsset, context);
[注] 一样
c2pa-web,在 a 中设置 URLContext在创建“ 阅读器” 或“ 构建器” 之前获取并解决“ 信任锁定” 设置 。 已贬值的原始设置 API 不解决 URL; 使用 aContext用于基于 URL 的信任主机.
个人设置( 折旧)
直接通过设置作为 JSON 字符串, 或作为匹配本地设置形状的原始对象( snake case key, 没有应用默认) , 已贬值, 并将被删除 Context 相反(上文). Builder.new编号 :Builder.withJson 保持这条已耗尽路径的同步 newAsync编号 :withJsonAsync 对应机构 Context 换句话说.
import { Reader, Builder } from '@contentauth/c2pa-node';
// Create settings object
const settings = {
verify: {
verify_after_reading: false,
verify_after_sign: false,
verify_trust: true,
ocsp_fetch: true
},
trust: {
verify_trust_list: true,
trust_anchors: "path/to/anchors.pem"
}
};
// Pass settings to Reader
const reader = await Reader.fromAsset(inputAsset, settings);
// Pass settings to Builder
const builder = Builder.new(settings);
// Settings can also be JSON strings
const settingsJson = JSON.stringify(settings);
const builder2 = Builder.new(settingsJson);
设置帮助函数
库提供创建和管理设置对象的辅助功能:
import {
createTrustSettings,
createCawgTrustSettings,
createVerifySettings,
mergeSettings,
settingsToJson,
loadSettingsFromFile,
loadSettingsFromUrl
} from '@contentauth/c2pa-node';
// Create trust settings
const trustSettings = createTrustSettings({
verifyTrustList: true,
userAnchors: "path/to/user-anchors.pem",
trustAnchors: "path/to/trust-anchors.pem",
allowedList: "path/to/allowed-list.pem"
});
// Create CAWG trust settings
const cawgTrustSettings = createCawgTrustSettings({
verifyTrustList: true,
trustAnchors: "path/to/cawg-anchors.pem"
});
// Create verify settings
const verifySettings = createVerifySettings({
verifyAfterReading: false,
verifyAfterSign: false,
verifyTrust: true,
verifyTimestampTrust: true,
ocspFetch: true,
remoteManifestFetch: true,
skipIngredientConflictResolution: false,
strictV1Validation: false
});
// Merge multiple settings
const combinedSettings = mergeSettings(trustSettings, verifySettings);
// combinedSettings is a plain Settings object — use it with a Context (recommended)...
const readerWithContext = await Reader.fromAsset(inputAsset, new Context(combinedSettings));
// ...or convert it to a JSON string for the deprecated per-instance settings path
const jsonString = settingsToJson(combinedSettings);
const readerWithJson = await Reader.fromAsset(inputAsset, jsonString);
// loadSettingsFromFile/loadSettingsFromUrl return a raw JSON string, not a Settings
// object, so they pair with the deprecated per-instance settings path, not Context, for now.
const fileSettings = await loadSettingsFromFile('./c2pa-settings.json');
const reader2 = await Reader.fromAsset(inputAsset, fileSettings);
const urlSettings = await loadSettingsFromUrl('https://example.com/c2pa-settings.json');
const builder = Builder.new(urlSettings);
可用设置
信任设置 :
verifyTrustList- 是否对照信托清单进行核查userAnchors- 用户提供的信任锁定(PEM格式或路径)trustAnchors- 用于验证的托管锚(PEM格式或路径)trustConfig- 信任配置文件路径allowedList- 允许的证书列表(PEM格式或路径)
校验设置 :
verifyAfterReading- 阅读清单后是否核实verifyAfterSign- 在签署清单后是否核实verifyTrust- 在验证期间是否核实信任verifyTimestampTrust- 是否验证时间戳信任ocspFetch- 是否获取OCSP的答复remoteManifestFetch- 是否获取远程清单skipIngredientConflictResolution- 是否跳过成分冲突解决方案strictV1Validation- 是否使用严格的v1验证
构建器设置 :
generate_c2pa_archive- 是否生成 C2PA 归档格式
[注] 设置以 per-ins 配置方式传递 。 没有影响所有读者和构建者的全球设置.
构建并使用自定义二进制
关于构建 Rust 二进制的说明,见 为 C2pa- 节点作出贡献。 。 。 . 要使用自定义二进制 :
export C2PA_LIBRARY_PATH=<path-to-binary-folder>/index.node