Skip to content

Commit

Permalink
Code cleanup, and add support for modular crypto providers. This allo…
Browse files Browse the repository at this point in the history
…ws for different JCE security providers such as BC or BC Fips if you require FIPS ready.
  • Loading branch information
robotdan committed Apr 1, 2020
1 parent 629c6f3 commit d2d775d
Show file tree
Hide file tree
Showing 32 changed files with 805 additions and 177 deletions.
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -10,6 +10,7 @@ We are very interested in compensating anyone that can identify a security relat
## Features
- JWT signing using HMAC, RSA and Elliptic Curve support
- `HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`
- Modular crypto provider so you can drop in support for BC FIPS or other Java JCE security providers.
- PEM decoding / encoding
- Decode PEM files to PrivateKey or PublicKey
- Decode private EC keys un-encapsulated in PKCS#8, returned PEM will be in PKCS#8 form.
Expand Down Expand Up @@ -166,6 +167,18 @@ JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);
assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");
```

### Build a Signer, or a Verifier using a provided CryptoProvider

This pattern is available on the HMAC, RSA and EC verifier and signers.

```java
// Build and EC signer using a BC Fips ready Crypto Provider
Signer signer = ECSigner.newSHA256Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))), new BCFIPSCryptoProvider());

// Build an EC verifier using a BC Fips ready Crypto Provider
Verifier verifier = ECVerifier.newVerifier(Paths.get("public_key.pem"), new BCFIPSCryptoProvider());
```

## JSON Web Keys

### Convert a Public Key to JWK
Expand Down
6 changes: 3 additions & 3 deletions build.savant
Expand Up @@ -15,7 +15,7 @@
*/

savantVersion = "1.0.0"
jacksonVersion = "2.10.1"
jacksonVersion = "2.10.3"

project(group: "io.fusionauth", name: "fusionauth-jwt", version: "3.1.7", licenses: ["ApacheV2_0"]) {

Expand All @@ -34,6 +34,7 @@ project(group: "io.fusionauth", name: "fusionauth-jwt", version: "3.1.7", licens
dependency(id: "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}")
}
group(name: "test-compile", export: false) {
dependency(id: "org.bouncycastle:bc-fips:1.0.1")
dependency(id: "org.testng:testng:6.8.7")
}
}
Expand All @@ -47,9 +48,8 @@ project(group: "io.fusionauth", name: "fusionauth-jwt", version: "3.1.7", licens
* Define Plugins
*/
dependency = loadPlugin(id: "org.savantbuild.plugin:dependency:1.0.2")
file = loadPlugin(id: "org.savantbuild.plugin:file:1.0.2")
java = loadPlugin(id: "org.savantbuild.plugin:java:1.0.2")
javaTestNG = loadPlugin(id: "org.savantbuild.plugin:java-testng:1.0.2")
javaTestNG = loadPlugin(id: "org.savantbuild.plugin:java-testng:1.0.5")
groovy = loadPlugin(id: "org.savantbuild.plugin:groovy:${savantVersion}")
idea = loadPlugin(id: "org.savantbuild.plugin:idea:${savantVersion}")
release = loadPlugin(id: "org.savantbuild.plugin:release-git:${savantVersion}")
Expand Down
23 changes: 17 additions & 6 deletions fusionauth-jwt.iml
Expand Up @@ -16,33 +16,44 @@
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.10.3/jackson-databind-2.10.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1-src.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.10.3/jackson-databind-2.10.3-src.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.10.3/jackson-annotations-2.10.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1-src.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.10.3/jackson-annotations-2.10.3-src.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.10.3/jackson-core-2.10.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1-src.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.10.3/jackson-core-2.10.3-src.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$USER_HOME$/.savant/cache/org/bouncycastle/bc-fips/1.0.1/bc-fips-1.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/org/bouncycastle/bc-fips/1.0.1/bc-fips-1.0.1-src.jar!/" />
</SOURCES>
</library>
</orderEntry>
Expand Down
17 changes: 13 additions & 4 deletions pom.xml
Expand Up @@ -6,7 +6,7 @@

<groupId>io.fusionauth</groupId>
<artifactId>fusionauth-jwt</artifactId>
<version>3.1.6</version>
<version>3.1.7</version>
<packaging>jar</packaging>

<name>FusionAuth JWT</name>
Expand Down Expand Up @@ -61,25 +61,34 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.1</version>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.1</version>
<version>2.10.3</version>
</dependency>

<!-- Testing Dependencies -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.7</version>
<scope>test</scope>
</dependency>

<!-- Used to test alternate Security Provider for FIPS ready -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
1 change: 1 addition & 0 deletions src/main/java/io/fusionauth/der/DerDecodingException.java
Expand Up @@ -22,6 +22,7 @@
* @author Daniel DeGroff
*/
public class DerDecodingException extends IOException {
@SuppressWarnings("unused")
public DerDecodingException(String message, Throwable cause) {
super(message, cause);
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/io/fusionauth/der/DerEncodingException.java
Expand Up @@ -22,6 +22,7 @@
* @author Daniel DeGroff
*/
public class DerEncodingException extends IOException {
@SuppressWarnings("unused")
public DerEncodingException(String message, Throwable cause) {
super(message, cause);
}
Expand All @@ -30,6 +31,7 @@ public DerEncodingException(Throwable cause) {
super(cause);
}

@SuppressWarnings("unused")
public DerEncodingException(String message) {
super(message);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/fusionauth/der/DerOutputStream.java
Expand Up @@ -23,7 +23,7 @@
* @author Daniel DeGroff
*/
public class DerOutputStream {
private ByteArrayOutputStream os;
private final ByteArrayOutputStream os;

public DerOutputStream() {
os = new ByteArrayOutputStream();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/io/fusionauth/der/DerValue.java
Expand Up @@ -25,9 +25,9 @@
* @author Daniel DeGroff
*/
public class DerValue {
public Tag tag;
private final DerInputStream value;

private DerInputStream value;
public Tag tag;

public DerValue(Tag tag, byte[] value) {
this.tag = tag;
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/io/fusionauth/jwks/JSONWebKeyBuilder.java
Expand Up @@ -234,13 +234,12 @@ private KeyType getKeyType(Key key) {

private String readCurveObjectIdentifier(Key key) {
try {
DerValue[] sequence = new DerInputStream(key.getEncoded()).getSequence();
if (key instanceof PrivateKey) {
DerValue[] sequence = new DerInputStream(key.getEncoded()).getSequence();
// Read the first value in the sequence, it is the algorithm OID, the second wil be the curve
sequence[1].getOID();
return sequence[1].getOID().decode();
} else {
DerValue[] sequence = new DerInputStream(key.getEncoded()).getSequence();
// Read the first value in the sequence, it is the algorithm OID, the second wil be the curve
sequence[0].getOID();
return sequence[0].getOID().decode();
Expand Down
71 changes: 0 additions & 71 deletions src/main/java/io/fusionauth/jwt/CryptoProvider.java

This file was deleted.

1 change: 1 addition & 0 deletions src/main/java/io/fusionauth/jwt/JWTSigningException.java
Expand Up @@ -22,6 +22,7 @@
* @author Daniel DeGroff
*/
public class JWTSigningException extends JWTException {
@SuppressWarnings("unused")
public JWTSigningException() {
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/io/fusionauth/jwt/JWTUtils.java
Expand Up @@ -23,7 +23,7 @@
import io.fusionauth.jwt.json.Mapper;
import io.fusionauth.pem.domain.PEM;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
Expand Down Expand Up @@ -60,7 +60,7 @@ public static String convertFingerprintToThumbprint(String fingerprint) {
* @return a SHA-1 or SHA-256 fingerprint
*/
public static String convertThumbprintToFingerprint(String x5tHash) {
byte[] bytes = Base64.getUrlDecoder().decode(x5tHash.getBytes(Charset.forName("UTF-8")));
byte[] bytes = Base64.getUrlDecoder().decode(x5tHash.getBytes(StandardCharsets.UTF_8));
return HexUtils.fromBytes(bytes);
}

Expand Down Expand Up @@ -167,7 +167,7 @@ public static KeyPair generate521_ECKeyPair() {
* @return an x5t hash.
*/
public static String generateJWS_x5t(String algorithm, String encodedCertificate) {
byte[] bytes = Base64.getDecoder().decode(encodedCertificate.getBytes(Charset.forName("UTF-8")));
byte[] bytes = Base64.getDecoder().decode(encodedCertificate.getBytes(StandardCharsets.UTF_8));
return digest(algorithm, bytes);
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/io/fusionauth/jwt/JWTVerifierException.java
Expand Up @@ -22,6 +22,7 @@
* @author Daniel DeGroff
*/
public class JWTVerifierException extends JWTException {
@SuppressWarnings("unused")
public JWTVerifierException() {
}

Expand Down
1 change: 0 additions & 1 deletion src/main/java/io/fusionauth/jwt/UnsecuredSigner.java
Expand Up @@ -24,7 +24,6 @@
* @author Daniel DeGroff
*/
public class UnsecuredSigner implements Signer {

@Override
public Algorithm getAlgorithm() {
return Algorithm.none;
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/io/fusionauth/jwt/ec/ECDSASignature.java
Expand Up @@ -51,7 +51,7 @@
* @author Daniel DeGroff
*/
public class ECDSASignature {
private byte[] bytes;
private final byte[] bytes;

public ECDSASignature(byte[] bytes) {
this.bytes = bytes;
Expand Down Expand Up @@ -86,7 +86,9 @@ public byte[] derDecode(Algorithm algorithm) throws IOException {
}

int len = result.length / 2;
//noinspection ManualMinMaxCalculation
System.arraycopy(r, r.length > len ? 1 : 0, result, r.length < len ? 1 : 0, r.length > len ? len : r.length);
//noinspection ManualMinMaxCalculation
System.arraycopy(s, s.length > len ? 1 : 0, result, s.length < len ? (len + 1) : len, s.length > len ? len : s.length);
return result;
}
Expand Down

0 comments on commit d2d775d

Please sign in to comment.