VeriAgent 可信内容签名接入指南

面向开发者,介绍如何通过 VeriAgent 对文本、文件或结构化业务数据生成可信内容签名,并完成证书、摘要与签名校验,验证内容完整性与来源可信性。

1. 前置条件

开始前,请确认你已满足以下条件:

  • 已拥有 VeriAgent 平台账号。
  • 已完成 Agent 认证,并已生成可用的本地证书材料。具体流程可参考 Agent 认证快速开始
  • 已安装 Node.js,建议使用 Node.js 18 或以上版本。
  • 当前网络可访问 npm、VeriAgent 平台及相关包发布源。
  • 如果在 OpenClaw 中接入,请先完成 OpenClaw 环境准备和 VeriAgent 插件接入。具体流程可参考 在 OpenClaw 中接入 VeriAgent
  • 如果在 Hermes Agent 中接入,请先完成 Hermes Agent 环境准备和 VeriAgent 插件接入。具体流程可参考 在 Hermes Agent 中接入 VeriAgent
  • 如果你的业务系统需要直接调用 VeriAgent 服务端接口,请先准备 API Key。创建方式可参考 创建 API Key

注意:签名依赖本地证书私钥。没有完成 Agent 认证或本地证书材料不可用时,无法生成有效签名。

2. 接入方式

形态签名入口验签入口适用场景
@esign-cn/veriagent-coreruntime.signStandardObject()runtime.verifyStandardObject()Node.js 直接接入,推荐
@esign-cn/openclaw-veriagentveriagent_sign / openclaw veriagent signveriagent_verify / openclaw veriagent verifyOpenClaw 工具或 CLI
hermes-veriagentveriagent_signveriagent_verifyHermes Agent 工具

统一链路:

text
payload / text / filePath
  -> ✅ 统一生成结构化 payload
  -> ✅ 计算 payloadHash
  -> ✅ 本地证书私钥生成 signature
  -> ✅ 产出 signedObject
  -> ✅ 后端按 certificateSerialNo 验签
  -> ✅ 返回 verified / issues

3. 统一签名对象

三种形态最终都围绕同一个 signedObject

json
{
  "schemaVersion": "1.0",
  "eventType": "business_event",
  "action": "manual_sign",
  "payload": {
    "bizId": "ct_123"
  },
  "payloadHash": "7b1b2f...",
  "signedAt": "2026-06-30T10:00:00.000Z",
  "certificateSerialNo": "CERT_SN_001",
  "signatureAlgorithm": "RSA-SHA256",
  "signature": "<base64>",
  "extensions": {
    "hostType": "openclaw",
    "traceId": "trace_001"
  }
}

签名覆盖范围:

字段是否参与签名
schemaVersion eventType action
payloadHash signedAt certificateSerialNo
signatureAlgorithm
payload否,通过 payloadHash 间接参与
extensions

统一伪代码:

javascript
function signStandardObject(input, cert) {
  const payloadHash = sha256Hex(canonicalizeJson(input.payload))

  const signedObject = {
    schemaVersion: '1.0',
    eventType: input.eventType,
    action: input.action,
    payload: input.payload,
    payloadHash,
    signedAt: nowIsoString(),
    certificateSerialNo: cert.certSn,
    signatureAlgorithm: 'RSA-SHA256',
  }

  const signTarget = {
    schemaVersion: signedObject.schemaVersion,
    eventType: signedObject.eventType,
    action: signedObject.action,
    payloadHash: signedObject.payloadHash,
    signedAt: signedObject.signedAt,
    certificateSerialNo: signedObject.certificateSerialNo,
    signatureAlgorithm: signedObject.signatureAlgorithm,
  }

  signedObject.signature = signWithLocalCertificate(
    canonicalizeJson(signTarget)
  )

  return signedObject
}

function verifyStandardObject(signedObject, certRecord) {
  const payloadHashVerified =
    sha256Hex(canonicalizeJson(signedObject.payload)) === signedObject.payloadHash

  const signatureVerified = verifySignature(
    canonicalizeJson({
      schemaVersion: signedObject.schemaVersion,
      eventType: signedObject.eventType,
      action: signedObject.action,
      payloadHash: signedObject.payloadHash,
      signedAt: signedObject.signedAt,
      certificateSerialNo: signedObject.certificateSerialNo,
      signatureAlgorithm: signedObject.signatureAlgorithm,
    }),
    signedObject.signature,
    certRecord.certContent
  )

  const certificateVerified = verifyCertificateStatus(certRecord, signedObject.signedAt)
  return payloadHashVerified && signatureVerified && certificateVerified
}

4. 最小接入示例

4.1 veriagent-core

bash
npm install @esign-cn/veriagent-core
javascript
const { createRuntime } = require('@esign-cn/veriagent-core')

const runtime = createRuntime({
  clientId: process.env.VERIAGENT_CLIENT_ID,
  terminalType: 'YOUR_INTEGRATION',
  installContext: { profile: 'prod' },
})

