使用Java的private键创建一个RSA256 JWT

发布于 2025-02-07 07:52:19 字数 2181 浏览 3 评论 0原文

我正在尝试为行API创建访问令牌 以下是我的私钥
{
“ alg”:“ rs256”,
“ D”:“ TC4IJ ...... WQSQIQ”,
“ dp”:“ njg12kiro ... nc02gdk-d8”,
“ dq”:“ uzrtj ..... ha70”,
“ e”:“ aqab”,
“ ext”:true,
“ key_ops”:[
“标志”
],
“ kty”:“ rsa”,
“ n”:“ rj_fxz ..... kundvoohimw”,
“ p”:“ 70K5HA_WTNMAEM ..... Z4PG79DZ5U”,
“ Qi”:“ 7J7GZQQ .... NFS7B8HRIC4”
}

下面的代码来创建带有有效载荷和标头的密钥的令牌

String token = null;
        byte[] privateKey = ResourceUtil.readStr("line_key/privatekey-dev.json", StandardCharsets.UTF_8).getBytes();
        // ペイロードの設定
        Map<String, Object> payloadClaims = new HashMap<>();
        // line channel id
        payloadClaims.put("iss", "XXXXXXX");
        payloadClaims.put("sub", "XXXXXXX");
        payloadClaims.put("aud", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        payloadClaims.put("exp", new Date(System.currentTimeMillis() + 60 * 30));
        payloadClaims.put("token_exp", 60 * 60 * 24 * 30);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privateKey);
            RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
            //Algorithm algorithm = Algorithm.RSA256(null, privKey);
            token = Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setHeaderParam("alg", "RS256")
                    .setHeaderParam("kid", "XXXXXXX").setClaims(payloadClaims)
                    .signWith(SignatureAlgorithm.RS256, privKey) 
                    .compact();
        } catch (Exception e) {
            log.error(e.getMessage());
        }

我想使用 但是它总是显示
java.security.spec.invalidkeyspecexception:java.security.invalidkeyexception:无效的密钥格式
即使我使用base64来解码从JSON文件中读取的私钥,也无法使用。

byte[] keyContentAsBytes = Base64.getMimeDecoder().decode(privateKey);

任何身体都可以告诉我如何解决这个问题。
谢谢

PS:JWT可以由Python与
生成

key = RSAAlgorithm.from_jwk(privateKey)
JWT = jwt.encode(payload, key, algorithm="RS256", headers=headers, json_encoder=None)

I am trying to create an access token for line API
below is my private key
{
"alg": "RS256",
"d": "TC4Ij......wqSQIQ",
"dp": "nJg12KiRo...nc02GdK-d8",
"dq": "UzRtJ.....HA70",
"e": "AQAB",
"ext": true,
"key_ops": [
"sign"
],
"kty": "RSA",
"n": "rj_fXZ.....kuNDvOOHimw",
"p": "70k5HA_wTnmAEm.....z4pG79DZ5U",
"qi": "7j7gzQq....NfS7B8HRiC4"
}

I wanted to create a token by the the key with payload and header using the code below

String token = null;
        byte[] privateKey = ResourceUtil.readStr("line_key/privatekey-dev.json", StandardCharsets.UTF_8).getBytes();
        // ペイロードの設定
        Map<String, Object> payloadClaims = new HashMap<>();
        // line channel id
        payloadClaims.put("iss", "XXXXXXX");
        payloadClaims.put("sub", "XXXXXXX");
        payloadClaims.put("aud", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        payloadClaims.put("exp", new Date(System.currentTimeMillis() + 60 * 30));
        payloadClaims.put("token_exp", 60 * 60 * 24 * 30);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privateKey);
            RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
            //Algorithm algorithm = Algorithm.RSA256(null, privKey);
            token = Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setHeaderParam("alg", "RS256")
                    .setHeaderParam("kid", "XXXXXXX").setClaims(payloadClaims)
                    .signWith(SignatureAlgorithm.RS256, privKey) 
                    .compact();
        } catch (Exception e) {
            log.error(e.getMessage());
        }

Since the private the not encoded so I didnt use Base64 to decode it.
But it always showed
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
Even if I use Base64 to decode the private key read from the json file it didnt work.

byte[] keyContentAsBytes = Base64.getMimeDecoder().decode(privateKey);

Can any body tell me how to solve this issue.
Thanks

PS: jwt can be generated by python with

key = RSAAlgorithm.from_jwk(privateKey)
JWT = jwt.encode(payload, key, algorithm="RS256", headers=headers, json_encoder=None)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

╰ゝ天使的微笑 2025-02-14 07:52:19

首先,由于您正在重新发明日期算术轮,因此您的令牌只能有效1.8秒。我怀疑这就是您的意图。从Java.Time中使用更高的API,而不是魔术数字,并从java.util中使用过时的类型,以便您的代码明确表示意图。

您没有PKCS-#8编码的密钥规范,因此您不能使用pkcs8encodedkeyspec。由于某种原因,我无法理解,JWK忽略了像PKC#8这样的现有标准,并发明了一种新格式,具有肿但仍然不透明的JSON编码。

如果您确实需要自己转换私钥,则可以从JWK获取参数,并创建 rsaprivatecrtkeyspec我说的是“真的,我会感到惊讶从JWK表示形式加载privateKey

这是JWK RSA私有密钥成员和Java的rsaprivatecrtkeyspec属性之间的映射。

JWK成员rsaprivatecrtkeyspec属性
n模量
ePubliceXponent
dprivatexponent d privateponp
qPriperp
QPrimeq dp primeq
dpprimeexponentp
dqprimeexponentq
qicrtCoefflic

base-64解释JWK中的每个值正面:新的BigInteger(+1,大小)。实例化a rsaprivatecrtkeyspec,并将其与您的key -factory代替pcks8encodedkeyspec

First, because you are re-inventing the date-arithmetic wheel, your token will only be valid for 1.8 seconds. I doubt that's what you intended. Use higher level APIs from java.time instead of magic numbers and obsolete types from java.util so that your code states the intent clearly.

You don't have a PKCS-#8–encoded key spec, so you can't use PKCS8EncodedKeySpec. For some reason I can't fathom, JWK ignored existing standards like PKCS #8 and invented a new format with a bloated yet still opaque JSON encoding.

If you really need to convert the private key yourself, you can get the parameters from the JWK and create a RSAPrivateCrtKeySpec. I say "really," because I'd be surprised if the library you are using doesn't have some means to load a PrivateKey from a JWK representation.

Here is the mapping between JWK RSA private key members and Java's RSAPrivateCrtKeySpec properties.

JWK memberRSAPrivateCrtKeySpec property
nmodulus
epublicExponent
dprivateExponent
pprimeP
qprimeQ
dpprimeExponentP
dqprimeExponentQ
qicrtCoefficient

Base-64 decode each value in the JWK, then create a BigInteger with the resulting magnitude, specifying the sign is positive: new BigInteger(+1, magnitude). Instantiate a RSAPrivateCrtKeySpec and use that with your KeyFactory in place of the PCKS8EncodedKeySpec.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文