updated to nimbus 4.3, check JCE policy and algorithm availability before running unit tests, closes #938
parent
2deec98b58
commit
f04face41e
|
@ -82,6 +82,10 @@
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-annotations</artifactId>
|
<artifactId>jackson-annotations</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
|
@ -40,8 +40,13 @@ import com.nimbusds.jose.JWEEncrypter;
|
||||||
import com.nimbusds.jose.JWEObject;
|
import com.nimbusds.jose.JWEObject;
|
||||||
import com.nimbusds.jose.crypto.DirectDecrypter;
|
import com.nimbusds.jose.crypto.DirectDecrypter;
|
||||||
import com.nimbusds.jose.crypto.DirectEncrypter;
|
import com.nimbusds.jose.crypto.DirectEncrypter;
|
||||||
|
import com.nimbusds.jose.crypto.ECDHDecrypter;
|
||||||
|
import com.nimbusds.jose.crypto.ECDHEncrypter;
|
||||||
import com.nimbusds.jose.crypto.RSADecrypter;
|
import com.nimbusds.jose.crypto.RSADecrypter;
|
||||||
import com.nimbusds.jose.crypto.RSAEncrypter;
|
import com.nimbusds.jose.crypto.RSAEncrypter;
|
||||||
|
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
|
||||||
|
import com.nimbusds.jose.jca.JCAContext;
|
||||||
|
import com.nimbusds.jose.jwk.ECKey;
|
||||||
import com.nimbusds.jose.jwk.JWK;
|
import com.nimbusds.jose.jwk.JWK;
|
||||||
import com.nimbusds.jose.jwk.OctetSequenceKey;
|
import com.nimbusds.jose.jwk.OctetSequenceKey;
|
||||||
import com.nimbusds.jose.jwk.RSAKey;
|
import com.nimbusds.jose.jwk.RSAKey;
|
||||||
|
@ -223,23 +228,40 @@ public class DefaultJWTEncryptionAndDecryptionService implements JWTEncryptionAn
|
||||||
if (jwk instanceof RSAKey) {
|
if (jwk instanceof RSAKey) {
|
||||||
// build RSA encrypters and decrypters
|
// build RSA encrypters and decrypters
|
||||||
|
|
||||||
RSAEncrypter encrypter = new RSAEncrypter(((RSAKey) jwk).toRSAPublicKey()); // there should always at least be the public key
|
RSAEncrypter encrypter = new RSAEncrypter((RSAKey) jwk); // there should always at least be the public key
|
||||||
|
encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
|
||||||
encrypters.put(id, encrypter);
|
encrypters.put(id, encrypter);
|
||||||
|
|
||||||
if (jwk.isPrivate()) { // we can decrypt!
|
if (jwk.isPrivate()) { // we can decrypt!
|
||||||
RSADecrypter decrypter = new RSADecrypter(((RSAKey) jwk).toRSAPrivateKey());
|
RSADecrypter decrypter = new RSADecrypter((RSAKey) jwk);
|
||||||
|
decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
|
||||||
decrypters.put(id, decrypter);
|
decrypters.put(id, decrypter);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("No private key for key #" + jwk.getKeyID());
|
logger.warn("No private key for key #" + jwk.getKeyID());
|
||||||
}
|
}
|
||||||
|
} else if (jwk instanceof ECKey) {
|
||||||
|
|
||||||
// TODO: add support for EC keys
|
// build EC Encrypters and decrypters
|
||||||
|
|
||||||
|
ECDHEncrypter encrypter = new ECDHEncrypter((ECKey) jwk);
|
||||||
|
encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
|
||||||
|
encrypters.put(id, encrypter);
|
||||||
|
|
||||||
|
if (jwk.isPrivate()) { // we can decrypt too
|
||||||
|
ECDHDecrypter decrypter = new ECDHDecrypter((ECKey) jwk);
|
||||||
|
decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
|
||||||
|
decrypters.put(id, decrypter);
|
||||||
|
} else {
|
||||||
|
logger.warn("No private key for key # " + jwk.getKeyID());
|
||||||
|
}
|
||||||
|
|
||||||
} else if (jwk instanceof OctetSequenceKey) {
|
} else if (jwk instanceof OctetSequenceKey) {
|
||||||
// build symmetric encrypters and decrypters
|
// build symmetric encrypters and decrypters
|
||||||
|
|
||||||
DirectEncrypter encrypter = new DirectEncrypter(((OctetSequenceKey) jwk).toByteArray());
|
DirectEncrypter encrypter = new DirectEncrypter((OctetSequenceKey) jwk);
|
||||||
DirectDecrypter decrypter = new DirectDecrypter(((OctetSequenceKey) jwk).toByteArray());
|
encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
|
||||||
|
DirectDecrypter decrypter = new DirectDecrypter((OctetSequenceKey) jwk);
|
||||||
|
decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
|
||||||
|
|
||||||
encrypters.put(id, encrypter);
|
encrypters.put(id, encrypter);
|
||||||
decrypters.put(id, decrypter);
|
decrypters.put(id, decrypter);
|
||||||
|
|
|
@ -23,9 +23,16 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
|
||||||
|
import org.junit.Assume;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
import org.mitre.jose.keystore.JWKSetKeyStore;
|
import org.mitre.jose.keystore.JWKSetKeyStore;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.nimbusds.jose.EncryptionMethod;
|
import com.nimbusds.jose.EncryptionMethod;
|
||||||
|
@ -33,6 +40,7 @@ import com.nimbusds.jose.JOSEException;
|
||||||
import com.nimbusds.jose.JWEAlgorithm;
|
import com.nimbusds.jose.JWEAlgorithm;
|
||||||
import com.nimbusds.jose.JWEHeader;
|
import com.nimbusds.jose.JWEHeader;
|
||||||
import com.nimbusds.jose.JWEObject;
|
import com.nimbusds.jose.JWEObject;
|
||||||
|
import com.nimbusds.jose.jca.JCASupport;
|
||||||
import com.nimbusds.jose.jwk.JWK;
|
import com.nimbusds.jose.jwk.JWK;
|
||||||
import com.nimbusds.jose.jwk.JWKSet;
|
import com.nimbusds.jose.jwk.JWKSet;
|
||||||
import com.nimbusds.jose.jwk.KeyUse;
|
import com.nimbusds.jose.jwk.KeyUse;
|
||||||
|
@ -58,13 +66,18 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class TestDefaultJWTEncryptionAndDecryptionService {
|
public class TestDefaultJWTEncryptionAndDecryptionService {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(TestDefaultJWTEncryptionAndDecryptionService.class);
|
||||||
|
|
||||||
private String plainText = "The true sign of intelligence is not knowledge but imagination.";
|
private String plainText = "The true sign of intelligence is not knowledge but imagination.";
|
||||||
|
|
||||||
private String issuer = "www.example.net";
|
private String issuer = "www.example.net";
|
||||||
private String subject = "example_user";
|
private String subject = "example_user";
|
||||||
private JWTClaimsSet claimsSet = null;
|
private JWTClaimsSet claimsSet = null;
|
||||||
|
|
||||||
// Example data taken from Mike Jones's draft-ietf-jose-json-web-encryption-14 appendix examples
|
@Rule
|
||||||
|
public ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
|
// Example data taken from rfc7516 appendix A
|
||||||
private String compactSerializedJwe = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ." +
|
private String compactSerializedJwe = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ." +
|
||||||
"OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe" +
|
"OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe" +
|
||||||
"ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb" +
|
"ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb" +
|
||||||
|
@ -167,8 +180,12 @@ public class TestDefaultJWTEncryptionAndDecryptionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void decrypt_RSA() throws ParseException {
|
public void decrypt_RSA() throws ParseException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support
|
||||||
|
&& JCASupport.isSupported(EncryptionMethod.A256GCM)
|
||||||
|
&& Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength
|
||||||
|
|
||||||
service.setDefaultDecryptionKeyId(RSAkid);
|
service.setDefaultDecryptionKeyId(RSAkid);
|
||||||
service.setDefaultEncryptionKeyId(RSAkid);
|
service.setDefaultEncryptionKeyId(RSAkid);
|
||||||
|
@ -184,8 +201,12 @@ public class TestDefaultJWTEncryptionAndDecryptionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void encryptThenDecrypt_RSA() throws ParseException {
|
public void encryptThenDecrypt_RSA() throws ParseException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support
|
||||||
|
&& JCASupport.isSupported(EncryptionMethod.A256GCM)
|
||||||
|
&& Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength
|
||||||
|
|
||||||
service.setDefaultDecryptionKeyId(RSAkid);
|
service.setDefaultDecryptionKeyId(RSAkid);
|
||||||
service.setDefaultEncryptionKeyId(RSAkid);
|
service.setDefaultEncryptionKeyId(RSAkid);
|
||||||
|
@ -212,8 +233,12 @@ public class TestDefaultJWTEncryptionAndDecryptionService {
|
||||||
|
|
||||||
|
|
||||||
// The same as encryptThenDecrypt_RSA() but relies on the key from the map
|
// The same as encryptThenDecrypt_RSA() but relies on the key from the map
|
||||||
//@Test
|
@Test
|
||||||
public void encryptThenDecrypt_nullID() throws ParseException {
|
public void encryptThenDecrypt_nullID() throws ParseException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support
|
||||||
|
&& JCASupport.isSupported(EncryptionMethod.A256GCM)
|
||||||
|
&& Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength
|
||||||
|
|
||||||
service.setDefaultDecryptionKeyId(null);
|
service.setDefaultDecryptionKeyId(null);
|
||||||
service.setDefaultEncryptionKeyId(null);
|
service.setDefaultEncryptionKeyId(null);
|
||||||
|
@ -239,8 +264,14 @@ public class TestDefaultJWTEncryptionAndDecryptionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expected=IllegalStateException.class)
|
@Test
|
||||||
public void encrypt_nullID_oneKey() {
|
public void encrypt_nullID_oneKey() throws NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support
|
||||||
|
&& JCASupport.isSupported(EncryptionMethod.A256GCM)
|
||||||
|
&& Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength
|
||||||
|
|
||||||
|
exception.expect(IllegalStateException.class);
|
||||||
|
|
||||||
service_2.setDefaultEncryptionKeyId(null);
|
service_2.setDefaultEncryptionKeyId(null);
|
||||||
assertEquals(null, service_2.getDefaultEncryptionKeyId());
|
assertEquals(null, service_2.getDefaultEncryptionKeyId());
|
||||||
|
@ -254,8 +285,15 @@ public class TestDefaultJWTEncryptionAndDecryptionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expected=IllegalStateException.class)
|
@Test
|
||||||
public void decrypt_nullID() throws ParseException {
|
public void decrypt_nullID() throws ParseException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support
|
||||||
|
&& JCASupport.isSupported(EncryptionMethod.A256GCM)
|
||||||
|
&& Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength
|
||||||
|
|
||||||
|
|
||||||
|
exception.expect(IllegalStateException.class);
|
||||||
|
|
||||||
service_2.setDefaultEncryptionKeyId(RSAkid);
|
service_2.setDefaultEncryptionKeyId(RSAkid);
|
||||||
service_2.setDefaultDecryptionKeyId(null);
|
service_2.setDefaultDecryptionKeyId(null);
|
||||||
|
|
14
pom.xml
14
pom.xml
|
@ -335,6 +335,11 @@
|
||||||
<artifactId>javax.persistence</artifactId>
|
<artifactId>javax.persistence</artifactId>
|
||||||
<version>2.1.0</version>
|
<version>2.1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>2.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Logging -->
|
<!-- Logging -->
|
||||||
|
@ -470,13 +475,12 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.nimbusds</groupId>
|
<groupId>com.nimbusds</groupId>
|
||||||
<artifactId>nimbus-jose-jwt</artifactId>
|
<artifactId>nimbus-jose-jwt</artifactId>
|
||||||
<version>4.2</version>
|
<version>4.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.zaxxer</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
<version>2.4.1</version>
|
<version>[1.52,]</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
Loading…
Reference in New Issue