我试图使用SubtleCrypto的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的示例数据设置了一些测试。
发布于 2019-01-09 15:56:29
要用SubtleCrypto验证JWS,您需要小心地在二进制和base64url表示之间正确地编码和解码数据。不幸的是,btoa()和atob()浏览器中的atob()很难使用,因为它们使用“一个Unicode字符串仅包含U+0000到U+00FF范围内的字符,每个字符分别表示一个值为0x00到0xFF的二进制字节”作为二进制数据的表示形式。
在Javascript中表示二进制数据的一个更好的解决方案是使用ES6对象TypedArray,并使用Javascript库(或者自己编写编码器)将它们转换为尊重RFC 4648的base64url。
附带注意: base64和base64url的区别在于在标准中为值62和63选择的字符,base64将它们编码为
+和/,而base64url编码-和_。
Javascript中这样一个库的一个例子是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'))
)
}https://stackoverflow.com/questions/54062583
复制相似问题