Skip to content

Commit

Permalink
Merge pull request #5 from longgt/feature/1.2.0
Browse files Browse the repository at this point in the history
Feature/1.2.0
  • Loading branch information
longgt authored Jun 7, 2024
2 parents 6cab8fe + aedf5c8 commit 0f67ad7
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 37 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,23 @@ To generate a key, run `java -jar target/json-web-key-generator-1.1.0-SNAPSHOT-j
```
usage: java -jar json-web-key-generator.jar -t <keyType> [options]
-t,--type <arg> Key Type, one of: RSA, oct, EC, OKP
(case-insensitive)
-s,--size <arg> Key Size in bits, required for RSA and oct key
types. Must be an integer divisible by 8
types. Must be an integer divisible by 8. If
omitted, defaults to 2048 for RSA, 2048 for oct
-c,--curve <arg> Key Curve, required for EC or OKP key type.
Must be one of P-256, secp256k1, P-384, P-521
for EC keys or one of Ed25519, Ed448, X25519,
X448 for OKP keys.
X448 for OKP keys. If omitted, defaults to
P-256 for EC, Ed25519 for OKP
-u,--usage <arg> Usage, one of: enc, sig (optional)
-a,--algorithm <arg> Algorithm (optional)
-i,--id <arg> Key ID (optional), one will be generated if not
defined
-g,--idGenerator <arg> Key ID generation method (optional). Can be one
of: date, timestamp, sha256, sha384, sha512, uuid, none. If
omitted, generator method defaults to
'timestamp'.
of: date, timestamp, sha256, sha384, sha512,
uuid, none. If omitted, generator method
defaults to 'timestamp'.
-I,--noGenerateId <deprecated> Don't generate a Key ID.
(Deprecated, use '-g none' instead.)
-p,--showPubKey Display public key separately (if applicable)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.mitre</groupId>
<artifactId>json-web-key-generator</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>1.2.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>json-web-key-generator</name>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/mitre/jose/jwk/ECKeyMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*/
public class ECKeyMaker {

public static final Curve DEFAULT_CURVE = Curve.P_256;

/**
* @param crv
* @param keyUse
Expand Down
73 changes: 42 additions & 31 deletions src/main/java/org/mitre/jose/jwk/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.KeyType;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.util.JSONObjectUtils;

/**
Expand Down Expand Up @@ -124,7 +126,7 @@ public static void main(String[] args) {

// parse out the important bits

KeyType keyType = KeyType.parse(kty);
KeyType keyType = parseKeyType(kty);

KeyUse keyUse = validateKeyUse(use);

Expand All @@ -151,10 +153,13 @@ private static void configureCommandLineOptions(Options options) {
options.addOption("t", "type", true, "Key Type, one of: " +
keyTypes.stream()
.map(KeyType::getValue)
.collect(Collectors.joining(", ")));
.collect(Collectors.joining(", "))
+ " (case-insensitive)");

options.addOption("s", "size", true,
"Key Size in bits, required for " + KeyType.RSA.getValue() + " and " + KeyType.OCT.getValue() + " key types. Must be an integer divisible by 8");
"Key Size in bits, required for " + KeyType.RSA.getValue() + " and " + KeyType.OCT.getValue() + " key types. "
+ "Must be an integer divisible by 8. " + "If omitted, defaults to " + RSAKeyMaker.DEFAULT_KEY_SIZE + " for "
+ KeyType.RSA + ", " + OctetSequenceKeyMaker.DEFAULT_KEY_SIZE + " for " + KeyType.OCT);
options.addOption("c", "curve", true,
"Key Curve, required for " + KeyType.EC.getValue() + " or " + KeyType.OKP.getValue() + " key type. Must be one of "
+ ecCurves.stream()
Expand All @@ -164,7 +169,8 @@ private static void configureCommandLineOptions(Options options) {
+ okpCurves.stream()
.map(Curve::getName)
.collect(Collectors.joining(", "))
+ " for OKP keys.");
+ " for OKP keys. " + "If omitted, defaults to " + ECKeyMaker.DEFAULT_CURVE + " for " + KeyType.EC + ", "
+ OKPKeyMaker.DEFAULT_CURVE + " for " + KeyType.OKP);

options.addOption("u", "usage", true, "Usage, one of: enc, sig (optional)");
options.addOption("a", "algorithm", true, "Algorithm (optional)");
Expand Down Expand Up @@ -200,69 +206,65 @@ private static KeyUse validateKeyUse(String use) {
}
}

private static JWK makeKey(String size, KeyIdGenerator kid, String crv, KeyType keyType, KeyUse keyUse, Algorithm keyAlg) {
private static JWK makeKey(String size, KeyIdGenerator kid, String crv, KeyType keyType, KeyUse keyUse, Algorithm keyAlg) {
JWK jwk;
if (keyType.equals(KeyType.RSA)) {
jwk = makeRsaKey(kid, size, keyType, keyUse, keyAlg);
jwk = makeRsaKey(kid, size, keyUse, keyAlg);
} else if (keyType.equals(KeyType.OCT)) {
jwk = makeOctKey(kid, size, keyType, keyUse, keyAlg);
jwk = makeOctKey(kid, size, keyUse, keyAlg);
} else if (keyType.equals(KeyType.EC)) {
jwk = makeEcKey(kid, crv, keyType, keyUse, keyAlg);
jwk = makeEcKey(kid, crv, keyUse, keyAlg);
} else if (keyType.equals(KeyType.OKP)) {
jwk = makeOkpKey(kid, crv, keyType, keyUse, keyAlg);
jwk = makeOkpKey(kid, crv, keyUse, keyAlg);
} else {
throw printUsageAndExit("Unknown key type: " + keyType);
}
return jwk;
}

private static JWK makeOkpKey(KeyIdGenerator kid, String crv, KeyType keyType, KeyUse keyUse, Algorithm keyAlg) {
if (Strings.isNullOrEmpty(crv)) {
throw printUsageAndExit("Curve is required for key type " + keyType);
}
Curve keyCurve = Curve.parse(crv);
private static JWK makeOkpKey(KeyIdGenerator kid, String crv, KeyUse keyUse, Algorithm keyAlg) {
Curve keyCurve = Strings.isNullOrEmpty(crv) ? OKPKeyMaker.DEFAULT_CURVE : Curve.parse(crv);

if (!okpCurves.contains(keyCurve)) {
throw printUsageAndExit("Curve " + crv + " is not valid for key type " + keyType);
throw printUsageAndExit("Curve " + crv + " is not valid for key type " + KeyType.OKP);
}

return OKPKeyMaker.make(keyCurve, keyUse, keyAlg, kid);
}

private static JWK makeEcKey(KeyIdGenerator kid, String crv, KeyType keyType, KeyUse keyUse, Algorithm keyAlg) {
if (Strings.isNullOrEmpty(crv)) {
throw printUsageAndExit("Curve is required for key type " + keyType);
}
Curve keyCurve = Curve.parse(crv);
private static JWK makeEcKey(KeyIdGenerator kid, String crv, KeyUse keyUse, Algorithm keyAlg) {
Curve keyCurve = Strings.isNullOrEmpty(crv) ? ECKeyMaker.DEFAULT_CURVE : Curve.parse(crv);

if (!ecCurves.contains(keyCurve)) {
throw printUsageAndExit("Curve " + crv + " is not valid for key type " + keyType);
throw printUsageAndExit("Curve " + crv + " is not valid for key type " + KeyType.EC);
}

return ECKeyMaker.make(keyCurve, keyUse, keyAlg, kid);
}

private static JWK makeOctKey(KeyIdGenerator kid, String size, KeyType keyType, KeyUse keyUse, Algorithm keyAlg) {
if (Strings.isNullOrEmpty(size)) {
throw printUsageAndExit("Key size (in bits) is required for key type " + keyType);
private static OctetSequenceKey makeOctKey(KeyIdGenerator kid, String size, KeyUse keyUse, Algorithm keyAlg) {
String keySizeValue = size;
if (Strings.isNullOrEmpty(keySizeValue)) {
keySizeValue = OctetSequenceKeyMaker.DEFAULT_KEY_SIZE;
}

// surrounding try/catch catches numberformatexception from this
Integer keySize = Integer.decode(size);
// surrounding try/catch catches NumberFormatException from this
Integer keySize = Integer.decode(keySizeValue);
if (keySize % 8 != 0) {
throw printUsageAndExit("Key size (in bits) must be divisible by 8, got " + keySize);
}

return OctetSequenceKeyMaker.make(keySize, keyUse, keyAlg, kid);
}

private static JWK makeRsaKey(KeyIdGenerator kid, String size, KeyType keyType, KeyUse keyUse, Algorithm keyAlg) {
if (Strings.isNullOrEmpty(size)) {
throw printUsageAndExit("Key size (in bits) is required for key type " + keyType);
private static RSAKey makeRsaKey(KeyIdGenerator kid, String size, KeyUse keyUse, Algorithm keyAlg) {
String keySizeValue = size;
if (Strings.isNullOrEmpty(keySizeValue)) {
keySizeValue = RSAKeyMaker.DEFAULT_KEY_SIZE;
}

// surrounding try/catch catches numberformatexception from this
Integer keySize = Integer.decode(size);
// surrounding try/catch catches NumberFormatException from this
Integer keySize = Integer.decode(keySizeValue);
if (keySize % 8 != 0) {
throw printUsageAndExit("Key size (in bits) must be divisible by 8, got " + keySize);
}
Expand Down Expand Up @@ -464,4 +466,13 @@ private static IllegalArgumentException printUsageAndExit(String message) {
System.exit(1);
return new IllegalArgumentException("Program was called with invalid arguments");
}

private static KeyType parseKeyType(String kty) {
for (KeyType kt : keyTypes) {
if (kt.getValue().equalsIgnoreCase(kty)) {
return kt;
}
}
return new KeyType(kty, null);
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/mitre/jose/jwk/OKPKeyMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*/
public class OKPKeyMaker {

public static final Curve DEFAULT_CURVE = Curve.Ed25519;

/**
* @param keyCurve
* @param keyUse
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/mitre/jose/jwk/OctetSequenceKeyMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
public class OctetSequenceKeyMaker {

public static final String DEFAULT_KEY_SIZE = "2048";

/**
* @param keySize in bits
* @return
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/mitre/jose/jwk/RSAKeyMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
*/
public class RSAKeyMaker {

public static final String DEFAULT_KEY_SIZE = "2048";

/**
* @param keySize
* @param keyUse
Expand Down

0 comments on commit 0f67ad7

Please sign in to comment.