java - 使用现有私钥和 RS256 算法生成 JWT

标签 java jwt private-key

我有下面的 RSA 私钥,我必须生成一个 JWT 使用RS256 算法 的 token 。

这是我的示例私钥:

-----BEGIN RSA PRIVATE KEY----- /
MIIEoAIBAAKCAQEAnFWdIwBbLRw4xfFDXYFmlXKB4BpKeuAtfh1dcs5mhod0WTo/
i/Z4DOpiiw/2H05luI4PzOZem8AlHI9hUhHq5p1+YHM68SyvBQ9OTl+O90nmLYOt
2Jzquks11bf29nJh7KwGVHOv2nh3eL39BVsqHSt0O/rjSa0bV+QtUc2DP9U4WzZ3
8RhT2bdiRcsDuMfI024u9JGG/O4iG3wDlXyS5j6G0NVw/KEJJtYYv8ruQVpvlKUd
Ntx7aE+u6F60SjJYQSfdjMoQNMDglBFwhY11RlHSmiJ/Ym8aE+Hj11JHhPcB1N+X
RWaHV9ply4TnE13PsQtGWVKsLDNQNUeIUljKdQIDAQABAoIBAAa4d3owYxBcDOTA
K7vdUDekezN9wy3nwozlXkW33G3JbOsDt1pLoiWL/eh/Kyl1XqdsaVQkTco28bbP
Qx5wFBUN4tzqlzdpoFcrV/EZPTV268+RFZbLnXDyGBez7N3zVNpZGtHj7JoLtmHD
vm4jLnr1NJik1G3aZI6GtJwLpaocwtKWHB59hVwF5NinW6BXN0ALNfwKwU4vMWYo
I65F2zvGMVl9rbfvU+E73DXK3TN5tLOAkqZMQ8+g/VnNd/XuZwh2ZADokEXV8aNR
7zVm3MCCcaa8IKJMrgnb9q47tzfyaoIu5aRYGYKZ/8wuItv4Dal30MK1CQoCD8cD
5uzorQECgYEA9+QTCXrVHzhJJm+QWQZrXu7ydk+tEix7WY9ZY702OHiTO2x9IT4d
4lKFbLhQrQMAFhO3B31Hq5ODGS4jB3bFzATrtOR9eLCR7l+0Az2FcU1Zmqsdkyv8
zlkD9oOYif6rICrVyLQ/lbQF7erVDRbxJUjeKqGAnvELrlzcr+rx+XECgYEAoXLQ
MdR+OLsP5XbcoA//Z2pgwwKZVs282MfYjZLVqeEAAC8BB9+8HHrtMaJGvADI06OV
7lTCDaE8UlqgzN2B55FmCTiLABjhk3fEDrhGVe4jhEZz1i8t0ArjsYTwXs/uXoUz
YP2rcJtkybOQEzjbvM4s5+B8iht+dYaqwoW5/0UCgYAp68UYZlBiXjdoq5dCpuZD
gK86ONEw8JrPk4Fvb5EazbFAbGFg3Mta+c+cijMCfy5ljWH3f0U+i8yw1m+QFJLw
pKhjx/w8C8gyArdDkQTfG1Ca6nMu71JqZv1Xk/uY4pt37iaHMYxLOc2C5aKv+wA+
6OrBVNyWhHcQPp4Hlfjj0QJ/de5oJf4SNV5vPi6U+la1OdV62PgNCls+lxtkFAYu
DOlOFtQ+7IGB50vj912STcJE8FOOMYm4NjyQ05df3kXvnjeXUST8ZBXIsO/LRvVU
a3CIgRb1hn7v+Af8Sq/Q5XD9rg2eejrSAG+CL9P6ahAecswoATj5v+hVd4PnODB2
rQKBgAwe3pkQRFHjameLHip+xcHQ85aASiLjhTvFhFjRHDpJ+FoiJ2H4xi4/jd1F
KGrhMpVnLXKwe1HaONFPV3yEFK2da1r66iIr/opcx1hyKmV1xvebcUxYYoRY6j/g
JMsceBR10oGEath+43rS78LASIQG83PmTYhkcEkQNftxEGqC
-----END RSA PRIVATE KEY-----

