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-core | runtime.signStandardObject() | runtime.verifyStandardObject() | Node.js 直接接入,推荐 |
@esign-cn/openclaw-veriagent | veriagent_sign / openclaw veriagent sign | veriagent_verify / openclaw veriagent verify | OpenClaw 工具或 CLI |
hermes-veriagent | veriagent_sign | veriagent_verify | Hermes Agent 工具 |
统一链路:
text
payload / text / filePath
-> ✅ 统一生成结构化 payload
-> ✅ 计算 payloadHash
-> ✅ 本地证书私钥生成 signature
-> ✅ 产出 signedObject
-> ✅ 后端按 certificateSerialNo 验签
-> ✅ 返回 verified / issues3. 统一签名对象
三种形态最终都围绕同一个 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-corejavascript
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 signedObject | signedObject 就是后续流转和验签的核心对象 |
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 | 未传 payload 或 payload 为空对象时,自动生成 payload.text |
filePath | 未传 payload 或 payload 为空对象时,自动生成 payload.file |
text / filePath | 仅在自动生成 payload 时二选一 |
| 文件签名 | 会生成 <filePath>.signed.json |
| 验签输入 | 支持 signedObject、signedObjectFile、filePath |
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.jsonHermes 要点:
| 项 | 说明 |
|---|---|
| 签名输入 | 优先使用非空 payload |
payload | 调用方提供结构化 JSON;非空时直接参与签名对象生成 |
text | 未传 payload 或 payload 为空对象时,自动生成 payload.text |
filePath | 未传 payload 或 payload 为空对象时,自动生成 payload.file |
text / filePath | 仅在自动生成 payload 时二选一 |
| 文件签名 | 会生成 <filePath>.signed.json |
| 验签输入 | 支持 signedObject、signedObjectFile、filePath |
5. 踩坑规则
| 规则 | 说明 |
|---|---|
| 先安装再签名 | 没有本地证书材料,三种形态都不能签 |
| 优先用标准对象 | 跨端流转时统一用 signedObject |
| 签名输入优先级 | 非空 payload 优先;没有 payload 时才从 text / filePath 自动生成 |
| 自动生成 payload | text 和 filePath 只能二选一 |
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 优先;未传 payload 或 payload 为空对象时,text 和 filePath 只能二选一。
diff
{
- "signedObject": {
- "requestId": "req_xxx",
- "signedObject": { "...": "..." }
- }
+ "signedObject": {
+ "...": "..."
+ }
}规则:OpenClaw 和 Hermes 验签时都不要把 .signed.json 外层 wrapper 直接塞给 signedObject。如果手上是文件,传 signedObjectFile 或 filePath。
6. 推荐接入顺序
| 步骤 | 建议 |
|---|---|
| 1 | 先用 veriagent-core 跑通 signStandardObject() 和 verifyStandardObject() |
| 2 | 确认业务 payload 结构稳定,再封装到 OpenClaw 或 Hermes |
| 3 | OpenClaw / Hermes 都优先传非空 payload;文本或文件便捷签名再传 text / filePath |
| 4 | 文件场景优先走 filePath -> .signed.json -> verify |