Skip to content

Commit

Permalink
abstract Mac, and Signature instance retrieval to optionally use BCFI…
Browse files Browse the repository at this point in the history
…PS if the provider has been registered
  • Loading branch information
robotdan committed Feb 23, 2020
1 parent e82c82a commit 629c6f3
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 29 deletions.
4 changes: 2 additions & 2 deletions build.savant
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2016-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,7 +17,7 @@
savantVersion = "1.0.0"
jacksonVersion = "2.10.1"

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

workflow {
standard()
Expand Down
12 changes: 6 additions & 6 deletions fusionauth-jwt.iml
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,33 @@
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.9.11+2.9.9.2/jackson-databind-2.9.11+2.9.9.2.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.9.11+2.9.9.2/jackson-databind-2.9.11+2.9.9.2-src.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1-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.9.9/jackson-annotations-2.9.9.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.9.9/jackson-annotations-2.9.9-src.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1-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.9.9/jackson-core-2.9.9.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9-src.jar!/" />
<root url="jar://$USER_HOME$/.savant/cache/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1-src.jar!/" />
</SOURCES>
</library>
</orderEntry>
Expand Down
34 changes: 33 additions & 1 deletion src/main/java/io/fusionauth/der/Tag.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2018-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -49,15 +49,41 @@ public class Tag {
*/
public static final int OctetString = 4;

/**
* PrintableString Tag
* <p>
* 19 decimal, 0x13 hex
* </p>
*/
public static final int PrintableString = 19;

/**
* Sequence Tag
* <p>
* 16 decimal, 0x10 hex, 0b00010000 binary
* </p>
* Because the Sequence tag is always in a constructed form (not primitive), the tag will present as <code>0x30</code> because
* the 6th bit is a <code>1</code> indicating a constructed form. So the raw sequence of <code>0b00010000</code> becomes
* <code>0b00110000</code> which is <code>48</code> decimal.
*/
public static final int Sequence = 48;

/**
* Set and Set of
* <p>
* 17 decimal, 0x11 hex
* </p>
*/
public static final int Set = 17;

/**
* UTCTime Tag
* <p>
* 23 decimal, 0x17 hex
* </p>
*/
public static final int UTCTime = 23;

/**
* True if this Tag is primitive. False if this Tag is constructed.
*/
Expand Down Expand Up @@ -141,8 +167,14 @@ public String getName() {
return "Object Identifier";
case OctetString:
return "Octet String";
case PrintableString:
return "PrintableString";
case Sequence:
return "Sequence";
case Set:
return "Set";
case UTCTime:
return "UTCTime";
default:
return "Other";
}
Expand Down
71 changes: 71 additions & 0 deletions src/main/java/io/fusionauth/jwt/CryptoProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/

package io.fusionauth.jwt;

import javax.crypto.Mac;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Signature;

/**
* @author Daniel DeGroff
*/
public class CryptoProvider {
private static final boolean USE_BC_FIPS;

private CryptoProvider() {
}

public static Mac getMacInstance(String name) throws NoSuchAlgorithmException {
return USE_BC_FIPS ? getBCFipsMacInstance(name) : Mac.getInstance(name);
}

public static Signature getSignatureInstance(String name) throws NoSuchAlgorithmException {
return USE_BC_FIPS ? getBCFipsSignatureInstance(name) : Signature.getInstance(name);
}

private static Mac getBCFipsMacInstance(String name) throws NoSuchAlgorithmException {
try {
return Mac.getInstance(name, "BCFIPS");
} catch (NoSuchProviderException e) {
// Should not happen since we checked during static initialization
throw new RuntimeException(e);
}
}

private static Signature getBCFipsSignatureInstance(String name) throws NoSuchAlgorithmException {
try {
return Signature.getInstance(name, "BCFIPS");
} catch (NoSuchProviderException e) {
// Should not happen since we checked during static initialization
throw new RuntimeException(e);
}
}

static {
Signature signature = null;
try {
signature = Signature.getInstance("SHA256withRSA", "BCFIPS");
} catch (Exception e) {
if (!(e instanceof NoSuchProviderException)) {
throw new RuntimeException(e);
}
}

USE_BC_FIPS = signature != null;
}
}
5 changes: 3 additions & 2 deletions src/main/java/io/fusionauth/jwt/ec/ECSigner.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2018-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,7 @@
import io.fusionauth.jwt.InvalidKeyTypeException;
import io.fusionauth.jwt.JWTSigningException;
import io.fusionauth.jwt.MissingPrivateKeyException;
import io.fusionauth.jwt.CryptoProvider;
import io.fusionauth.jwt.Signer;
import io.fusionauth.jwt.domain.Algorithm;
import io.fusionauth.pem.domain.PEM;
Expand Down Expand Up @@ -138,7 +139,7 @@ public byte[] sign(String message) {
Objects.requireNonNull(message);

try {
Signature signature = Signature.getInstance(algorithm.getName());
Signature signature = CryptoProvider.getSignatureInstance(algorithm.getName());
signature.initSign(privateKey, new SecureRandom());
signature.update((message).getBytes(StandardCharsets.UTF_8));
byte[] derEncoded = signature.sign();
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/fusionauth/jwt/ec/ECVerifier.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2018-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@
import io.fusionauth.jwt.InvalidKeyTypeException;
import io.fusionauth.jwt.JWTVerifierException;
import io.fusionauth.jwt.MissingPublicKeyException;
import io.fusionauth.jwt.CryptoProvider;
import io.fusionauth.jwt.Verifier;
import io.fusionauth.jwt.domain.Algorithm;
import io.fusionauth.pem.domain.PEM;
Expand Down Expand Up @@ -126,7 +127,7 @@ public void verify(Algorithm algorithm, byte[] message, byte[] signature) {
Objects.requireNonNull(signature);

try {
Signature verifier = Signature.getInstance(algorithm.getName());
Signature verifier = CryptoProvider.getSignatureInstance(algorithm.getName());
verifier.initVerify(publicKey);
verifier.update(message);

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/fusionauth/jwt/hmac/HMACSigner.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2016-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@

package io.fusionauth.jwt.hmac;

import io.fusionauth.jwt.CryptoProvider;
import io.fusionauth.jwt.JWTSigningException;
import io.fusionauth.jwt.Signer;
import io.fusionauth.jwt.domain.Algorithm;
Expand Down Expand Up @@ -126,7 +127,7 @@ public byte[] sign(String message) {
Objects.requireNonNull(message);

try {
Mac mac = Mac.getInstance(algorithm.getName());
Mac mac = CryptoProvider.getMacInstance(algorithm.getName());
mac.init(new SecretKeySpec(secret, algorithm.getName()));
return mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/fusionauth/jwt/hmac/HMACVerifier.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2016-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@

package io.fusionauth.jwt.hmac;

import io.fusionauth.jwt.CryptoProvider;
import io.fusionauth.jwt.InvalidJWTSignatureException;
import io.fusionauth.jwt.JWTVerifierException;
import io.fusionauth.jwt.Verifier;
Expand Down Expand Up @@ -107,7 +108,7 @@ public void verify(Algorithm algorithm, byte[] message, byte[] signature) {
Objects.requireNonNull(signature);

try {
Mac mac = Mac.getInstance(algorithm.getName());
Mac mac = CryptoProvider.getMacInstance(algorithm.getName());
mac.init(new SecretKeySpec(secret, algorithm.getName()));
byte[] actualSignature = mac.doFinal(message);

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/fusionauth/jwt/rsa/RSASigner.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2016-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@

package io.fusionauth.jwt.rsa;

import io.fusionauth.jwt.CryptoProvider;
import io.fusionauth.jwt.InvalidKeyLengthException;
import io.fusionauth.jwt.JWTSigningException;
import io.fusionauth.jwt.MissingPrivateKeyException;
Expand Down Expand Up @@ -138,7 +139,7 @@ public byte[] sign(String message) {
Objects.requireNonNull(message);

try {
Signature signature = Signature.getInstance(algorithm.getName());
Signature signature = CryptoProvider.getSignatureInstance(algorithm.getName());
signature.initSign(privateKey);
signature.update(message.getBytes(StandardCharsets.UTF_8));
return signature.sign();
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/fusionauth/jwt/rsa/RSAVerifier.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2016-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@

package io.fusionauth.jwt.rsa;

import io.fusionauth.jwt.CryptoProvider;
import io.fusionauth.jwt.InvalidJWTSignatureException;
import io.fusionauth.jwt.InvalidKeyLengthException;
import io.fusionauth.jwt.JWTVerifierException;
Expand Down Expand Up @@ -125,7 +126,7 @@ public void verify(Algorithm algorithm, byte[] message, byte[] signature) {
Objects.requireNonNull(signature);

try {
Signature verifier = Signature.getInstance(algorithm.getName());
Signature verifier = CryptoProvider.getSignatureInstance(algorithm.getName());
verifier.initVerify(publicKey);
verifier.update(message);
if (!verifier.verify(signature)) {
Expand Down
23 changes: 19 additions & 4 deletions src/test/java/io/fusionauth/der/TagTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019, FusionAuth, All Rights Reserved
* Copyright (c) 2018-2020, FusionAuth, All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,7 +27,7 @@
public class TagTest {
@Test
public void binaryAssertions() {
// I know these won't change - this is for understanding.
// I know these won't change - this is for (my) understanding.

assertEquals(0b00000000, 0); // General
assertEquals(0b01000000, 64); // Application
Expand All @@ -50,12 +50,12 @@ public void tag() {
// Context specific primitive Integer
assertEquals(new Tag(0b10000010).tagClass, TagClass.ContextSpecific);
assertTrue(new Tag(0b10000010).is(Tag.Integer));
assertTrue(new Tag(0b00000010).isPrimitive());
assertTrue(new Tag(0b10000010).isPrimitive());

// Universal primitive Object Identifier
assertEquals(new Tag(0b00000110).tagClass, TagClass.Universal);
assertTrue(new Tag(0b00000110).is(Tag.ObjectIdentifier));
assertTrue(new Tag(0b00000010).isPrimitive());
assertTrue(new Tag(0b00000110).isPrimitive());

// Context specific primitive Object Identifier
assertEquals(new Tag(0b10000110).tagClass, TagClass.ContextSpecific);
Expand Down Expand Up @@ -93,5 +93,20 @@ public void tag() {

assertEquals(new Tag(0xA1).value, 1);
assertEquals(new Tag(0xA1).tagClass, TagClass.ContextSpecific);

// Universal PrintableString
assertEquals(new Tag(0b00010011).tagClass, TagClass.Universal);
assertTrue(new Tag(0b00010011).is(Tag.PrintableString));
assertTrue(new Tag(0b00010011).isPrimitive());

// Universal Set
assertEquals(new Tag(0b00010001).tagClass, TagClass.Universal);
assertTrue(new Tag(0b00010001).is(Tag.Set));
assertTrue(new Tag(0b00010001).isPrimitive());

// Universal UTCTime
assertEquals(new Tag(0b00010111).tagClass, TagClass.Universal);
assertTrue(new Tag(0b00010111).is(Tag.UTCTime));
assertTrue(new Tag(0b00010111).isPrimitive());
}
}
Loading

0 comments on commit 629c6f3

Please sign in to comment.