当前位置: 首页 > 知识库问答 >
问题:

为什么EC密钥被视为JWT和JWK的有效RSA密钥?

胡元明
2023-03-14

我最近一直在致力于实现一个web服务,该服务可以签署和发布JWT,还可以出于JWT验证的目的公开JWKsendpoint。

根据IETF规范,JWT/JWK非常简单,但我注意到一些奇怪的事情,我现在还无法解释:

TL;DR:为什么EC P-256源密钥适用于使用RSA algo签名JWT?

说来话长:

我正在使用预先存在的私钥文件对JWT进行签名,并将JWK导入node-jose密钥库。

密钥库:

const jose = require('node-jose');
const fs = require('fs')

const PRIVATE_KEY_PATH = process.env.PRIVATE_KEY_PATH

const privateKey = fs.readFileSync(PRIVATE_KEY_PATH,"utf8");

console.log('Begin import of private key to the JWKS...')
let jwkJson = {}
const jwks = jose.JWK.createKeyStore();
jwks.add(privateKey, 'pem').then(function(jwk) {
  console.log(`Imported JWK:\n${JSON.stringify(jwk, null, 2)}`)
  jwkJson = jwks.toJSON(true)
});


const getPrivateKey = () => {
  return privateKey;
}


const getJwks = () => {
  return jwkJson
}

module.exports = {
  getPrivateKey,
  getJwks
}

JWT公司:

const jwt = require('jsonwebtoken')
const keystore = require('../util/keystore')

const payload = {
  cert_hash: 'whatever'
}
const signOptions = {
  algorithm: "RS256",
  expiresIn: Math.floor(Date.now() / 1000) + 1800,
  issuer: 'whatever',
  subject: 'whatever'
}

return jwt.sign(payload, keystore.getPrivateKey(), signOptions);

看起来很标准,似乎很有效。

捕获在关键文件类型中。它是椭圆曲线(ES)P-256或通过openssl创建的JWT-worldES256

openssl ecparam -genkey -name P-256 -noout -out api-gw.key

示例键:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNkiJxzt3uGhxh
OzlG1Zs4HRx0rn1caAcyrzGiIK3LxD4ewcUPqjco8ONbrMSxhurMZbbZyasUyDs5
2guveFhGVYQzfgMmJLK77eAkEB6zHcAP76tpv6LYFuDNTep9pUc+5tQIyNDY5hKe
UMkxrgzckTVyLpzcH2tsugjUUT4A7ad4brXR1/3hqusA53DNucI4Sv7CJTAGMenN
8SwifbIwxvlORFQ8QvYCBdW8HZ1TvoBz3E6vk7gypNUvRNAVMquQapb6LS0VkmSg
bk5cSaopcvyn2Oq+cxnSh7glgZcfeopZ80j4bFmsZnK2UDJnAGm+RC7Q1SvMDhhb
7F/1x97fAgMBAAECggEAPMLj8XWuvVD0cHzb2icLARQBtC9bGHQbJI0KA5zbIe54
Wgj2IUIzmaNR4Gf5n2t8fTvXRxpHuhXRA7GCYLQWi3t9XubxMVYJimiuJpqpKFIz
0cIKjXA6RtrESYqtM8Qlgd8ibxJEQMgIWskQHuIOJSe6f2xtqtaSnwmB0JfO1uDg
RnZoUEd+oZMqu2vqz0cL0e1Q6UR9WYpSH68uS05KgYlZOzOsHMadkXfwW6BEqYd6
2gh9I1GkrY0ZsuCOVhCAc7rtuUQRMnpACNuWci/qPKQLcvSJBojS/W9xEVrVBXkQ
AZyZltjw1B5CJ9/2lbFVRTM4D/JSS84BsQEwsZm2MQKBgQDrL9kIlKCTXNl4lTYk
G8JTKV85/MUY2seWmg2K18EL8ovovY15TjKF5N6g518phmiMUPg+QxkFiAY3gZ4A
+aXsdkxo2XeTEOxFQ3ysbI4H0L0+GMCCAvqCGJr4c1kGSB1kFnGDlo7bSXBUxwlZ
4tTnVQEX0H+mfTJ7yOxv7A/lWQKBgQDfw1XtbnykCEbWXNsmgzzrmk3vvZKlNfc8
CR6PD6fCCa/yYwCv0ItJMVcF14z0vIlsaw6TmsotQIpn6tzv+ttA9KxIKPVtUNFi
O5RTgTFQUq4NO0uUje6Wj1M6uRJRo9yHUted+wcCHoQ4k1xGg7jCMiw/8O7K3Diy
Kxz9Ve2G9wKBgQDbsPd4t3WEElCm/iLz+eY9TsFAZqkqfXvBZ6hM0RvocCpXP3G/
Jde2EUQRY/AV1xMkN6KcbosaCqVcBj01Rf7DcwIPU00KWN2MGe2FF2ZZUJjmP7Lb
/7JIAnoIqZ84afbifsCMngBWQTSoTMCkcWpVqab6uu3y9LJKxTZvmkCDCQKBgGNb
LNBceuOq+Sk92eFj7K0AuxJ0rqTFLZ5uvi7v2KGEA6gw5aErjG1XhziE2YXiIXMO
pk5MMPGe8tXpp2i3jpttCQKRjUiY1iA0LExX1TnBPJ+LcKfpzcL0qRQuEUBG7ij4
U91GFXqPak5kwFhfLK6t8JADv0Q8PMB//ENQ4ENJAoGAf8fdXSYwWEhdcQcxA3JV
MHDKSOblhapT52oXnNN6VW63ccv0mRD0gRQL5nOUQdGghvtFixBoasIMz0K2i8tH
kRz56CTLpLFop+gMz+j1PPL+hjRJOGpqoPjnHkWbvK6iGadTE4nT8iqGq4p11yuc
K+HDZxjTgVXEEbOuIpbAd/8=
-----END PRIVATE KEY-----