标题

{
  "alg": "RS256",
  "typ": "JWT"
}

正文:

{
  "iss": "14a2fecb-ddd7-4823-46e2-67515bc01734",
  "sub": "13f7982d-1f78-46e2-4823-3273568fce89",
  "iat": 1521132568,
  "exp": 1522136156,
  "aud": "account-d.example.com",
  "scope": "signature"
}

下面是我的示例 Java 代码:

package com.knyc.demo;
import java.security.spec.PKCS8EncodedKeySpec;
import org.bouncycastle.util.encoders.Base64;
import org.mule.api.MuleEventContext;
import org.mule.api.lifecycle.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.jsonwebtoken.*;
import java.util.Date;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
public class GenerateJwtToken implements Callable{  
    protected final Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public String onCall(MuleEventContext eventContext) throws Exception {
        String issuer = "14a2fecb-ddd7-4823-a9cc-67515bc01734";
        String scope = "signature";
        String subject = "13f7982d-1f78-46e2-a843-3273568fce89";
        String audience = "account-d.docusign.com";
        String privateKeyPEM ="-----BEGIN RSA PRIVATE KEY-----\n" +
"MIIEoAIBAAKCAQEAnFWdIwBbLRw4xfFDXYFmlXKB4BpKeuAtfh1dcs5mhod0WTo/\n" +
"i/Z4DOpiiw/2H05luI4PzOZem8AlHI9hUhHq5p1+YHM68SyvBQ9OTl+O90nmLYOt\n" +
"2Jzquks11bf29nJh7KwGVHOv2nh3eL39BVsqHSt0O/rjSa0bV+QtUc2DP9U4WzZ3\n" +
"8RhT2bdiRcsDuMfI024u9JGG/O4iG3wDlXyS5j6G0NVw/KEJJtYYv8ruQVpvlKUd\n" +
"Ntx7aE+u6F60SjJYQSfdjMoQNMDglBFwhY11RlHSmiJ/Ym8aE+Hj11JHhPcB1N+X\n" +
"RWaHV9ply4TnE13PsQtGWVKsLDNQNUeIUljKdQIDAQABAoIBAAa4d3owYxBcDOTA\n" +
"K7vdUDekezN9wy3nwozlXkW33G3JbOsDt1pLoiWL/eh/Kyl1XqdsaVQkTco28bbP\n" +
"Qx5wFBUN4tzqlzdpoFcrV/EZPTV268+RFZbLnXDyGBez7N3zVNpZGtHj7JoLtmHD\n" +
"vm4jLnr1NJik1G3aZI6GtJwLpaocwtKWHB59hVwF5NinW6BXN0ALNfwKwU4vMWYo\n" +
"I65F2zvGMVl9rbfvU+E73DXK3TN5tLOAkqZMQ8+g/VnNd/XuZwh2ZADokEXV8aNR\n" +
"7zVm3MCCcaa8IKJMrgnb9q47tzfyaoIu5aRYGYKZ/8wuItv4Dal30MK1CQoCD8cD\n" +
"5uzorQECgYEA9+QTCXrVHzhJJm+QWQZrXu7ydk+tEix7WY9ZY702OHiTO2x9IT4d\n" +
"4lKFbLhQrQMAFhO3B31Hq5ODGS4jB3bFzATrtOR9eLCR7l+0Az2FcU1Zmqsdkyv8\n" +
"zlkD9oOYif6rICrVyLQ/lbQF7erVDRbxJUjeKqGAnvELrlzcr+rx+XECgYEAoXLQ\n" +
"MdR+OLsP5XbcoA//Z2pgwwKZVs282MfYjZLVqeEAAC8BB9+8HHrtMaJGvADI06OV\n" +
"7lTCDaE8UlqgzN2B55FmCTiLABjhk3fEDrhGVe4jhEZz1i8t0ArjsYTwXs/uXoUz\n" +
"YP2rcJtkybOQEzjbvM4s5+B8iht+dYaqwoW5/0UCgYAp68UYZlBiXjdoq5dCpuZD\n" +
"gK86ONEw8JrPk4Fvb5EazbFAbGFg3Mta+c+cijMCfy5ljWH3f0U+i8yw1m+QFJLw\n" +
"pKhjx/w8C8gyArdDkQTfG1Ca6nMu71JqZv1Xk/uY4pt37iaHMYxLOc2C5aKv+wA+\n" +
"6OrBVNyWhHcQPp4Hlfjj0QJ/de5oJf4SNV5vPi6U+la1OdV62PgNCls+lxtkFAYu\n" +
"DOlOFtQ+7IGB50vj912STcJE8FOOMYm4NjyQ05df3kXvnjeXUST8ZBXIsO/LRvVU\n" +
"a3CIgRb1hn7v+Af8Sq/Q5XD9rg2eejrSAG+CL9P6ahAecswoATj5v+hVd4PnODB2\n" +
"rQKBgAwe3pkQRFHjameLHip+xcHQ85aASiLjhTvFhFjRHDpJ+FoiJ2H4xi4/jd1F\n" +
"KGrhMpVnLXKwe1HaONFPV3yEFK2da1r66iIr/opcx1hyKmV1xvebcUxYYoRY6j/g\n" +
"JMsceBR10oGEath+43rS78LASIQG83PmTYhkcEkQNftxEGqC\n" +
"-----END RSA PRIVATE KEY-----";
        String privKeyPEM = privateKeyPEM.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
        privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
       /* byte [] encoded = Base64.decode(privKeyPEM);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
       */
       try {
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;
            long nowMs = System.currentTimeMillis()/1000;
            long expMs = nowMs + 3600;
            Date now = new Date(nowMs);
            Date exp = new Date(expMs);       
            byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(privKeyPEM);
            Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
            System.out.println(signingKey);

            JwtBuilder builder = Jwts.builder()
                                        .setIssuedAt(now)
                                        .setSubject(subject)
                                        .setIssuer(issuer)
                                        .setAudience(audience)
                                        .claim("scope",scope)
                                        .signWith(signatureAlgorithm, signingKey)
                                        .setExpiration(exp);         
            return builder.compact();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

它抛出异常说: “必须使用 RSA 私钥计算 RSA 签名。指定的 javax.crypto.spec.SecretKeySpec 类型的 key 不是 RSA 私钥。”

提前致谢...

最佳答案

你可以使用这个库 https://github.com/jwtk/jjwt

package <your package name>;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

    public class JWT {

    private String privateKey;
    <your other props such as issuer etc.>

    public JWT(String privateKey) {
        this.privateKey = privateKey;
    }

    public String encode() {

        String retStr = null;

        Claims claims = Jwts.claims();
        claims.put("issuer", "14a2fecb-ddd7-4823-a9cc-67515bc01734");
        claims.put("scope", "signature");
        claims.put("subject", "13f7982d-1f78-46e2-a843-3273568fce89");
        claims.put("audience", "account-d.docusign.com");

        // strip the headers
        privateKey = privateKey.replace("-----BEGIN RSA PRIVATE KEY-----", "");
        privateKey = privateKey.replace("-----END RSA PRIVATE KEY-----", "");
        privateKey = privateKey.replaceAll("\\s+","");

        byte[] encodedKey = android.util.Base64.decode(this.privateKey, android.util.Base64.DEFAULT);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);

        try {

            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey privKey = kf.generatePrivate(keySpec);

            retStr = Jwts.builder().setClaims(claims).signWith(privKey).compact();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return retStr;
    }
}

关于java - 使用现有私钥和 RS256 算法生成 JWT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49330180/

相关文章:

node.js - Passport jwt 401未经授权

reactjs - Auth0 React SPA API 的访问 token 不正确

iphone - 如何将现有的私钥用于新的 iOS 开发证书?

java - 如何在 sonarqube 5.1+ 中添加自定义规则

java - Android中使用SQLite获取RowID

Java:这是在特定时区将当前时间作为日历对象获取的正确方法吗?

java - 如何强制覆盖方法并同时调用 super

Java - 带有代码的 token 流 OAuth 2 E2E

apache - 如何创建用于连接到网站的私有(private)证书

java - 将字符串转换为 key 以进行加密