const status = await runtime.status()
if (!status.certificateFile) {
  await runtime.install()
}

const signResult = await runtime.signStandardObject({
  eventType: 'business_event',
  action: 'manual_sign',
  payload: { bizId: 'ct_123', amount: 12800 },
  context: { hostType: 'node-service', traceId: 'trace_001' },
})

const verifyResult = await runtime.verifyStandardObject({
  signedObject: signResult.signedObject,
})

常用返回字段:

调用关键字段说明
signStandardObject()requestId signedObjectsignedObject 就是后续流转和验签的核心对象
verifyStandardObject()verified signatureVerified payloadHashVerified certificateVerified issues优先看 verified,失败时再看分项结果

4.2 OpenClaw

入口示例
工具签名veriagent_sign({ eventType, action, payload, context })
工具验签veriagent_verify({ signedObject })
CLI 签名openclaw veriagent sign --event-type business_event --action manual_sign --payload-json '{"bizId":"ct_123"}'
CLI 文件签名openclaw veriagent sign --event-type business_event --action manual_sign --file-path /tmp/demo.pdf
CLI 文件验签openclaw veriagent verify --file-path /tmp/demo.pdf
javascript
const signResult = await openclaw.callTool('veriagent_sign', {
  eventType: 'business_event',
  action: 'manual_sign',
  payload: { bizId: 'ct_123' },
  context: { hostType: 'openclaw', traceId: 'trace_002' },
})

await openclaw.callTool('veriagent_verify', {
  signedObject: signResult.signedObject,
})

OpenClaw 要点:

说明
签名输入优先使用非空 payload
payload调用方提供结构化 JSON;非空时直接参与签名对象生成
text未传 payloadpayload 为空对象时,自动生成 payload.text
filePath未传 payloadpayload 为空对象时,自动生成 payload.file
text / filePath仅在自动生成 payload 时二选一
文件签名会生成 <filePath>.signed.json
验签输入支持 signedObjectsignedObjectFilefilePath

4.3 Hermes

Hermes 与 OpenClaw 的 payload 和验签输入规则保持一致。

入口示例
工具签名veriagent_sign({ eventType, action, payload, context })
工具文件签名veriagent_sign({ eventType, action, filePath, context })
工具验签veriagent_verify({ signedObject })
工具文件验签veriagent_verify({ filePath })
python
sign_result = hermes.call_tool("veriagent_sign", {
    "eventType": "business_event",
    "action": "manual_sign",
    "filePath": "/tmp/demo.pdf",
    "context": {
        "hostType": "hermes",
        "traceId": "trace_003"
    }
})

verify_result = hermes.call_tool("veriagent_verify", {
    "filePath": "/tmp/demo.pdf"
})

Hermes 文件签名会自动生成:

text
/tmp/demo.pdf
  -> ✅ /tmp/demo.pdf.signed.json

Hermes 要点:

说明
签名输入优先使用非空 payload
payload调用方提供结构化 JSON;非空时直接参与签名对象生成
text未传 payloadpayload 为空对象时,自动生成 payload.text
filePath未传 payloadpayload 为空对象时,自动生成 payload.file
text / filePath仅在自动生成 payload 时二选一
文件签名会生成 <filePath>.signed.json
验签输入支持 signedObjectsignedObjectFilefilePath

5. 踩坑规则

规则说明
先安装再签名没有本地证书材料,三种形态都不能签
优先用标准对象跨端流转时统一用 signedObject
签名输入优先级非空 payload 优先;没有 payload 时才从 text / filePath 自动生成
自动生成 payloadtextfilePath 只能二选一
payload 要稳定相同业务语义必须生成相同 JSON
certificateSerialNo 必须显式带上后端按它查证书
extensions 只放追踪字段不要放业务事实字段

常见错误:

diff
{
  "eventType": "business_event",
  "action": "manual_sign",
- "text": "hello veriagent",
- "filePath": "/tmp/demo.pdf"
+ "filePath": "/tmp/demo.pdf"
}

规则:OpenClaw 和 Hermes 的签名输入规则一致。非空 payload 优先;未传 payloadpayload 为空对象时,textfilePath 只能二选一。

diff
{
- "signedObject": {
-   "requestId": "req_xxx",
-   "signedObject": { "...": "..." }
- }
+ "signedObject": {
+   "...": "..."
+ }
}

规则:OpenClaw 和 Hermes 验签时都不要把 .signed.json 外层 wrapper 直接塞给 signedObject。如果手上是文件,传 signedObjectFilefilePath

6. 推荐接入顺序

步骤建议
1先用 veriagent-core 跑通 signStandardObject()verifyStandardObject()
2确认业务 payload 结构稳定,再封装到 OpenClaw 或 Hermes
3OpenClaw / Hermes 都优先传非空 payload;文本或文件便捷签名再传 text / filePath
4文件场景优先走 filePath -> .signed.json -> verify