虽然我明确声明我在JWT情况下使用RS256作为algo,但在导入密钥时节点jose推断出它本身是RSA类型:

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "gxGP1sgIVSrKTUlfBKKqdKk97UQEhEDFSMRY2vstxQk",
      "n": "zZIicc7d7hocYTs5RtWbOB0cdK59XGgHMq8xoiCty8Q-HsHFD6o3KPDjW6zEsYbqzGW22cmrFMg7OdoLr3hYRlWEM34DJiSyu-3gJBAesx3AD--rab-i2BbgzU3qfaVHPubUCMjQ2OYSnlDJMa4M3JE1ci6c3B9rbLoI1FE-AO2neG610df94arrAOdwzbnCOEr-wiUwBjHpzfEsIn2yMMb5TkRUPEL2AgXVvB2dU76Ac9xOr5O4MqTVL0TQFTKrkGqW-i0tFZJkoG5OXEmqKXL8p9jqvnMZ0oe4JYGXH3qKWfNI-GxZrGZytlAyZwBpvkQu0NUrzA4YW-xf9cfe3w",
      "e": "AQAB"
    }
  ]
}

有人能解释一下这一切是怎么回事吗?我的理解是底层密钥类型必须与签名算法匹配。

更新:加密输出:

const keystore = require('./util/keystore')

const key = require('crypto').createPrivateKey(
    {
      key: keystore.getPrivateKey(),
      format: 'pem',
      encoding: 'utf8'
    }
)

console.log(`key.asymmetricKeyType: ${key.asymmetricKeyType}`) // rsa
console.log(`key.asymmetricKeyDetails: ${key.asymmetricKeyDetails}`) // undefined

共有1个答案

巫墨一
2023-03-14

显然,问题不在于JWT/JWK依赖项,而在于密钥和X509生成过程中涉及的openssl命令链。

其中一个命令-openssl req-错误地包含param-keyout(而不是-key),该命令隐式生成RSA密钥,而没有在其源代码中提及密钥类型,并覆盖原始EC密钥。

不幸的是,我找不到一个简单的openssl命令来验证密钥类型,这是我在发布此问题之前尝试做的事情,但我的一般建议是在密钥源文件中查找密钥类型。看起来它要么显式声明,要么隐式假设为RSA。

 类似资料:
  • 假设我有一个python结构,表示RSA密钥对,如下所示: 如何编写python代码来生成可用于验证使用此RSA私钥签名的JWT的JWK?使用的算法是RSA256。 这个网站mkjwk完成了我想做的事情。但我正试图用python代码来做到这一点。

  • 我知道RSA密钥可以使用不同的算法生成。使用,我似乎无法指定密钥生成器应该使用什么算法。我怀疑它使用的是。 如何在bashshell或Ruby中使用不同的算法(例如)生成RSA密钥?库是否支持使用不同的算法生成RSA密钥?如果没有,有人知道我可以使用另一个图书馆吗?(在ruby中,似乎不允许选择算法,但文档对我来说很难遵循soo…?) 很抱歉,如果这个问题已经得到了回答,但我还没有找到答案。 也许

  • 我已经创建了一个基本的JWT生成器,但需要几个方面的建议。我一直在使用JWT. io的指南和Auth0/java-jwt库/repo来生成令牌。 JWT使用两个不同的密钥进行签名。 使用RSA512算法,使用4096位密钥对刷新令牌进行签名。 访问令牌正在通过RSA256算法用1024位RSA密钥签名。 由于4096位验证过程需要更长的时间,我在“速度”方面提出了建议,但由于刷新令牌的请求似乎较少

  • 在画布中,为了让LTI应用程序进行身份验证,站点管理员必须输入远程站点的JWK。JWK的格式定义明确: 首先,我们可以使用像openssl这样的工具,创建一个密钥,并从中生成JWK吗?目前,我们正在使用jose4j编写代码来实现这一点,但还不清楚这是否必要。 其次,Canvas需要一些可选字段,如kid、alg和use。我们猜测use应该是“sig”,我们编造了kid:“1”,猜测alg:“RS2

  • 我遇到了许多API,它们为用户提供了一个API密钥和一个秘密。但我的问题是:两者之间有什么区别? 在我看来,一把钥匙就足够了。假设我有钥匙,只有我和服务器知道。我用这个键创建了一个HMAC哈希,并进行了一个API调用。在服务器上,我们再次创建HMAC哈希,并将其与发送的哈希进行比较。如果是相同的,则呼叫经过身份验证。 那为什么要用两把钥匙呢? 编辑:或者该API密钥用于查找API机密?

  • 对示例代码中应用的概念“带RSA加密的JSON Web令牌(JWT)”有疑问 参见:http://connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-rsa-encryption 我的问题:为什么客户端使用私钥?为什么不在加密器上使用私钥,在解密器类上使用公钥呢? 欢迎对此RSA示例代码的概念方面进行澄清。