如何解决智能健康卡令牌验证失败
我正在编写下面的代码来获取 jwt 令牌,我想用它来验证 SMART Health Cards Validation SDK
var jose = require("node-jose");
const {JWS} = require("node-jose");
async function a1(){
try {
const keystore={
keys: [
{
kty: 'EC',d: 'gLkNmSBFWR67hEu62eVfVWhFbLGl309jOszsocqbexE',use: 'sig',crv: 'P-256',kid: '6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1',x: '5R2yrryD1ztBYnyKyQF5r5kzPUjnVnmR5pMe7H9ykNU',y: 'VaqqjG0N2rSuijP9P9QiOjX4XEhIl8k8fzA6FZTSMhY',alg: 'ES256'
}
]
}
const ks = await jose.JWK.asKeyStore(keystore);
const rawKey = ks.get(keystore.keys[0].kid)
const key = await jose.JWK.asKey(rawKey);
const payload =JSON.stringify({ "iss" : "https://spec.smarthealth.cards/examples/issuer","sub": "1234567890","name": "John Doe","iat": 1516239022});
const token =await jose.JWS.createSign( {format: 'compact'},key).update(payload,"utf8").final();
console.log(token);
}catch (err) {
console.log(err);
}
}
a1();
我正在获取令牌:
eyJhbGciOiJFUzI1NiIsImtpZCI6IjZkODU4MTAyNDAyZGJiZWIwZjliYjcxMWUzZDEzYTEyMjk2ODQ3OTJkYjQ5NDBkYjBkMGU3MWMwOGNhNjAyZTEifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkVyaWMgRC4iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE1MTYyMzkwMjJ9.dbjb9YHFCWaFYGQYyGDDL1iFvqk1Ed9k3-PAhVx4NtvFml1q0VcpW854IXW_J47f6Vf1otm2WeftVQHjY3K4vg
当我使用这个命令时:
node . --path C:\Users\User\Documents\Saguaro\health-cards-validation-SDK-main\jws.text --type jws
错误
│ · JWS 标头缺少“zip”属性。
│ · 膨胀 JWS 有效载荷时出错。您是否使用了原始 DEFLATE 压缩?
│ 不正确的标题检查
│ · JWS 验证失败:在 issuer set 中找不到 key with 'kid' = 6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1
请让我知道发行者集是什么以及如何将孩子的价值放入发行者集。 另外,deflate 压缩是什么意思以及如何消除这个问题。 请注意:以上为伪代码。
解决方法
您基本上有两个主要错误:
第一条(我把这两条消息算作一个错误的一部分)
· JWS 标头缺少“zip”属性。
· 膨胀 JWS 负载时出错。您是否使用了原始 DEFLATE 压缩?
表示您的令牌格式不正确。
Smart Health Cards require a compressed payload,使用 DEFLATE(参见 RFC1951)算法,以及带有值“DEF”的“zip”标头以表明有效载荷已被压缩,这是我只见过的在 JWE RFC 中定义,但不适用于 JWS。大多数 JWT 库可能不为签名令牌提供压缩有效负载,并且 node-jose 也仅支持 JWE,因此必须手动完成。
为此,您可以使用 zlib 压缩有效负载并手动将 "zip":"DEF"
添加到标头:
const zlib = require("zlib");
...
const payload = "{...}" // very long payload,see example in https://mikkel.ca/blog/digging-into-quebecs-proof-of-vaccination/
const payloadBuf = zlib.deflateRawSync(payload)
const token =await jose.JWS.createSign({alg: 'ES256',fields: { zip: 'DEF' },format: 'compact'},key).update(payloadBuf,"utf8").final();
第二个错误是:
JWS 验证失败:在发行者集中找不到 'kid' = 6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1 的密钥
这意味着为了验证您的令牌,需要由给定的 keyId (kid) 标识的公钥,并且该密钥应在您的“发行者集合”中提供。
根据linked documentation验证器工具有一个参数
-k,--jwkset <key> path to trusted issuer key set
进一步描述为:一个 JSON Web 密钥 (JWK) 集,对发行者公共签名密钥进行编码
所以基本上你必须将你的密钥库作为 JWKS (JSON Web Key Set) 存储在一个文件中(例如 issuerPublicKeys.json)
如下所示,并在参数中提供该文件的路径。在验证您的令牌期间,验证器将从令牌标头中读取 kid
并尝试在提供的密钥集中找到相应的密钥。
{
"keys":
[
{
"kty": "EC","kid": "6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1","use": "sig","alg": "ES256","crv": "P-256","x" : "SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74","y" : "lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI"
}
]
}
注意:d
值(私钥)不包括在内,您应该只显示公钥。
我下载了 package,向负载添加了一些更多需要的数据(例如找到了 here),对其进行了测试并首先得到了上述错误,在提供参数 {{1} 后该错误消失了}:
--jwkset issuerPublicKeys.json
也就是说,jwt 可以用公钥验证!
密钥集本身也可以被验证:
node . --path jws.txt --type jws --jwkset issuerPublicKeys.json
使用当前值,结果将是:
验证密钥集
│
└─ 错误
·
key[6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1]:>'kid'与发行者密钥中的指纹不匹配。预期:a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg,实际:
6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e
验证完成
提到的指纹与孩子相同。所以当你用值“a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg”替换孩子时,错误消失了:
验证密钥集
验证完成
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。