You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript中验证欧盟新冠通行证的P-256 COSE数据签名

问题核心原因说明

ES256和P-256是匹配的:ES256算法就是指采用SHA-256哈希、P-256(secp256r1)曲线的ECDSA签名算法,你的公钥参数没有问题。验证失败主要来自两个底层错误:

  • 待签名数据构造不符合COSE规范
  • 签名格式不匹配加密库要求

问题1:待签名数据构造错误

COSE签名验证不能直接使用payload内容做哈希,必须按照COSE规范构造Sig_structure结构后,整体做CBOR编码再参与哈希:

  • Sig_structure固定为四元素数组:["Signature1", 受保护头原始Buffer, 外部附加数据空Buffer, payload原始Buffer]
  • 你之前仅传入cbor_data做哈希,和签发时的待签名内容不一致,必然验证失败。

问题2:签名格式不匹配

COSE标准中使用的ECDSA签名是raw格式(r值+s值直接拼接,共64字节),而你用的ec-key库默认要求DER编码格式的签名,格式不匹配导致验证失败。


可运行的修正方案

推荐换用更符合规范的轻量加密库处理,修正后的代码示例如下:

const cbor = require("cbor");
const { p256 } = require("@noble/curves/p256");
const { sha256 } = require("@noble/hashes/sha256");

// 解码COSE消息
const result = cbor.decode(coseMessage);
const [protectedHeadersRaw, unprotectedHeaders, payload, signatureRaw] = result.value;

// 构造Sig_structure并CBOR编码
const sigStructure = [
  "Signature1",
  protectedHeadersRaw,
  Buffer.alloc(0), // 欧盟新冠通行证无外部附加数据
  payload
];
const sigStructureEncoded = cbor.encode(sigStructure);

// 哈希待签名内容
const msgHash = sha256(sigStructureEncoded);

// 验证签名,传入raw格式签名、公钥x/y坐标
const verified = p256.verify(signatureRaw, msgHash, {
  x: Buffer.from(pKey.x, 'base64url'), // 若x/y为普通base64格式可调整解码参数
  y: Buffer.from(pKey.y, 'base64url')
});

额外排查点

  • 确认公钥的x、y字段编码格式:JWK规范中默认是base64url编码,转换为Buffer时不要用普通base64解码
  • 确认protectedHeadersRaw是解码得到的原始Buffer,不要用解码后的JSON对象重新编码,否则会因为CBOR序列化的细微差异(比如整数长度、map键顺序)导致哈希不匹配

内容的提问来源于stack exchange,提问作者Simon H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 18:36:02