我想使用 openssl 创建证书、密钥和公钥(3.2.1 30 Jan 2024)。我需要签署此密钥并将其用作 JWT 令牌,以通过 https 请求获取另一个访问令牌。
该应用程序是用 TypeScript 编写的,这限制了签名库的选择。我目前使用 jose 和 jsonwebtoken 包,目的是正确签署密钥。
jwt-package的verify方法的消息似乎说密钥没有PS256算法的正确RSA-PSS参数。
创建证书有以下要求:
为了创建证书,我使用 openssl 执行了以下命令来创建 cert.pem、key.pem 和 pubkey.pem。
openssl req -newkey rsa-pss -new -nodes -x509 -days 3650 -pkeyopt rsa_keygen_bits:4096 -sigopt rsa_pss_saltlen:32 -keyout key.pem -out cert.pem
openssl x509 -pubkey -noout -in cert.pem > pubkey.pem
乍一看似乎可以工作,但根据 jwt.io 调试器生成的令牌似乎没有有效签名,因为测试未通过。这就提出了客户端渲染是否会成为问题的问题。无论如何,Chrome 和 Firefox 中的结果保持不变。
const PS256 = 'PS256'
/**
* Other const for SignJWT declared
* ...
*/
const getSignedJWTToken = async () => {
const privateKeyString = readFileSync(privateKeyPath, 'utf-8')
const privateKey = await importPKCS8(privateKeyString, PS256)
const signedJwt = await new SignJWT()
.setProtectedHeader({ alg: PS256 })
.setIssuer(clientId)
.setSubject(clientId)
.setAudience(audienceUrl)
.setIssuedAt(currentTime)
.setExpirationTime(expirationTime)
.setJti(uuid)
.setNotBefore(notValidBeforeTime)
.sign(privateKey)
return signedJwt
}
由于 jose 没有给出任何问题的指示,所以我使用 jsonwebtoken verify 方法来检查签名密钥是否可以通过密钥进行验证。 jose的验证方法提供了很多信息,但没有表明签名成功。
const logVerifcationOfSignedKey = async (signedJwt: string) => {
const bufferKey: Buffer = fs.readFileSync(`${certPath}/key.pem`)
jwt.verify(signedJwt, bufferKey, { algorithms: [PS256] }, (err, decoded) => {
if (err)
console.error('JWT verification failed:', err)
else
console.log('JWT verified successfully:', decoded)
})
}
// Output: Error: Invalid key for this operation, its RSA-PSS parameters do not meet the
// requirements of "alg" PS256.
这就是问题所在,显然只能通过在创建密钥时使用不同的过程来解决。
我能够在此处(已接受的答案)找到有关
-keyout
选项参数的提示。这显然应该独立于证书创建密钥。仅使用 -out
参数的替代方案并不是解决方案。
有没有人有线索或解决方案可以帮助解决这个问题,或者有人真正认识到这个问题吗?
jsonwebtoken
库未实现正确的 RSASSA-PSS 参数验证。当没有明确的参数时,它缺少一个条件here。
此情况已在
jose
库此处中说明,这就是为什么在 Node.js 中,您可以使用 RSASSA-PSS 密钥与 jose
进行签名和验证,但不能使用 jsonwebtoken
。 jsonwebtoken
中的一个错误。
就 jwt.io 而言,它在幕后使用
jose
,但浏览器运行时使用 Web Cryptography API 并且不支持 SPKI/PKCS#8 id-RSASSA-PSS (1.2.840.113549.1.1.10)
结构。这种功能在 2022 年被删除了,以使规范与不同 Web 加密 API 实现之间的可互操作性保持一致。
为了获得最佳的互操作性,您应该对所有内容使用 JSON Web 密钥格式,或者,如果您坚持使用 PEM 序列化密钥,请使用普通的旧
rsaEncryption (1.2.840.113549.1.1.1)
OID 而不是 RSA JWA 算法的 id-RSASSA-PSS (1.2.840.113549.1.1.10)
。