Skip to content

Commit

Permalink
Take PublicKey instead of RSAPublicKey or ECPublicKey
Browse files Browse the repository at this point in the history
  • Loading branch information
robotdan committed Aug 25, 2021
1 parent 25c9597 commit 4ec7b6f
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 33 deletions.
8 changes: 8 additions & 0 deletions CHANGES
@@ -1,5 +1,13 @@
FusionAuth JWT Changes

Changes in 4.3.0

* Take PublicKey instead of RSAPublicKey or ECPublicKey on verifier methods and then validate the key to ensure the correct type.
* Support taking a PrivatKey object when building a signer in addition to a PEM.

Resolves https://github.com/FusionAuth/fusionauth-jwt/issues/35
Thanks to @tommed for the request.

Changes in 4.2.2

* Bump optional dep bc-fips to 1.0.2.1 (1.0.2+P1)
Expand Down
16 changes: 8 additions & 8 deletions README.md
Expand Up @@ -41,23 +41,23 @@ We are very interested in compensating anyone that can identify a security relat
<dependency>
<groupId>io.fusionauth</groupId>
<artifactId>fusionauth-jwt</artifactId>
<version>4.2.2</version>
<version>4.3.0</version>
</dependency>
```

### Gradle
```groovy
implementation 'io.fusionauth:fusionauth-jwt:4.2.2'
implementation 'io.fusionauth:fusionauth-jwt:4.3.0'
```

### Gradle Kotlin
```kotlin
implementation("io.fusionauth:fusionauth-jwt:4.2.2")
implementation("io.fusionauth:fusionauth-jwt:4.3.0")
```

### Savant
```groovy
dependency(id: "io.fusionauth:fusionauth-jwt:4.2.2")
dependency(id: "io.fusionauth:fusionauth-jwt:4.3.0")
```

For others see [https://search.maven.org](https://search.maven.org/artifact/io.fusionauth/fusionauth-jwt/4.0.1/jar).
Expand Down Expand Up @@ -104,7 +104,7 @@ assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");

#### Sign and encode a JWT using RSA
```java
// Build an RSA signer using a SHA-256 hash
// Build an RSA signer using a SHA-256 hash. A signer may also be built using the PrivateKey object.
Signer signer = RSASigner.newSHA256Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));

