【发布时间】:2019-01-12 20:30:15
【问题描述】:
我正在尝试使用 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。
【问题讨论】:
-
signaturePart和partialToken是 base64url 编码的。在使用verify之前你需要解码它们 -
@pedrofb 你说得对,
signaturePart需要被解码。然而,partialToken(JWS 签名输入)不应在 RFC 7515 中的第 5 节中为验证步骤进行解码。 -
我的错误。无需解码
partialToken。签名是 base64url 编码的,与 base64 略有不同。在应用atob之前,您需要将+替换为-,并将/替换为_ -
是的,使用
btoa()真的很糟糕,因为它无法处理输出中的非字母字符,因此函数名称中二进制的“b”并不是真的。我改用 rfc4648.js 并且效果很好。 :) -
您可能想用解决方案来回答您自己的问题以备将来使用
标签: javascript jwt webcrypto-api