A2A JWS签名验证怎么过:从验签到排错

A2A 协议里用 JWS 给消息签名,目的是让接收方确认消息确实来自声称的代理,并且内容没有被改过。
验证失败时,先别急着换算法,大多数问题出在签名原文取错、密钥对不上或时间戳超出允许窗口这三处。
下面按验签的实际顺序拆开讲。

先确认签名原文到底签了什么

JWS 的签名不是对整个 JSON 请求体直接做哈希,而是对 BASE64URL(header) + "." + BASE64URL(payload) 这段字符串签名。
接收方验签时,必须用完全相同的字符串重新计算,任何空格、换行、字段顺序变化都会导致验签失败。

实际操作中,把收到的 JWS 按 . 切成三段,取前两段拼回签名原文:

signing_input = jws_parts[0] + "." + jws_parts[1]

然后用公钥验证第三段签名。
常见错误是先把 payload 解码成 JSON,再重新序列化去验签,这样几乎一定失败,因为序列化顺序和空白字符已经变了。

检查方法:在验签代码里打印 signing_input 的前 80 个字符,和发送方日志里的值对比。
如果对不上,问题就在取原文这一步。

密钥和算法要成对匹配

A2A 代理通常用非对称密钥签消息,常见是 ES256 或 RS256。
验签方需要拿到发送方 Agent Card 里公布的公钥,或者通过 JWKS 端点获取。
这里有几个容易踩的点:

  • 算法声明和密钥类型不一致:header 里写 alg: ES256,但拿到的公钥是 RSA 密钥,验签库会直接报错。
  • 用了对称密钥验非对称签名:HS256 需要共享密钥,和 ES256 的公钥验证不是一回事,不能混用。
  • 公钥格式不对:PEM、JWK、裸 Base64 之间需要转换,直接塞进去会解析失败。

如果 Agent Card 里给了 jwks_uri,
优先从那里取密钥,
并核对 kid 是否和 JWS header 里的 kid 一致。kid 对不上时不要强行用第一把钥匙试,
先确认密钥轮换是否已经发生。

时间戳和消息时效性检查

JWS 的 payload 里一般会带 iat(签发时间)和 exp(过期时间)。
验签通过只说明签名有效,不代表消息还在有效期内。
接收方通常要检查当前时间是否落在允许窗口内,比如签发后 5 分钟内。

排查时先看两个时间:

  • 发送方服务器的系统时间是否准确,用 date -u 核对。
  • 接收方和发送方是否存在明显时区或时钟偏差。

如果验签报 token expired 或类似错误,但签名本身能通过,问题就在时间窗口,不在密钥。

用最小样例复现验证过程

当线上验签失败又不好打断点时,可以拿一条失败消息的原始 JWS 字符串,在本地写一段最小验签代码复现。
步骤是:切分三段、拼签名原文、用公钥验证、再检查 payload 里的时间字段。

如果本地能通过、线上失败,重点查两处:线上是否对请求体做了二次编码,以及线上加载的公钥是不是最新版本。
反过来,本地也失败,就按前面三节逐项排除。

几个容易混淆的边界

JWS 验签通过,只能证明消息完整且来自持有对应私钥的一方,不证明对方有权限执行某个操作。
权限判断要单独做。
另外,如果 A2A 消息经过网关转发,网关如果重写了 JSON 字段顺序,接收方拿到的 payload 已经和签名原文不一致,这种场景下要么让网关透传原始 JWS,要么在网关层完成验签后再转发。

对接初期建议把验签失败的原因分类记录:原文不一致、密钥不匹配、时间过期、格式解析失败。
分类清楚后,排查会快很多。

分享到:
上一篇
A2A Agent Card 配置怎么写:从字段填写到端点验证
1
系统公告

关于香港云优质服务器IP地址更换的通知

尊敬的客户: 因原IP运营商大幅涨价,为避免成本转嫁至用户,我司决定更换IP服务商。本次更换后,您的续费价格将保持不变,且新IP网络质量与服务标准不受影响。新IP已分配至后台,即刻生效(更换的新IP都是香港原生IPv4)。 涉及 IP 段: 45.192.x.x 旧 IP 停用时间: 2026 年 12 月 1 日
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意