// Build a new JWT with an issuer(iss), issued at(iat), subject(sub) and expiration(exp)
Expand All @@ -128,7 +128,7 @@ Signer signer = RSASigner.newSHA512Signer(new String(Files.readAllBytes(Paths.ge

#### Verify and decode a JWT using RSA
```java
// Build an RSA verifier using an RSA Public Key
// Build an RSA verifier using an RSA Public Key. A verifier may also be built using the PublicKey object.
Verifier verifier = RSAVerifier.newVerifier(Paths.get("public_key.pem"));

// Verify and decode the encoded string JWT to a rich object
Expand All @@ -140,7 +140,7 @@ assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");

#### Sign and encode a JWT using EC
```java
// Build an EC signer using a SHA-256 hash
// Build an EC signer using a SHA-256 hash. A signer may also be built using the PrivateKey object.
Signer signer = ECSigner.newSHA256Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));

// Build a new JWT with an issuer(iss), issued at(iat), subject(sub) and expiration(exp)
Expand All @@ -164,7 +164,7 @@ Signer signer = ECSigner.newSHA512Signer(new String(Files.readAllBytes(Paths.get

#### Verify and decode a JWT using EC
```java
// Build an EC verifier using an EC Public Key
// Build an EC verifier using an EC Public Key. A verifier may also be built using the PublicKey object.
Verifier verifier = ECVerifier.newVerifier(Paths.get("public_key.pem"));

// Verify and decode the encoded string JWT to a rich object
Expand Down
20 changes: 11 additions & 9 deletions src/main/java/io/fusionauth/jwt/ec/ECVerifier.java
Expand Up @@ -31,6 +31,7 @@
import java.nio.file.Path;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.ECPublicKey;
Expand All @@ -44,12 +45,15 @@ public class ECVerifier implements Verifier {

private final CryptoProvider cryptoProvider;

private ECVerifier(ECPublicKey publicKey, CryptoProvider cryptoProvider) {
private ECVerifier(PublicKey publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
Objects.requireNonNull(cryptoProvider);

this.cryptoProvider = cryptoProvider;
this.publicKey = publicKey;
if (!(publicKey instanceof ECPublicKey)) {
throw new InvalidKeyTypeException("Expecting a public key of type [ECPublicKey], but found [" + publicKey.getClass().getSimpleName() + "].");
}
this.publicKey = (ECPublicKey) publicKey;
}

private ECVerifier(String publicKey, CryptoProvider cryptoProvider) {
Expand All @@ -63,7 +67,7 @@ private ECVerifier(String publicKey, CryptoProvider cryptoProvider) {
}

if (!(pem.publicKey instanceof ECPublicKey)) {
throw new InvalidKeyTypeException("Expecting an EC public key, but found " + pem.publicKey.getAlgorithm() + " / " + pem.publicKey.getFormat() + "");
throw new InvalidKeyTypeException("Expecting a public key of type [ECPublicKey], but found [" + pem.publicKey.getClass().getSimpleName() + "].");
}

this.publicKey = pem.getPublicKey();
Expand All @@ -76,7 +80,7 @@ private ECVerifier(String publicKey, CryptoProvider cryptoProvider) {
* @return a new instance of the EC verifier.
*/
public static ECVerifier newVerifier(String publicKey) {
return newVerifier(publicKey, new DefaultCryptoProvider());
return new ECVerifier(publicKey, new DefaultCryptoProvider());
}

/**
Expand All @@ -85,8 +89,8 @@ public static ECVerifier newVerifier(String publicKey) {
* @param publicKey The EC public key object.
* @return a new instance of the EC verifier.
*/
public static ECVerifier newVerifier(ECPublicKey publicKey) {
return newVerifier(publicKey, new DefaultCryptoProvider());
public static ECVerifier newVerifier(PublicKey publicKey) {
return new ECVerifier(publicKey, new DefaultCryptoProvider());
}

/**
Expand Down Expand Up @@ -118,7 +122,6 @@ public static ECVerifier newVerifier(byte[] bytes) {
* @return a new instance of the EC verifier.
*/
public static ECVerifier newVerifier(String publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
return new ECVerifier(publicKey, cryptoProvider);
}

Expand All @@ -129,8 +132,7 @@ public static ECVerifier newVerifier(String publicKey, CryptoProvider cryptoProv
* @param cryptoProvider The crypto provider used to get the ECDSA Signature algorithm.
* @return a new instance of the EC verifier.
*/
public static ECVerifier newVerifier(ECPublicKey publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
public static ECVerifier newVerifier(PublicKey publicKey, CryptoProvider cryptoProvider) {
return new ECVerifier(publicKey, cryptoProvider);
}

Expand Down
22 changes: 14 additions & 8 deletions src/main/java/io/fusionauth/jwt/rsa/RSAPSSVerifier.java
Expand Up @@ -18,6 +18,7 @@

import io.fusionauth.jwt.InvalidJWTSignatureException;
import io.fusionauth.jwt.InvalidKeyLengthException;
import io.fusionauth.jwt.InvalidKeyTypeException;
import io.fusionauth.jwt.JWTVerifierException;
import io.fusionauth.jwt.MissingPublicKeyException;
import io.fusionauth.jwt.Verifier;
Expand All @@ -32,6 +33,7 @@
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;
Expand All @@ -49,12 +51,15 @@ public class RSAPSSVerifier implements Verifier {

private final CryptoProvider cryptoProvider;

private RSAPSSVerifier(RSAPublicKey publicKey, CryptoProvider cryptoProvider) {
private RSAPSSVerifier(PublicKey publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
Objects.requireNonNull(cryptoProvider);

this.cryptoProvider = cryptoProvider;
this.publicKey = publicKey;
if (!(publicKey instanceof RSAPublicKey)) {
throw new InvalidKeyTypeException("Expecting a public key of type [RSAPublicKey], but found [" + publicKey.getClass().getSimpleName() + "].");
}
this.publicKey = (RSAPublicKey) publicKey;
assertValidKeyLength();
}

Expand All @@ -67,6 +72,9 @@ private RSAPSSVerifier(String publicKey, CryptoProvider cryptoProvider) {
if (pem.publicKey == null) {
throw new MissingPublicKeyException("The provided PEM encoded string did not contain a public key.");
}
if (!(pem.publicKey instanceof RSAPublicKey)) {
throw new InvalidKeyTypeException("Expecting a public key of type [RSAPublicKey], but found [" + pem.publicKey.getClass().getSimpleName() + "].");
}

this.publicKey = pem.getPublicKey();
assertValidKeyLength();
Expand All @@ -78,8 +86,8 @@ private RSAPSSVerifier(String publicKey, CryptoProvider cryptoProvider) {
* @param publicKey The RSA public key object.
* @return a new instance of the RSA verifier.
*/
public static RSAPSSVerifier newVerifier(RSAPublicKey publicKey) {
return newVerifier(publicKey, new DefaultCryptoProvider());
public static RSAPSSVerifier newVerifier(PublicKey publicKey) {
return new RSAPSSVerifier(publicKey, new DefaultCryptoProvider());
}

/**
Expand All @@ -89,8 +97,7 @@ public static RSAPSSVerifier newVerifier(RSAPublicKey publicKey) {
* @param cryptoProvider The crypto provider used to get the RSA signature Algorithm.
* @return a new instance of the RSA verifier.
*/
public static RSAPSSVerifier newVerifier(RSAPublicKey publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
public static RSAPSSVerifier newVerifier(PublicKey publicKey, CryptoProvider cryptoProvider) {
return new RSAPSSVerifier(publicKey, cryptoProvider);
}

Expand All @@ -101,7 +108,7 @@ public static RSAPSSVerifier newVerifier(RSAPublicKey publicKey, CryptoProvider
* @return a new instance of the RSA verifier.
*/
public static RSAPSSVerifier newVerifier(String publicKey) {
return newVerifier(publicKey, new DefaultCryptoProvider());
return new RSAPSSVerifier(publicKey, new DefaultCryptoProvider());
}

/**
Expand All @@ -112,7 +119,6 @@ public static RSAPSSVerifier newVerifier(String publicKey) {
* @return a new instance of the RSA verifier.
*/
public static RSAPSSVerifier newVerifier(String publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
return new RSAPSSVerifier(publicKey, cryptoProvider);
}

Expand Down
22 changes: 14 additions & 8 deletions src/main/java/io/fusionauth/jwt/rsa/RSAVerifier.java
Expand Up @@ -18,6 +18,7 @@

import io.fusionauth.jwt.InvalidJWTSignatureException;
import io.fusionauth.jwt.InvalidKeyLengthException;
import io.fusionauth.jwt.InvalidKeyTypeException;
import io.fusionauth.jwt.JWTVerifierException;
import io.fusionauth.jwt.MissingPublicKeyException;
import io.fusionauth.jwt.Verifier;
Expand All @@ -31,6 +32,7 @@
import java.nio.file.Path;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;
Expand All @@ -46,12 +48,15 @@ public class RSAVerifier implements Verifier {

private final CryptoProvider cryptoProvider;

private RSAVerifier(RSAPublicKey publicKey, CryptoProvider cryptoProvider) {
private RSAVerifier(PublicKey publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
Objects.requireNonNull(cryptoProvider);

this.cryptoProvider = cryptoProvider;
this.publicKey = publicKey;
if (!(publicKey instanceof RSAPublicKey)) {
throw new InvalidKeyTypeException("Expecting a public key of type [RSAPublicKey], but found [" + publicKey.getClass().getSimpleName() + "].");
}
this.publicKey = (RSAPublicKey) publicKey;
assertValidKeyLength();
}

Expand All @@ -64,6 +69,9 @@ private RSAVerifier(String publicKey, CryptoProvider cryptoProvider) {
if (pem.publicKey == null) {
throw new MissingPublicKeyException("The provided PEM encoded string did not contain a public key.");
}
if (!(pem.publicKey instanceof RSAPublicKey)) {
throw new InvalidKeyTypeException("Expecting a public key of type [RSAPublicKey], but found [" + pem.publicKey.getClass().getSimpleName() + "].");
}

this.publicKey = pem.getPublicKey();
assertValidKeyLength();
Expand All @@ -75,8 +83,8 @@ private RSAVerifier(String publicKey, CryptoProvider cryptoProvider) {
* @param publicKey The RSA public key object.
* @return a new instance of the RSA verifier.
*/
public static RSAVerifier newVerifier(RSAPublicKey publicKey) {
return newVerifier(publicKey, new DefaultCryptoProvider());
public static RSAVerifier newVerifier(PublicKey publicKey) {
return new RSAVerifier(publicKey, new DefaultCryptoProvider());
}

/**
Expand All @@ -86,8 +94,7 @@ public static RSAVerifier newVerifier(RSAPublicKey publicKey) {
* @param cryptoProvider The crypto provider used to get the RSA signature Algorithm.
* @return a new instance of the RSA verifier.
*/
public static RSAVerifier newVerifier(RSAPublicKey publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
public static RSAVerifier newVerifier(PublicKey publicKey, CryptoProvider cryptoProvider) {
return new RSAVerifier(publicKey, cryptoProvider);
}

Expand All @@ -98,7 +105,7 @@ public static RSAVerifier newVerifier(RSAPublicKey publicKey, CryptoProvider cry
* @return a new instance of the RSA verifier.
*/
public static RSAVerifier newVerifier(String publicKey) {
return newVerifier(publicKey, new DefaultCryptoProvider());
return new RSAVerifier(publicKey, new DefaultCryptoProvider());
}

/**
Expand All @@ -109,7 +116,6 @@ public static RSAVerifier newVerifier(String publicKey) {
* @return a new instance of the RSA verifier.
*/
public static RSAVerifier newVerifier(String publicKey, CryptoProvider cryptoProvider) {
Objects.requireNonNull(publicKey);
return new RSAVerifier(publicKey, cryptoProvider);
}

Expand Down

0 comments on commit 4ec7b6f

Please sign in to comment.