From 8ade60873b1af720ccf12ff20c080a3e3cb571c5 Mon Sep 17 00:00:00 2001 From: Long Giang Date: Thu, 6 Jun 2024 15:43:05 +0700 Subject: [PATCH 1/3] feat: bump nimbus-jose-jwt to 9.39.1 --- pom.xml | 24 +++++-------------- .../java/org/mitre/jose/jwk/Launcher.java | 7 +++--- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index ebb09e9..fd71a5c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.mitre json-web-key-generator - 0.9-SNAPSHOT + 1.0.0-SNAPSHOT jar json-web-key-generator @@ -11,16 +11,9 @@ UTF-8 - 11 + 17 - - scm:git:https://github.com/mitreid-connect/json-web-key-generator.git - scm:git:git@github.com:mitreid-connect/json-web-key-generator.git - https://github.com/mitreid-connect/json-web-key-generator.git - HEAD - - org.sonatype.oss oss-parent @@ -91,7 +84,7 @@ com.nimbusds nimbus-jose-jwt - 8.19 + 9.39.1 commons-cli @@ -106,17 +99,12 @@ com.google.code.gson gson - 2.8.6 - - - org.bouncycastle - bcprov-jdk15on - 1.66 + 2.11.0 org.bouncycastle - bcpkix-jdk15on - 1.66 + bcpkix-jdk18on + 1.78.1 diff --git a/src/main/java/org/mitre/jose/jwk/Launcher.java b/src/main/java/org/mitre/jose/jwk/Launcher.java index f494b85..d82b029 100644 --- a/src/main/java/org/mitre/jose/jwk/Launcher.java +++ b/src/main/java/org/mitre/jose/jwk/Launcher.java @@ -58,6 +58,7 @@ import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jose.jwk.KeyType; import com.nimbusds.jose.jwk.KeyUse; +import com.nimbusds.jose.util.JSONObjectUtils; /** * Small Helper App to generate Json Web Keys @@ -407,8 +408,8 @@ private static void writeKeyToFile(boolean keySet, String outFile, String pubOut List jwkList = new ArrayList<>(existingKeys); jwkList.add(jwk); JWKSet jwkSet = new JWKSet(jwkList); - json = JsonParser.parseString(jwkSet.toJSONObject(false).toJSONString()); - pubJson = JsonParser.parseString(jwkSet.toJSONObject(true).toJSONString()); + json = JsonParser.parseString(JSONObjectUtils.toJSONString(jwkSet.toJSONObject(false))); + pubJson = JsonParser.parseString(JSONObjectUtils.toJSONString(jwkSet.toJSONObject(true))); } else { json = JsonParser.parseString(jwk.toJSONString()); pubJson = JsonParser.parseString(jwk.toPublicJWK().toJSONString()); @@ -427,7 +428,7 @@ private static void writeKeyToFile(boolean keySet, String outFile, String pubOut private static void printKey(boolean keySet, JWK jwk, Gson gson) { if (keySet) { JWKSet jwkSet = new JWKSet(jwk); - JsonElement json = JsonParser.parseString(jwkSet.toJSONObject(false).toJSONString()); + JsonElement json = JsonParser.parseString(JSONObjectUtils.toJSONString(jwkSet.toJSONObject(false))); System.out.println(gson.toJson(json)); } else { JsonElement json = JsonParser.parseString(jwk.toJSONString()); From cd93fa5245eade7a30f2a3befe8eee7dae8b5382 Mon Sep 17 00:00:00 2001 From: Long Giang Date: Thu, 6 Jun 2024 15:44:58 +0700 Subject: [PATCH 2/3] feat: makes KeyIdGenerator generates kid from thumbprint for SHA1 and SHA256 --- .../java/org/mitre/jose/jwk/ECKeyMaker.java | 15 +++++++- .../org/mitre/jose/jwk/KeyIdGenerator.java | 36 ++++++++++++------- .../java/org/mitre/jose/jwk/OKPKeyMaker.java | 10 +++++- .../mitre/jose/jwk/OctetSequenceKeyMaker.java | 9 ++++- .../java/org/mitre/jose/jwk/RSAKeyMaker.java | 14 +++++++- 5 files changed, 67 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/mitre/jose/jwk/ECKeyMaker.java b/src/main/java/org/mitre/jose/jwk/ECKeyMaker.java index 60d76de..6f289a0 100644 --- a/src/main/java/org/mitre/jose/jwk/ECKeyMaker.java +++ b/src/main/java/org/mitre/jose/jwk/ECKeyMaker.java @@ -10,11 +10,15 @@ import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.ECParameterSpec; +import java.util.LinkedHashMap; import com.nimbusds.jose.Algorithm; import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.ECKey; +import com.nimbusds.jose.jwk.JWKParameterNames; +import com.nimbusds.jose.jwk.KeyType; import com.nimbusds.jose.jwk.KeyUse; +import com.nimbusds.jose.util.Base64URL; /** * @author jricher @@ -41,9 +45,18 @@ public static ECKey make(Curve crv, KeyUse keyUse, Algorithm keyAlg, KeyIdGenera ECPublicKey pub = (ECPublicKey) kp.getPublic(); ECPrivateKey priv = (ECPrivateKey) kp.getPrivate(); + Base64URL x = ECKey.encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()); + Base64URL y = ECKey.encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()); + + LinkedHashMap requiredParams = new LinkedHashMap<>(); + requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString()); + requiredParams.put(JWKParameterNames.KEY_TYPE, KeyType.EC.getValue()); + requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString()); + requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString()); + ECKey ecKey = new ECKey.Builder(crv, pub) .privateKey(priv) - .keyID(kid.generate(keyUse, pub.getEncoded())) + .keyID(kid.generate(requiredParams)) .algorithm(keyAlg) .keyUse(keyUse) .build(); diff --git a/src/main/java/org/mitre/jose/jwk/KeyIdGenerator.java b/src/main/java/org/mitre/jose/jwk/KeyIdGenerator.java index e350e1b..695dbb2 100644 --- a/src/main/java/org/mitre/jose/jwk/KeyIdGenerator.java +++ b/src/main/java/org/mitre/jose/jwk/KeyIdGenerator.java @@ -3,13 +3,17 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.Map; import java.util.Optional; -import java.util.function.BiFunction; +import java.util.function.Function; import com.google.common.hash.Hashing; +import com.nimbusds.jose.jwk.JWKParameterNames; import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.util.Base64; import com.nimbusds.jose.util.Base64URL; +import com.nimbusds.jose.util.JSONObjectUtils; +import com.nimbusds.jose.util.StandardCharset; /** * @author jricher @@ -17,40 +21,46 @@ */ // KeyID generator functions public class KeyIdGenerator { - public static KeyIdGenerator TIMESTAMP = new KeyIdGenerator("timestamp", (use, pubKey) -> { + private static final String PUBLIC_KEY = "pub_key"; + + public static KeyIdGenerator TIMESTAMP = new KeyIdGenerator("timestamp", (params) -> { + KeyUse use = (KeyUse) params.get(JWKParameterNames.PUBLIC_KEY_USE); return Optional.ofNullable(use).map(KeyUse::getValue).map(s -> s + "-").orElse("") + Instant.now().getEpochSecond(); }); - public static KeyIdGenerator DATE = new KeyIdGenerator("date", (use, pubKey) -> { + public static KeyIdGenerator DATE = new KeyIdGenerator("date", (params) -> { + KeyUse use = (KeyUse) params.get(JWKParameterNames.PUBLIC_KEY_USE); return Optional.ofNullable(use).map(KeyUse::getValue).map(s -> s + "-").orElse("") + Instant.now().truncatedTo(ChronoUnit.SECONDS).toString(); }); - public static KeyIdGenerator SHA256 = new KeyIdGenerator("sha256", (use, pubKey) -> { - byte[] bytes = Hashing.sha256().hashBytes(pubKey).asBytes(); + public static KeyIdGenerator SHA256 = new KeyIdGenerator("sha256", (params) -> { + final String json = JSONObjectUtils.toJSONString(params); + byte[] bytes = Hashing.sha256().hashBytes(json.getBytes(StandardCharset.UTF_8)).asBytes(); return Base64URL.encode(bytes).toString(); }); - public static KeyIdGenerator SHA1 = new KeyIdGenerator("sha1", (use, pubKey) -> { - byte[] bytes = Hashing.sha1().hashBytes(pubKey).asBytes(); + public static KeyIdGenerator SHA1 = new KeyIdGenerator("sha1", (params) -> { + final String json = JSONObjectUtils.toJSONString(params); + byte[] bytes = Hashing.sha1().hashBytes(json.getBytes(StandardCharset.UTF_8)).asBytes(); return Base64.encode(bytes).toString(); }); - public static KeyIdGenerator NONE = new KeyIdGenerator("none", (use, pubKey) -> { + public static KeyIdGenerator NONE = new KeyIdGenerator("none", (params) -> { return null; }); private final String name; - private final BiFunction fn; + private final Function, String> fn; - public KeyIdGenerator(String name, BiFunction fn) { + public KeyIdGenerator(String name, Function, String> fn) { this.name = name; this.fn = fn; } - public String generate(KeyUse keyUse, byte[] pubKey) { - return this.fn.apply(keyUse, pubKey); + public String generate(final Map params) { + return this.fn.apply(params); } public String getName() { @@ -69,7 +79,7 @@ public static KeyIdGenerator get(String name) { } public static KeyIdGenerator specified(String kid) { - return new KeyIdGenerator(null, (u, p) -> kid); + return new KeyIdGenerator(null, (params) -> kid); } } diff --git a/src/main/java/org/mitre/jose/jwk/OKPKeyMaker.java b/src/main/java/org/mitre/jose/jwk/OKPKeyMaker.java index 6da0a1e..5e7f482 100644 --- a/src/main/java/org/mitre/jose/jwk/OKPKeyMaker.java +++ b/src/main/java/org/mitre/jose/jwk/OKPKeyMaker.java @@ -4,6 +4,7 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; +import java.util.LinkedHashMap; import org.bouncycastle.asn1.ASN1BitString; import org.bouncycastle.asn1.ASN1OctetString; @@ -12,6 +13,8 @@ import com.nimbusds.jose.Algorithm; import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.JWKParameterNames; +import com.nimbusds.jose.jwk.KeyType; import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.jwk.OctetKeyPair; import com.nimbusds.jose.util.Base64URL; @@ -84,12 +87,17 @@ public static JWK make(Curve keyCurve, KeyUse keyUse, Algorithm keyAlg, KeyIdGen d = ((ASN1OctetString)ASN1OctetString.fromByteArray(d)).getOctets(); } + LinkedHashMap requiredParams = new LinkedHashMap<>(); + requiredParams.put(JWKParameterNames.OKP_SUBTYPE, keyCurve.toString()); + requiredParams.put(JWKParameterNames.KEY_TYPE, KeyType.OKP.getValue()); + requiredParams.put(JWKParameterNames.OKP_PUBLIC_KEY, Base64URL.encode(x).toString()); + // Now that we have the raw numbers, export them as a JWK OctetKeyPair jwk = new OctetKeyPair.Builder(keyCurve, Base64URL.encode(x)) .d(Base64URL.encode(d)) .keyUse(keyUse) .algorithm(keyAlg) - .keyID(kid.generate(keyUse, x)) + .keyID(kid.generate(requiredParams)) .build(); return jwk; diff --git a/src/main/java/org/mitre/jose/jwk/OctetSequenceKeyMaker.java b/src/main/java/org/mitre/jose/jwk/OctetSequenceKeyMaker.java index 21ae42b..9e4197a 100644 --- a/src/main/java/org/mitre/jose/jwk/OctetSequenceKeyMaker.java +++ b/src/main/java/org/mitre/jose/jwk/OctetSequenceKeyMaker.java @@ -4,8 +4,11 @@ package org.mitre.jose.jwk; import java.security.SecureRandom; +import java.util.LinkedHashMap; import com.nimbusds.jose.Algorithm; +import com.nimbusds.jose.jwk.JWKParameterNames; +import com.nimbusds.jose.jwk.KeyType; import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.jwk.OctetSequenceKey; import com.nimbusds.jose.util.Base64URL; @@ -30,9 +33,13 @@ public static OctetSequenceKey make(Integer keySize, KeyUse use, Algorithm alg, Base64URL encoded = Base64URL.encode(bytes); + LinkedHashMap requiredParams = new LinkedHashMap<>(); + requiredParams.put(JWKParameterNames.OCT_KEY_VALUE, encoded.toString()); + requiredParams.put(JWKParameterNames.KEY_TYPE, KeyType.OCT.getValue()); + // make a key OctetSequenceKey octetSequenceKey = new OctetSequenceKey.Builder(encoded) - .keyID(kid.generate(use, bytes)) + .keyID(kid.generate(requiredParams)) .algorithm(alg) .keyUse(use) .build(); diff --git a/src/main/java/org/mitre/jose/jwk/RSAKeyMaker.java b/src/main/java/org/mitre/jose/jwk/RSAKeyMaker.java index ec24e62..d6728d4 100644 --- a/src/main/java/org/mitre/jose/jwk/RSAKeyMaker.java +++ b/src/main/java/org/mitre/jose/jwk/RSAKeyMaker.java @@ -8,10 +8,14 @@ import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPublicKey; +import java.util.LinkedHashMap; import com.nimbusds.jose.Algorithm; +import com.nimbusds.jose.jwk.JWKParameterNames; +import com.nimbusds.jose.jwk.KeyType; import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.jwk.RSAKey; +import com.nimbusds.jose.util.Base64URL; /** * @author jricher @@ -35,11 +39,19 @@ public static RSAKey make(Integer keySize, KeyUse keyUse, Algorithm keyAlg, KeyI RSAPublicKey pub = (RSAPublicKey) kp.getPublic(); RSAPrivateCrtKey priv = (RSAPrivateCrtKey) kp.getPrivate(); + Base64URL n = Base64URL.encode(pub.getModulus()); + Base64URL e = Base64URL.encode(pub.getPublicExponent()); + + LinkedHashMap requiredParams = new LinkedHashMap<>(); + requiredParams.put(JWKParameterNames.RSA_EXPONENT, e.toString()); + requiredParams.put(JWKParameterNames.KEY_TYPE, KeyType.RSA.getValue()); + requiredParams.put(JWKParameterNames.RSA_MODULUS, n.toString()); + RSAKey rsaKey = new RSAKey.Builder(pub) .privateKey(priv) .keyUse(keyUse) .algorithm(keyAlg) - .keyID(kid.generate(keyUse, pub.getEncoded())) + .keyID(kid.generate(requiredParams)) .build(); return rsaKey; From 209f68624c06186543f197c5a0d57d39c877fba1 Mon Sep 17 00:00:00 2001 From: Long Giang Date: Thu, 6 Jun 2024 15:45:21 +0700 Subject: [PATCH 3/3] feat: bump JDK from 11 to 17 --- Dockerfile | 8 ++++---- README.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index d7f5cb5..a373022 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,19 @@ # Get the builder image -FROM maven:3.8.6-openjdk-11 AS builder +FROM maven:3.9.7-eclipse-temurin-17 AS builder COPY . /build WORKDIR /build # Build the app -# Artifact will be stored at /build/target/json-web-key-generator-0.9-SNAPSHOT-jar-with-dependencies.jar +# Artifact will be stored at /build/target/json-web-key-generator-1.0.0-SNAPSHOT-jar-with-dependencies.jar RUN mvn package # Build the image with the new .jar binary # We need a jre 11+ starter container for this -FROM openjdk:11-jre-slim +FROM eclipse-temurin:17-jre-focal ARG GIT_COMMIT=unspecified ARG GIT_TAG=unspecified LABEL org.opencontainers.image.authors="Besmir Zanaj" LABEL org.opencontainers.image.revision=$GIT_COMMIT LABEL org.opencontainers.image.version="$GIT_TAG" -COPY --from=0 /build/target/json-web-key-generator-0.9-SNAPSHOT-jar-with-dependencies.jar ./json-web-key-generator.jar +COPY --from=0 /build/target/json-web-key-generator-1.0.0-SNAPSHOT-jar-with-dependencies.jar ./json-web-key-generator.jar ENTRYPOINT ["java", "-jar", "json-web-key-generator.jar"] diff --git a/README.md b/README.md index 4e6315e..ea3fd48 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ A commandline Java-based generator for JSON Web Keys (JWK) and JSON Private/Shar ## Standalone run -To compile, run `mvn package`. This will generate a `json-web-key-generator-0.9-SNAPSHOT-jar-with-dependencies.jar` in the `/target` directory. +To compile, run `mvn package`. This will generate a `json-web-key-generator-1.0.0-SNAPSHOT-jar-with-dependencies.jar` in the `/target` directory. -To generate a key, run `java -jar target/json-web-key-generator-0.9-SNAPSHOT-jar-with-dependencies.jar -t `. Several other arguments are defined which may be required depending on your key type: +To generate a key, run `java -jar target/json-web-key-generator-1.0.0-SNAPSHOT-jar-with-dependencies.jar -t `. Several other arguments are defined which may be required depending on your key type: ``` usage: java -jar json-web-key-generator.jar -t [options] @@ -41,7 +41,7 @@ usage: java -jar json-web-key-generator.jar -t [options] ## Docker -### Build with docker +### Build with docker Example: