如何使用Web Crypto API的SubtleCrypto验证签名的JWT?

时间:2019-01-06 14:39:00

标签: javascript jwt webcryptoapi

我正在尝试使用Web Crypto API的SubtleCrypto接口来验证JWT的签名。

我的代码将不会验证令牌签名,而JWT.io上的调试工具将而且也不知道为什么。这是我的验证功能:

function verify (jwToken, jwKey) {
  const partialToken = jwToken.split('.').slice(0, 2).join('.')
  const signaturePart = jwToken.split('.')[2]
  const encoder = new TextEncoder()
  return window.crypto.subtle
    .importKey('jwk', jwKey, { 
         name: 'RSASSA-PKCS1-v1_5', 
         hash: { name: 'SHA-256' } 
       }, false, ['verify'])
    .then(publicKey =>
      window.crypto.subtle.verify(
        { name: 'RSASSA-PKCS1-v1_5' },
        publicKey,
        encoder.encode(atob(signaturePart)),
        encoder.encode(partialToken)
      ).then(isValid => alert(isValid ? 'Valid token' : 'Invalid token'))
    )
}

我希望该代码能够正常工作,并为正确签名的JWT提供积极的验证。而是示例代码无法验证签名的令牌。对于我来说,该示例在Chrome 71中失败。

我还使用RFC 7520中的示例数据设置了一些tests

1 个答案:

答案 0 :(得分:2)

要使用SubtleCrypto验证JWS,您需要谨慎地在二进制和base64url表示形式之间正确编码和解码数据。不幸的是,btoa()atob()浏览器中的standard implementation难以使用,因为它们使用“仅包含U + 0000到U + 00FF范围内的字符的Unicode字符串。分别表示值为0x00到0xFF的二进制字节”。

以Javascript表示二进制数据的更好解决方案是使用ES6对象TypedArray并使用Javascript库(或自己编写编码器)将它们转换为支持RFC 4648的base64url。

  

旁注:base64和base64url之间的区别是在标准中为值62和63选择的字符,base64将它们编码为+/,而base64url编码-和{ {1}}。

rfc4648.js是Java语言中此类库的示例。

_