Signed Agent Cards:基于 JWS 防范智能体名片伪造与投毒

11 分钟阅读
1name · description · versionerror2supportedInterfaces[] · url · protocolBinding · protocolVersionerror3capabilities · defaultInputModes · defaultOutputModeserror4skills[] · id · name · description · tagserror5securitySchemes · securitywarning6provider · signatures[]warning
密码学校验位于 Agent Card 验证管道的核心信任层,确保在发起任何远程智能体调用之前验证元数据完整性。

当人工智能体通过在公网上拉取 agent.json 文件相互发现时,信任不能仅仅建立在对网络链路的盲目信任之上。一张未签名的名片,只要遭遇一次 DNS 劫持或 CDN 配置失误,就可能把自主决策系统引向恶意端点。在 A2A v1.0 规范中,Signed Agent Cards 通过 JSON Web Signature 彻底解决了这一隐患。

为什么未签名卡片存在安全隐患

A2A 协议官方规范 中,智能体的能力发现被设计为轻量、静态且无须凭据的模式:客户端智能体只需对目标域名的 /.well-known/agent.json 发起标准 HTTP GET 请求。

尽管这一特性极大地促进了多智能体生态的快速扩张,但在企业级安全攻防中,它也暴露了被称作 Agent Card Poisoning(智能体名片投毒) 的严峻风险:

  1. 接口端点重定向:攻击者若攻破 DNS 解析或边缘反向代理,即可篡改 supportedInterfaces[].url 字段,神不知鬼不觉地将包含敏感上下文的 Prompt 数据转发到监听或伪造的镜像服务器。
  2. 能力与 Prompt 恶意注入:通过篡改 skills 技能数组或 description 描述,攻击者可以误导主控智能体,将涉及金融交易或高权权限的业务委派给未经验证的恶意模型。
  3. 身份伪冒欺诈:缺乏加密签名背书时,任何人都可以自行部署卡片并在 provider.organization 中宣称自己是知名金融机构或头部软件供应商。

为了保障多智能体网络免受此类威胁,由 a2aproject/A2A 官方代码仓维护的 v1.0 规范基于 RFC 7515: JSON Web Signature (JWS) 正式落地了 signatures 签名数组机制。

signatures 数组的结构剖析

在 A2A v1.0 Agent Card 中,顶层属性 signatures 包含一个签名对象数组。这种设计支持由多个主体联合签名——例如,开发智能体的软件厂商签名,以及为该智能体执行合规审查的第三方安全认证机构签名。

数组中的每个对象均符合标准 JWS Flattened 序列化或 Compact 紧凑格式:

包含 JWS 签名的 Agent Card 片段
{
  "name": "Treasury Reconciliation Agent",
  "version": "1.2.0",
  "supportedInterfaces": [
    {
      "url": "https://agents.acme-finance.com/a2a/v1",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ],
  "signatures": [
    {
      "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6IjIwMjYtMDktY29yZSIsInR5cCI6IkpXUyJ9",
      "signature": "MEQCIFz8fV9Q2b6HqVqYx3...7k1vU8X3g"
    }
  ]
}

签名对象中各核心字段的作用如下:

  • protected:Base64URL 编码的 JSON 字符串,包含 JWS 标头参数:
    • alg:采用的加密签名算法(如 ES256RS256)。
    • kid:密钥标识符,可索引至提供商受信任公钥仓库中的对应公钥。
    • crit:(可选)关键标头扩展数组,要求验证端智能体必须识别并执行校验。
  • signature:针对规范化 Payload 和 protected 头部计算生成的 Base64URL 编码数字签名串。

使用 ES256 为 agent.json 生成签名

在对 Agent Card 计算签名时,必须对待签名的 Payload 进行确定性规范化(在计算摘要之前移除已有的 signatures 字段),以确保在不同编程语言和运行环境中生成一致的散列值。

以下是使用 Node.js 原生 Web Crypto 模块进行卡片签名的参考实现:

sign-agent-card.mjs
import crypto from 'node:crypto';
import fs from 'node:fs';

// 1. 读取卡片并在计算签名前剥离现存 signatures 属性
const rawCard = JSON.parse(fs.readFileSync('agent.json', 'utf8'));
const { signatures, ...unsignedPayload } = rawCard;
const payloadString = JSON.stringify(unsignedPayload);

// 2. 准备 JWS Protected 标头
const header = {
  alg: 'ES256',
  kid: 'https://acme-finance.com/.well-known/jwks.json#key-2026',
  typ: 'JWS'
};

const base64Url = (str) => Buffer.from(str).toString('base64url');

const protectedHeaderB64 = base64Url(JSON.stringify(header));
const payloadB64 = base64Url(payloadString);
const signingInput = `${protectedHeaderB64}.${payloadB64}`;

// 3. 使用私钥 (P-256 EC 密钥) 执行签名
const privateKeyPem = fs.readFileSync('private-key.pem', 'utf8');
const signer = crypto.createSign('SHA256');
signer.update(signingInput);
signer.end();

const signatureB64 = signer.sign(privateKeyPem, 'base64url');

// 4. 将生成的签名挂载回卡片
const signedCard = {
  ...rawCard,
  signatures: [
    {
      protected: protectedHeaderB64,
      signature: signatureB64
    }
  ]
};

fs.writeFileSync('agent.signed.json', JSON.stringify(signedCard, null, 2));
console.log('✓ Agent Card 已成功生成 ES256 数字签名');

客户端智能体如何验证签名

当客户端智能体从网络上检索到未知第三方的 Agent Card 时,必须在解析具体业务能力或调用接口之前完成防伪校验:

  1. 提取签名:解析文档中的 signatures 字段。若不存在,根据组织的零信任策略标记为未认证或直接拒绝调用。
  2. 解码头部:使用 base64url 解码 protected 内容,检查 algkid。丢弃不符合安全基线的算法(如废弃的 RSA 短密钥或伪造的 none 算法)。
  3. 获取公钥:通过 kid 标识获取对应的公钥证书,校验该公钥所属域名与卡片中的 provider.url 是否严格一致。
  4. 验证摘要与签名:重构未签名 Payload,重新生成确定性规范化哈希,并借助公钥执行签名校验。

密钥轮换与安全实践清单

在生产环境中维护 Signed Agent Cards 时,请遵循以下安全准则:

  • 解耦密钥生命周期与服务部署:通过 kid 引用统一的 JWKS 端点(/.well-known/jwks.json),切忌硬编码固定公钥,以便实现无感知无缝轮换。
  • 强制全链路 HTTPSsupportedInterfaces 下列出的所有通信端点以及公钥地址必须强制启用带有正规 CA 证书的 HTTPS。
  • 域名主体强绑定:确保承载 Agent Card 的域名与 provider.url 以及 JWKS 端点的主机名具备一致性。
  • 发布前合规自检:在正式发布至生产公网根目录前,务必使用官方 校验器 排除所有潜在格式与安全告警。

常见问题解答

在 A2A v1.0 中,JWS 签名是强制性的吗?

在基础规范中签名是可选的,但对于暴露在公网或多租户网络环境下的生产级智能体,强烈建议配置签名。缺少签名时,调用方无法判断卡片在传输过程中是否被中间人篡改。

什么是“智能体名片投毒”(Agent Card Poisoning)?

智能体名片投毒是指攻击者通过 DNS 缓存污染、CDN 错误配置或中间人攻击等手段篡改 agent.json 文件,将接口端点重定向到恶意服务器,或注入虚假能力描述以诱导调用。

签名 Signed Agent Card 推荐使用哪种加密算法?

推荐使用 ES256(基于 P-256 和 SHA-256 的 ECDSA),其具有体积紧凑、计算高效的优点。对于需要兼容传统企业 PKI 体系的场景,也可以使用 RS256。

公钥或 JWKS 端点应该托管在哪里?

公钥必须托管在服务提供商权威域名下的 HTTPS 端点,通常位于 /.well-known/jwks.json,或者通过 JWS 保护头中的 kid / x5u 属性进行引用。

Agent Card 校验器如何评估卡片中的签名?

校验器会检查 signatures 数组中是否包含格式合规的 JWS Compact 或 Flattened 对象,验证 protected 头部参数、标准算法标识符以及公钥引用的有效性。

参考资料

  1. A2A 协议官方规范 (a2a-protocol.org)a2a-protocol.org
  2. A2A 协议官方代码仓 (a2aproject/A2A)github.com/a2aproject/A2A
  3. RFC 7515: JSON Web Signature (JWS)datatracker.ietf.org/doc/html/rfc7515

相关工具: Agent Card 校验器

下一步

在正式部署前检测您的 Agent Card 完整性。

校验器将全面检查卡片结构、JWS 签名格式,并标记公钥引用缺失或接口未加密的安全隐患。