如何在openssl中创建符合PS256要求的带有RSA-PSS参数的key.pem?

问题描述 投票:0回答:1

正确运行的应用程序的预期行为

我想使用 openssl 创建证书、密钥和公钥(3.2.1 30 Jan 2024)。我需要签署此密钥并将其用作 JWT 令牌,以通过 https 请求获取另一个访问令牌。

环境

该应用程序是用 TypeScript 编写的,这限制了签名库的选择。我目前使用 josejsonwebtoken 包,目的是正确签署密钥。

问题

jwt-package的verify方法的消息似乎说密钥没有PS256算法的正确RSA-PSS参数。

要求

创建证书有以下要求:

  • 哈希方法:SHA-256
  • 掩码生成功能:带有 SHA-256 的 MGF1
  • 盐的长度:32字节
  • 预告片字段:0xBC

为了创建证书,我使用 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
}
使用 jsonwebtoken verify 方法验证签名令牌

由于 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
参数的替代方案并不是解决方案。

有没有人有线索或解决方案可以帮助解决这个问题,或者有人真正认识到这个问题吗?

node.js jwt openssl rsa jose
1个回答
0
投票

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)

© www.soinside.com 2019 - 2024. All rights reserved.