Monday, May 21, 2018

How to create a self signed certificate, and how to validate the JWT token using Nimbus

This post will help you to generate a self-signed certificate and show you how to validate the JWT token using Nimbus Jose JWT library.


package com.varra.samples;

import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;

import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

import sun.security.rsa.RSAPublicKeyImpl;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;

public class JWTTokenUtils {


/** 
* Create a self-signed X.509 Certificate
* @param dn the X.509 Distinguished Name, eg "CN=RK, L=Hyderabad, C=Hyderabad"
* @param pair the KeyPair
* @param days how many days from now the Certificate is valid for
* @param algorithm the signing algorithm, eg "SHA1withRSA"
*/ 
public static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
  throws GeneralSecurityException, IOException
{
  PrivateKey privkey = pair.getPrivate();
  X509CertInfo info = new X509CertInfo();
  Date from = new Date();
  Date to = new Date(from.getTime() + days * 86400000l);
  CertificateValidity interval = new CertificateValidity(from, to);
  BigInteger sn = new BigInteger(64, new SecureRandom());
  X500Name owner = new X500Name(dn);
 
  info.set(X509CertInfo.VALIDITY, interval);
  info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
  //info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
  info.set(X509CertInfo.SUBJECT, owner);
  info.set(X509CertInfo.ISSUER, owner);
  info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
  info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
  AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
  info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
 
  // Sign the cert to identify the algorithm that's used.
  X509CertImpl cert = new X509CertImpl(info);
  cert.sign(privkey, algorithm);
 
  // Update the algorith, and resign.
  algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
  info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
  cert = new X509CertImpl(info);
  cert.sign(privkey, algorithm);
  return cert;
}
public static String generateToken(RSAPrivateKey privateKey) throws Exception
{
// Create RSA-signer with the private key
final JWSSigner signer = new RSASSASigner(privateKey);
// Prepare JWT with claims set
final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
    .subject("alice")
    .issuer("Rajakrishna Reddy")
    .claim("user", "Rajakrishna Reddy")
    .claim("email", "abc@xyz.com")
    .claim("tenantId", "123")
    .expirationTime(new Date(new Date().getTime() + 60 * 1000))
    .build();
final SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
signedJWT.sign(signer);
return signedJWT.serialize();
}
public static boolean isValidToken(String token, RSAPublicKey publicKey) throws Exception
{
return SignedJWT.parse(token).verify(new RSASSAVerifier(publicKey));
}
public static boolean isValidToken(String token, String publicKey) throws Exception
{
byte[] decoded = Base64.getDecoder().decode(publicKey);
    X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    RSAPublicKey generatePublic = (RSAPublicKey) kf.generatePublic(spec);
    BigInteger modulus = generatePublic.getModulus();
    BigInteger exponent = generatePublic.getPublicExponent();
    return SignedJWT.parse(token).verify(new RSASSAVerifier(new RSAPublicKeyImpl(modulus, exponent)));
//return SignedJWT.parse(token).verify(new RSASSAVerifier(publicKey));
}
public static void main(String[] args) throws Exception {
final String algorithmType = "RSA";
final String algorithm = "SHA256withRSA";
final String dn = "CN=Rajakrishna Reddy, OU=OU, O=varra, L=Hyderabad, ST=TL, C=IN";
final int days = 365;
final KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithmType);
keyGenerator.initialize(2048);
final KeyPair kp = keyGenerator.genKeyPair();
final X509Certificate certificate = generateCertificate(dn, kp, days, algorithm);
System.out.println("X09.Certificate: "+certificate);
//final String token = generateToken((RSAPrivateKey) kp.getPrivate());
final String token = "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1MjUyNDUyMDAsInN1YiI6IkpXVCIsInVzZXJfbWV0YWRhdGEiOiJ7XCJVc2VybmFtZVwiOlwibWNzYVwifSIsImlhdCI6MTUyNTE1ODgwMH0.wbroKZfrdGPGnk3OaPWbRr56rRzkg4DFO999jmSsut8IYAthKU0f26CIjWfrNPXD5asV74JYIS49VFNkFwbWfnIFETY1CaLIIm6F6NP5cFE7LW5G-y0qNRaCJgOLaFV4z4lsQOi0KAfuFVckiL5EHxhyBks-MCQEXMWO2JIBBZjAxhIH7fmhMHsYQQUxvm8Tx1dpnbvyh9E6x5F9BNZeS2DcBCqvzCuSUAz2DbgsJ-gVyrDRJgcItiCnscZy2u3sZq3XBTK2qBiSIpS4zVZupVS0f-5v57y7BvdVX2siuu-StN5614zvON_MJRgNLdo1yA1Y5F8eJ9IZrelMWB5GZw";
final String publiKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2hg1nqteEY12r5AO/enYD14aXEUaoqgvhtcHDwEPQwf9KqGpwoeC8jQE1qHfb2K1Wm/o4ug60Kv02f7AEJiNrUuKe9MYJdTr/DhekVrE0ttJkGCjLoNiVgMZHKH557Ouf6RsWJc5QjUiqxg6azwYUuHu2U199MZzFXvAVVUQR+hh8YqQM4KIQytOpj1JhxH7hQehth9vF5kIhA+K8htIIO04UF9+8ScrBHMQgj9q0RLperVQLxGsYT8cEZIn9tv1r47jynrTS0z/Vq2uVMGRg/bRPuo598++XUIglM92Ehbih87j//ATcHtsabefzBAVQuN4OaqLTT375JRAWpoWmQIDAQAB";
System.out.println("Token: "+token);
//System.out.println("Is valid?: "+isValidToken(token, (RSAPublicKey) kp.getPublic()));
System.out.println("Is valid?: "+isValidToken(token, publiKey));
//System.out.println(isValidToken(token, CertificateUtil.parseRSAPublicKey()));
}
}

No comments:

Post a Comment