Skip to content

Commit

Permalink
fixes networknt#2056 add KeyUtil and test cases for JWT and JWK (netw…
Browse files Browse the repository at this point in the history
  • Loading branch information
stevehu authored Dec 18, 2023
1 parent 747243c commit 834c4c3
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
public class JwtIssuer {
private static final Logger logger = LoggerFactory.getLogger(JwtIssuer.class);
public static final String JWT_CONFIG = "jwt";
private static JwtConfig jwtConfig = (JwtConfig) Config.getInstance().getJsonObjectConfig(JWT_CONFIG, JwtConfig.class);
private static final JwtConfig jwtConfig = (JwtConfig) Config.getInstance().getJsonObjectConfig(JWT_CONFIG, JwtConfig.class);

/**
* A static method that generate JWT token from JWT claims object
Expand Down
83 changes: 83 additions & 0 deletions security/src/main/java/com/networknt/security/KeyUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.networknt.security;

import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwk.PublicJsonWebKey;
import org.jose4j.lang.JoseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

/**
* This is a utility class that is used to serialize and deserialize keys and jwks.
*
* @author Steve Hu
*/
public class KeyUtil {
public static final Logger logger = LoggerFactory.getLogger(KeyUtil.class);
public static KeyPair generateKeyPair(String algorithm, int keySize) throws Exception {
// Generate a key pair
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
}
public static String serializePublicKey(PublicKey publicKey) throws Exception {
// Serialize the public key
byte[] publicKeyBytes = publicKey.getEncoded();
return Base64.getEncoder().encodeToString(publicKeyBytes);
}

public static String serializePrivateKey(PrivateKey privateKey) throws Exception {
// Serialize the private key
byte[] privateKeyBytes = privateKey.getEncoded();
return Base64.getEncoder().encodeToString(privateKeyBytes);
}

public static PrivateKey deserializePrivateKey(String serializedPrivateKey, String algorithm) throws Exception {
// Deserialize the private key
byte[] decodedPrivateKeyBytes = Base64.getDecoder().decode(serializedPrivateKey);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decodedPrivateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePrivate(privateKeySpec);
}

public static PublicKey deserializePublicKey(String serializedPublicKey, String algorithm) throws Exception {
// Deserialize the public key
byte[] decodedPublicKeyBytes = Base64.getDecoder().decode(serializedPublicKey);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decodedPublicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePublic(publicKeySpec);
}

public static String generateJwk(PublicKey longKey, String longKeyId, PublicKey currKey, String currKeyId, PublicKey prevKey, String prevKeyId) {
List<JsonWebKey> jwkList = new ArrayList<>();
try {
// Create a JWK object from the long live public key
PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(longKey);
jwk.setKeyId(longKeyId);
jwkList.add(jwk);
// Create a JWK object from the current public key
jwk = PublicJsonWebKey.Factory.newPublicJwk(currKey);
jwk.setKeyId(currKeyId);
jwkList.add(jwk);
// Create a JWK object from the previous public key
if(prevKey != null && prevKeyId != null) {
jwk = PublicJsonWebKey.Factory.newPublicJwk(prevKey);
jwk.setKeyId(prevKeyId);
jwkList.add(jwk);
}
} catch (JoseException e) {
logger.error("Exception:", e);
}
// create a JsonWebKeySet object with the list of JWK objects
JsonWebKeySet jwks = new JsonWebKeySet(jwkList);
// and output the JSON of the JWKS
return jwks.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);
}
}
53 changes: 53 additions & 0 deletions security/src/test/java/com/networknt/security/KeyUtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.networknt.security;

import com.networknt.utility.HashUtil;
import org.junit.Test;

import java.security.KeyPair;

public class KeyUtilTest {
@Test
public void testSerializePublicKey() throws Exception {
KeyPair keyPair = KeyUtil.generateKeyPair("RSA", 2048);
System.out.println("public key = " + KeyUtil.serializePublicKey(keyPair.getPublic()));
System.out.println("private key = " + KeyUtil.serializePrivateKey(keyPair.getPrivate()));
}

@Test
public void testDeserializeKey() throws Exception {
KeyPair keyPair = KeyUtil.generateKeyPair("RSA", 2048);
String publicKey = KeyUtil.serializePublicKey(keyPair.getPublic());
String privateKey = KeyUtil.serializePrivateKey(keyPair.getPrivate());
System.out.println("public key = " + publicKey);
System.out.println("private key = " + privateKey);
KeyUtil.deserializePrivateKey(privateKey, "RSA");
KeyUtil.deserializePublicKey(publicKey, "RSA");
}

/**
* This is the method to generate a JWK and keys for the database population per environment.
*
* @throws Exception exception
*/
@Test
public void testGenerateJwk() throws Exception {
KeyPair longKeyPair = KeyUtil.generateKeyPair("RSA", 2048);
String longKeyId = HashUtil.generateUUID();
System.out.println("longKeyId = " + longKeyId);
String publicKey = KeyUtil.serializePublicKey(longKeyPair.getPublic());
System.out.println("long public key = " + publicKey);
String privateKey = KeyUtil.serializePrivateKey(longKeyPair.getPrivate());
System.out.println("long private key = " + privateKey);

KeyPair currKeyPair = KeyUtil.generateKeyPair("RSA", 2048);
String currKeyId = HashUtil.generateUUID();
System.out.println("currKeyId = " + currKeyId);
publicKey = KeyUtil.serializePublicKey(currKeyPair.getPublic());
System.out.println("curr public key = " + publicKey);
privateKey = KeyUtil.serializePrivateKey(currKeyPair.getPrivate());
System.out.println("curr private key = " + privateKey);

String jwk = KeyUtil.generateJwk(longKeyPair.getPublic(), longKeyId, currKeyPair.getPublic(), currKeyId, null, null);
System.out.println("jwk = " + jwk);
}
}

0 comments on commit 834c4c3

Please sign in to comment.