我正在尝试使用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。
答案 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语言中此类库的示例。
_