2

我正在编写以下代码以获取 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

在 sdk 文件中,我收到以下错误:

错误
│·JWS 标头缺少“zip”属性。
│ · 膨胀 JWS 有效负载时出错。您是否使用原始 DEFLATE 压缩?
│ 不正确的标头检查
│ · JWS 验证失败:在颁发者集中找不到 'kid' = 6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1 的密钥

请让我知道发行者集合以及如何将孩子价值放入发行者集合中。另外,放气压缩是什么意思以及如何解决这个问题。请注意:以上为伪代码。

4

1 回答 1

3

你基本上有两个主要错误:

第一个(我将这两条消息计为一个错误的一部分)

· JWS 标头缺少“zip”属性。
· 膨胀 JWS 有效负载时出错。您是否使用原始 DEFLATE 压缩?

表示您的令牌格式不正确。

智能健康卡需要一个压缩的有效负载,使用 DEFLATE(参见RFC1951)算法,以及一个值为“DEF”的“zip”标头,以显示有效负载已压缩,我只在JWE RFC中看到过定义,但没有对于 JWS。大多数 JWT 库可能不为签名令牌提供压缩负载,并且 node-jose 也仅支持 JWE,因此必须手动完成。

为此,您可以使用 zlib 压缩有效负载并手动将 a 添加"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) 标识的公钥,并且该密钥应在您的“颁发者集”中提供。

根据链接的文档,验证器工具有一个参数

 -k, --jwkset <key>         path to trusted issuer key set

进一步描述为:JSON Web Key (JWK) Set,编码颁发者公共签名密钥

所以基本上你必须将你的密钥库存储在一个文件(例如 issuerPublicKeys.json)中作为一个 JWKS(JSON Web 密钥集),如下所示,并在参数中提供该文件的路径。在验证您的令牌期间,验证器将从kid令牌头中读取 并尝试在提供的密钥集中找到相应的密钥。

{
  "keys":
    [
      {
        "kty": "EC",
        "kid": "6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1",
        "use": "sig",
        "alg": "ES256",
        "crv": "P-256",
        "x"  : "SVqB4JcUD6lsfvqMr-OKUNUphdNn64Eay60978ZlL74",
        "y"  : "lf0u0pMj4lGAzZix5u4Cm5CMQIgMNpkwy163wtKYVKI"
      }
    ]
}

注意:d不包括值(私钥),您只应该显示公钥。

我下载了,在有效载荷中添加了一些更多必需的数据(示例在这里找到),测试它并首先得到上述错误,提供参数后消失--jwkset issuerPublicKeys.json

node . --path jws.txt --type jws --jwkset issuerPublicKeys.json

这意味着,可以使用公钥验证 jwt!

Keyset 本身也可以被验证:

node . --type jwkset --path issuerPublicKeys.json

使用当前值,结果将是:

验证密钥集
│<br> └─ 错误
·
key[6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1]: >'kid' 与颁发者密钥中的指纹不匹配。预期:a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg,实际:
6d858102402dbbeb0f9bb711e3d13a1229684792db4940db0d0e71c08ca602e1
验证完成

提到的指纹与孩子相同。所以当你用值“a7qE0Y0DyqeOFFREIQSLKfu5WlbckdxVXKFasfcI-Dg”替换孩子时,错误消失了:

验证键集
验证已完成

于 2021-07-13T10:53:29.747 回答