如何使用Web Crypto API的SubtleCrypto验证签名的JWT? [英] How to verify a signed JWT with SubtleCrypto of the Web Crypto API?

查看:372
本文介绍了如何使用Web Crypto API的SubtleCrypto验证签名的JWT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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.

推荐答案

要使用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'))
    )
}

这篇关于如何使用Web Crypto API的SubtleCrypto验证签名的JWT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