@contentauth/c2pa-node

中文文档
0.10.0发布于 2026/11/05MITTypeScriptES Module构建来源已验证近 30 天下载 48.6万

C2PA 的节点绑定

中文使用文档
文档目录12 节
  1. 先决条件
  2. 安装
  3. 安装用于应用程序
  4. 文档
  5. 构成部分
  6. 阅读器
  7. 构建器
  8. 签名人
  9. 身份断言部分
  10. 信任标记
  11. 设置和配置
  12. 构建并使用自定义二进制

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:表示资产是新的数字创建,a DigitalSourceType 需要时间。 清单中不得有母成分。 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 中设置 URL Context在创建“ 阅读器” 或“ 构建器” 之前获取并解决“ 信任锁定” 设置 。 已贬值的原始设置 API 不解决 URL; 使用 a Context 用于基于 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

版本与发布记录

@contentauth/c2pa-node 共发布 42 个版本,首次发布于 2025/08/12;过去 12 个月发布了 33 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.10.0latest2026/11/055 天前
0.9.122026/11/046 天前
0.9.112026/10/2714 天前
0.9.102026/10/1724 天前
0.9.92026/09/301 个月前
0.9.82026/09/241 个月前

关于 @contentauth/c2pa-node 的常见问题

@contentauth/c2pa-node 是什么?

C2PA 的节点绑定

如何安装 @contentauth/c2pa-node?

在项目目录运行 npm install @contentauth/c2pa-node,或使用 pnpm add / yarn add / bun add。

@contentauth/c2pa-node 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@contentauth/c2pa-node 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@contentauth/c2pa-node 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@contentauth/c2pa-node 可以商用吗?

@contentauth/c2pa-node 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@contentauth/c2pa-node 的下载量有多少?

根据 npm 官方下载统计,@contentauth/c2pa-node 在 2026/10/11 – 2026/11/09 这 30 天内被下载 485,807 次,日均约 16,194 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@contentauth/c2pa-node 还在维护吗?

最新版本 0.10.0 发布于 2026/11/05(5 天前);至今共发布 42 个版本,其中过去 12 个月发布了 33 个;首次发布于 2025/08/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。