• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

用户头像
it1352
帮助1

问题说明

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

I'm trying to verify the signature of a JWT using the SubtleCrypto interface of the Web Crypto API.

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

My code will not verify the token signature while the debug tool at JWT.io will and I don't know why. Here is my verify function:

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中失败.

I expected that code to work and provide a positive verification of a properly signed JWT. Instead the example code fail to verify the signed token. The example fail in Chrome 71 for me.

我还使用来自RFC 7520的示例数据设置了一些测试.

I have also set up some tests using the example data from RFC 7520.

正确答案

#1

要使用SubtleCrypto验证JWS,您需要谨慎地在二进制和base64url表示形式之间正确编码和解码数据.不幸的是,在btoa()和<<的浏览器中,标准实现 c1>难以使用,因为它们使用仅包含U 0000到U 00FF范围内的字符的Unicode字符串,每个字符代表一个分别具有0x00到0xFF值的二进制字节".

To verify a JWS with SubtleCrypto you need to be careful to encode and decode the data properly between binary and base64url representation. Unfortunately the standard implementation in the browser of btoa() and atob() are difficult to work with as they use "a Unicode string containing only characters in the range U 0000 to U 00FF, each representing a binary byte with values 0x00 to 0xFF respectively" as the representation of binary data.

使用JavaScript表示二进制数据的更好解决方案是使用ES6对象 RFC 4648 .

A better solution to represent binary data in Javascript is to use ES6 object TypedArray and use a Javascript library (or write the encoder yourself) to convert them to base64url that honors RFC 4648.

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

Side note: The difference between base64 and base64url is the characters selected for value 62 and 63 in the standard, base64 encode them to and / while base64url encode - and _.

rfc4648.js 就是这种Java语言库的示例.

An example of such a library in Javascript is rfc4648.js.

import { base64url } from 'rfc4648'

async function verify (jwsObject, jwKey) {
  const jwsSigningInput = jwsObject.split('.').slice(0, 2).join('.')
  const jwsSignature = jwsObject.split('.')[2]
  return window.crypto.subtle
    .importKey('jwk', jwKey, { 
         name: 'RSASSA-PKCS1-v1_5', 
         hash: { name: 'SHA-256' } 
       }, false, ['verify'])
    .then(key=>
      window.crypto.subtle.verify(
        { name: 'RSASSA-PKCS1-v1_5' },
        key,
        base64url.parse(jwsSignature, { loose: true }),
        new TextEncoder().encode(jwsSigningInput))
      ).then(isValid => alert(isValid ? 'Valid token' : 'Invalid token'))
    )
}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tanhcfggbb
系列文章
更多 icon
同类精品
更多 icon
继续加载