简体   繁体   中英

Generating a JWT using an existing private key and RS256 algorithm

have the below RSA Private key with me and I have to generate a JWT token using RS256 algorithm .

Here is my sample Private Key :

-----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-----

Header

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

Body :

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

Below is my sample Java code:

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 "";
        }
    }
}

It is throwing exception saying: "RSA signatures must be computed using an RSA PrivateKey. The specified key of type javax.crypto.spec.SecretKeySpec is not an RSA PrivateKey."

Thanks in Advance...

You could use this library 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;
    }
}

If some of you is still struggling in generating a jwt Token especially for Docusign Auth services maybe this example can work also for you :

Before you start , use this command on linux box in order to convert your RSA private key in the correct format : copy and paste your key in a file and launch :

openssl pkcs8 -topk8 -nocrypt -in privatekeyOLD -out privatekeyNEW

After copy again the new key generated ,and paste inside your code inside the variable String rsaPrivateKey (maybe yuo'll remove some extra chars generating during the copy and paste process) As a reference I've used this https://www.viralpatel.net/java-create-validate-jwt-token/

Required JDK 11

import io.jsonwebtoken.Jwts;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

public class JWTIO{
//  reference https://www.viralpatel.net/java-create-validate-jwt-token/
public static String createJwtSignedHMAC() throws InvalidKeySpecException, NoSuchAlgorithmException {

    PrivateKey privateKey = getPrivateKey();

    Instant now = Instant.now();
    String jwtToken = Jwts.builder()     
            .setIssuer("2a03dbc6-XXXX-XXXXX-XXXX-7e9ac9df613f")
            .setSubject("2a285ff3-XXXX-XXXX-XXXXX-e433497afc23")
            .setAudience("account-d.docusign.com")
            .claim("scope","signature impersonation")
            .setIssuedAt(Date.from(now))
            .setExpiration(Date.from(now.plus(5l, ChronoUnit.MINUTES)))
            .signWith(privateKey)
            .compact();

    return jwtToken;
}

private static PrivateKey getPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
    /* before to put the rsa private key in your String you must convert in PKCSS#8 
     * THE CERTIFICATE PROVIDED BY DOCUSIGN IS PKCS#1 and does not works
     * copy the rsa provate key ina file and use this command in linux ubuntu for 
     * example
     * openssl pkcs8 -topk8 -nocrypt -in privatekeyOLD -out privatekeyNEW
     * */
    String rsaPrivateKey = "-----BEGIN PRIVATE KEY-----" + 
            "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCKAIc+hqdKgcPb" + 
            "9XbR5Osbdeq1J14zxRG58CkrHZO0PMSf/smoCEyEcxhGsjrITl/sLv/q8iOVMKgY" + 
            "KdpOMIoPDGCF8KCXA4F9hM/WXJstprEeqPi7a1FnXzi3uwaf+jy2zUviDt09jm+g" + 
            "uu5TaZzTuzyoClEgfwIu2LwuHaJKtjceRKHWKvUqqxBQMXlq/s5lNXWajWSpLffP" + 
            "/5L0YfCK9uW1FJJXT4cP9fiNbcd6GiHGwVk/eJy4QYaR9lWNvnKKu1H52xgWkLC+" + 
            "TwfOtcqtjF9sWE5XIAjpdFVh5u64g/uOafKzEF/yVOTzPvYUWI3PhKjqSS3V3yhk" + 
            "TqoFG53hAgMBAAECggEALo0NEgdkCRsK0XjUsurQb/vvx1nXSglQ+HLNwFCC0Yqq" + 
            "HPpaVccu4ILejoJyl7zwWIBmLX+uhxXZrgT4MeXnvDnFmYjY8vfox0l0vm+QnO6c" + 
            "0qXW+Ymy9PbG8BszmeVUc6l+zmuLL8eLWiGUYSjAESAYzupkAV02hEzx9XBjnWWl" + 
            "ifoWOXvO22ADtO8jRk1ODbOrqyt1Hz7UDLtQI6Vdw3QovadW/3hKCx+0a/WxgDhR" + 
            "VosPudbzIGYBzdnbOyT+ToVIyMBTJU/8muZbWsaaOXHhel9lD/CUjvCcivL5tcSU" + 
            "0KvEiHVCXWfojbuy/RksgSTvl/aFEOrmqRjyu2JEbQKBgQDt+B4r6NVuqOPus+Xb" + 
            "RHF8QpvtwzIWSxxAwbtAWxWDJSrMMlhAx1yZ4kefSxbxAkdNkv9vQoVabVAEiWdJ" + 
            "VzXB8W9tvcD57zrbiraHQI5hCn+t5GIsSTnbhg6CG2dxv58uWviDneeNEdDeki+b" + 
            "vwTTXuHIeyCnPdLI/vaMzO0clwKBgQCUdVm5IYxRd93ohYH14zIfty+7J301iB3t" + 
            "t/fccrg1qjx4WniLbhLweVYdL44XpzMZUzdAYFhyHUIyAWIR4yHC3b0+u34oshjv" + 
            "MD/gjWPiNTBBthYTy559todm3jyj+g9Z+gLLu2G93+wGl3u15igiTy0oMmh4bS3s" + 
            "xtFk1pLQRwKBgF8L+wEOvjC0xFVTBTvO2oUHFcChdh/xYBd9SY0q1CzNa4qjkRxO" + 
            "hG3yMykslL0ua8xQKjYGG71Ca/Nj7h0c+Bu+kwMCB1HMe3W0sbLT1gpsZxLNZWjK" + 
            "1pEXujO9PlPwdWPOcfQf3Zw6wXIkcV+DrCnAe+3XP/OMfeRJ8a/LKemBAoGAf46M" + 
            "9wqiO+WYH4+G6LS7fpCxTEdTx8kangQxzZIsQL/ykR568KI1V7WJji4sEpqwxxO/" + 
            "J2sg03vcQob5spDLk1lenyYN8f2Eew+j8tbJebVlrzA6q+uKVE2e7X4J8IKM6ixs" + 
            "doycIL7jV46U1ufYmBIbpKwbI0375bO2esP7BUUCgYBqmx7GJnyOapOYlR7wHhYL" + 
            "rXk0QWwE7j3d4zQCHGOqzFqWxyIi1hsQYCwgOeobmd0r5kULRRptYBKvflEiboVq" + 
            "RL3VeyR9ZIEDkbCUewwf2qn6EoOCfi7x6/36brhn8r3mWC9rvNiKB33iBJrkin1p" + 
            "f0aUgyrlhk1aMnDDBFFb8A==" + 
            "-----END PRIVATE KEY-----";

    rsaPrivateKey = rsaPrivateKey.replace("-----BEGIN PRIVATE KEY-----", "");
    rsaPrivateKey = rsaPrivateKey.replace("-----END PRIVATE KEY-----", "");

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(rsaPrivateKey));
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey privKey = kf.generatePrivate(keySpec);
    return privKey;
}
}

Required libraries

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.2</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
    <version>0.11.2</version>
    <scope>runtime</scope>
</dependency>

To invoke this method you must surrond it with try catch, and you'll be ready to go example :

String bearer = null;
try {
    bearer = JWTIO.createJwtSignedHMAC();
} catch (InvalidKeySpecException e) {
    
    e.printStackTrace();
} catch (NoSuchAlgorithmException e) {

    e.printStackTrace();
}

It is not working because of the line separators. You should also remove the \\n by

privKeyPEM = privKeyPEM.replaceAll("\n", "");

after

privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM