diff --git a/common/src/main/java/org/keycloak/common/crypto/CryptoProvider.java b/common/src/main/java/org/keycloak/common/crypto/CryptoProvider.java index aefcb319e2..ed70e88e28 100644 --- a/common/src/main/java/org/keycloak/common/crypto/CryptoProvider.java +++ b/common/src/main/java/org/keycloak/common/crypto/CryptoProvider.java @@ -3,6 +3,7 @@ package org.keycloak.common.crypto; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; +import java.security.spec.ECParameterSpec; /** * Abstraction to handle differences between the APIs for non-fips and fips mode @@ -43,4 +44,13 @@ public interface CryptoProvider { */ public PemUtilsProvider getPemUtils(); + + /** + * Create the param spec for the EC curve + * + * @param curveName + * @return + */ + public ECParameterSpec createECParams(String curveName); + } diff --git a/core/pom.xml b/core/pom.xml index 1131a559fc..d6688a4cac 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -46,14 +46,6 @@ org.keycloak keycloak-common - - org.bouncycastle - bcprov-jdk15on - - - org.bouncycastle - bcpkix-jdk15on - com.fasterxml.jackson.core jackson-core diff --git a/core/src/main/java/org/keycloak/KeyPairVerifier.java b/core/src/main/java/org/keycloak/KeyPairVerifier.java index c8b6dce612..a224aa1976 100644 --- a/core/src/main/java/org/keycloak/KeyPairVerifier.java +++ b/core/src/main/java/org/keycloak/KeyPairVerifier.java @@ -36,14 +36,14 @@ public class KeyPairVerifier { try { privateKey = PemUtils.decodePrivateKey(privateKeyPem); } catch (Exception e) { - throw new VerificationException("Failed to decode private key"); + throw new VerificationException("Failed to decode private key", e); } PublicKey publicKey; try { publicKey = PemUtils.decodePublicKey(publicKeyPem); } catch (Exception e) { - throw new VerificationException("Failed to decode public key"); + throw new VerificationException("Failed to decode public key", e); } try { diff --git a/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java b/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java index 809014a436..d44c09197e 100755 --- a/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java +++ b/core/src/main/java/org/keycloak/jose/jwk/JWKParser.java @@ -17,9 +17,8 @@ package org.keycloak.jose.jwk; -import org.bouncycastle.jce.ECNamedCurveTable; -import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; -import org.bouncycastle.jce.spec.ECNamedCurveSpec; + +import org.keycloak.common.crypto.CryptoIntegration; import org.keycloak.common.util.Base64Url; import org.keycloak.crypto.KeyType; import org.keycloak.util.JsonSerialization; @@ -27,6 +26,7 @@ import org.keycloak.util.JsonSerialization; import java.math.BigInteger; import java.security.KeyFactory; import java.security.PublicKey; +import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPublicKeySpec; import java.security.spec.RSAPublicKeySpec; @@ -99,9 +99,9 @@ public class JWKParser { } try { - ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name); - ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN()); + ECPoint point = new ECPoint(x, y); + ECParameterSpec params = CryptoIntegration.getProvider().createECParams(name); ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params); KeyFactory kf = KeyFactory.getInstance("ECDSA"); diff --git a/core/src/test/java/org/keycloak/KeyPairVerifierTest.java b/core/src/test/java/org/keycloak/KeyPairVerifierTest.java index db1296d2d0..1b3216b7d1 100644 --- a/core/src/test/java/org/keycloak/KeyPairVerifierTest.java +++ b/core/src/test/java/org/keycloak/KeyPairVerifierTest.java @@ -19,7 +19,6 @@ package org.keycloak; import org.junit.Assert; import org.junit.ClassRule; -import org.junit.Rule; import org.junit.Test; import org.keycloak.common.VerificationException; import org.keycloak.rule.CryptoInitRule; @@ -34,10 +33,10 @@ public abstract class KeyPairVerifierTest { @ClassRule public static CryptoInitRule cryptoInitRule = new CryptoInitRule(); - String privateKey1 = "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y="; + protected String privateKey1 = "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y="; String publicKey1 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"; - String privateKey2048 = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEA4V3MpOnuKsdBbR1UzNjK9o5meEMQ4s5Vpykhv1DpqTilKOiE\n" + protected String privateKey2048 = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEA4V3MpOnuKsdBbR1UzNjK9o5meEMQ4s5Vpykhv1DpqTilKOiE\n" + "H7VQ/XtjNxw0yjnFBilCnpK6yN9mDEHbBEzaRjtdrgVhkIejiaXFBP5MBhUQ5l9u\n" + "8E3IZC3E8pwDjVF0Z9u0R4lGeUg2k6O+NKumqIvxoLCTuG0zf53bctGsRd57LuFi\n" + "pgCkNyxvscOhulsbEMYrLwlb5bMGgx9v+RCnwvunNEb7RK+5pzP+iH1MRejRsX+U\n" + "7h9zHRn2gQhIl7SzG9GXebuPWr4KKwfMHWy0PEuQrsfWRXm9/dTEavbfNkv5E53z\n" + "WXjWyf93ezkVhBX0YoXmf6UO7PAlvsrjno3TuwIDAQABAoIBAQC5iCAOcCtLemhp\n" + "bOlADwXgPtErFoNTROyMxjbrKrCCSIjniawj8oAvfiHq38Sx6ydBcDxREZjF/+wi\n" diff --git a/core/src/test/java/org/keycloak/RSAVerifierTest.java b/core/src/test/java/org/keycloak/RSAVerifierTest.java index 6d120b7cf9..f930f0d2fc 100755 --- a/core/src/test/java/org/keycloak/RSAVerifierTest.java +++ b/core/src/test/java/org/keycloak/RSAVerifierTest.java @@ -17,101 +17,44 @@ package org.keycloak; -import junit.framework.Assert; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.X509v1CertificateBuilder; -import org.bouncycastle.crypto.util.PrivateKeyFactory; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.jcajce.JcaPEMWriter; -import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; -import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; -import org.bouncycastle.operator.OperatorCreationException; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Test; import org.keycloak.common.util.Time; import org.keycloak.common.VerificationException; import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.representations.AccessToken; +import org.keycloak.rule.CryptoInitRule; import org.keycloak.util.JsonSerialization; import org.keycloak.util.TokenUtil; -import java.io.IOException; -import java.io.StringWriter; -import java.math.BigInteger; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PublicKey; -import java.security.Security; -import java.security.SignatureException; -import java.util.Date; -import javax.security.auth.x500.X500Principal; /** * @author Bill Burke * @version $Revision: 1 $ */ -public class RSAVerifierTest { - private static X509Certificate[] idpCertificates; +public abstract class RSAVerifierTest { + // private static X509Certificate[] idpCertificates; private static KeyPair idpPair; private static KeyPair badPair; - private static KeyPair clientPair; - private static X509Certificate[] clientCertificateChain; + // private static KeyPair clientPair; + // private static X509Certificate[] clientCertificateChain; private AccessToken token; - public static X509Certificate generateTestCertificate(String subject, String issuer, KeyPair pair) - throws CertificateException, InvalidKeyException, IOException, - NoSuchProviderException, OperatorCreationException, - SignatureException - { - X500Name issuerDN = new X500Name("CN=" + issuer); - BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); - Date notBefore = new Date(System.currentTimeMillis() - 10000); - Date notAfter = new Date(System.currentTimeMillis() + 10000); - X500Name subjectDN = new X500Name("CN=" + subject); - SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo - .getInstance(pair.getPublic().getEncoded()); - - X509v1CertificateBuilder builder = new X509v1CertificateBuilder( - issuerDN, serialNumber, notBefore, notAfter, subjectDN, subjectPublicKeyInfo - ); - - AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder() - .find("SHA256WithRSAEncryption"); - - AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder() - .find(sigAlgId); - - ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId) - .build(PrivateKeyFactory.createKey(pair.getPrivate().getEncoded())); - - X509CertificateHolder holder = builder.build(signer); - - return new JcaX509CertificateConverter().getCertificate(holder); - } + @ClassRule + public static CryptoInitRule cryptoInitRule = new CryptoInitRule(); @BeforeClass public static void setupCerts() - throws CertificateException, InvalidKeyException, IOException, - NoSuchAlgorithmException, NoSuchProviderException, - OperatorCreationException, SignatureException + throws Exception { + // CryptoIntegration.init(ClassLoader.getSystemClassLoader()); badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); idpPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); - idpCertificates = new X509Certificate[]{generateTestCertificate("CN=IDP", "CN=IDP", idpPair)}; - clientPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); - clientCertificateChain = new X509Certificate[]{generateTestCertificate("CN=Client", "CN=IDP", idpPair)}; } @Before @@ -124,22 +67,7 @@ public class RSAVerifierTest { .addAccess("service").addRole("admin"); } - @Test - public void testPemWriter() { - PublicKey realmPublicKey = idpPair.getPublic(); - StringWriter sw = new StringWriter(); - JcaPEMWriter writer = new JcaPEMWriter(sw); - try { - writer.writeObject(realmPublicKey); - writer.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } - System.out.println(sw.toString()); - } - - - @Test + @Test public void testSimpleVerification() throws Exception { String encoded = new JWSBuilder() .jsonContent(token) @@ -154,7 +82,6 @@ public class RSAVerifierTest { return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "http://localhost:8080/auth/realm"); } - // @Test public void testSpeed() throws Exception { @@ -176,8 +103,6 @@ public class RSAVerifierTest { System.out.println("took: " + end); } - - @Test public void testBadSignature() { diff --git a/core/src/test/java/org/keycloak/jose/HmacTest.java b/core/src/test/java/org/keycloak/jose/HmacTest.java index ab5e3b9343..5b8125cd4c 100755 --- a/core/src/test/java/org/keycloak/jose/HmacTest.java +++ b/core/src/test/java/org/keycloak/jose/HmacTest.java @@ -18,10 +18,12 @@ package org.keycloak.jose; import org.junit.Assert; +import org.junit.ClassRule; import org.junit.Test; import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.HMACProvider; +import org.keycloak.rule.CryptoInitRule; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; @@ -31,7 +33,10 @@ import java.util.UUID; * @author Bill Burke * @version $Revision: 1 $ */ -public class HmacTest { +public abstract class HmacTest { + + @ClassRule + public static CryptoInitRule cryptoInitRule = new CryptoInitRule(); @Test public void testHmacSignatures() throws Exception { @@ -43,5 +48,4 @@ public class HmacTest { Assert.assertTrue(HMACProvider.verify(input, secret)); } - } diff --git a/core/src/test/java/org/keycloak/jose/jwk/JWKTest.java b/core/src/test/java/org/keycloak/jose/jwk/JWKTest.java index 3a7694f30b..78e400adb5 100644 --- a/core/src/test/java/org/keycloak/jose/jwk/JWKTest.java +++ b/core/src/test/java/org/keycloak/jose/jwk/JWKTest.java @@ -21,7 +21,6 @@ import java.util.Arrays; import java.util.List; import org.junit.ClassRule; -import org.junit.Rule; import org.junit.Test; import org.keycloak.common.util.Base64Url; import org.keycloak.common.util.BouncyIntegration; @@ -62,7 +61,7 @@ public abstract class JWKTest { @Test public void publicRs256() throws Exception { - KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); + KeyPair keyPair = KeyPairGenerator.getInstance("RSA", BouncyIntegration.PROVIDER ).generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); X509Certificate certificate = generateV1SelfSignedCertificate(keyPair, "Test"); @@ -97,7 +96,7 @@ public abstract class JWKTest { @Test public void publicRs256Chain() throws Exception { - KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); + KeyPair keyPair = KeyPairGenerator.getInstance("RSA", BouncyIntegration.PROVIDER).generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); List certificates = Arrays.asList(generateV1SelfSignedCertificate(keyPair, "Test"), generateV1SelfSignedCertificate(keyPair, "Intermediate")); diff --git a/core/src/test/java/org/keycloak/util/JWKSUtilsTest.java b/core/src/test/java/org/keycloak/util/JWKSUtilsTest.java index 0d7f413a1a..86785251a5 100644 --- a/core/src/test/java/org/keycloak/util/JWKSUtilsTest.java +++ b/core/src/test/java/org/keycloak/util/JWKSUtilsTest.java @@ -17,30 +17,25 @@ package org.keycloak.util; +import org.junit.ClassRule; import org.junit.Test; -import org.keycloak.common.util.Base64Url; -import org.keycloak.common.util.CertificateUtils; -import org.keycloak.common.util.KeyUtils; -import org.keycloak.common.util.PemUtils; -import org.keycloak.crypto.JavaAlgorithm; import org.keycloak.crypto.KeyUse; import org.keycloak.crypto.KeyWrapper; import org.keycloak.jose.jwk.*; +import org.keycloak.rule.CryptoInitRule; -import java.nio.charset.StandardCharsets; -import java.security.*; -import java.security.cert.X509Certificate; -import java.security.spec.ECGenParameterSpec; import java.util.Map; import static org.junit.Assert.*; -public class JWKSUtilsTest { +public abstract class JWKSUtilsTest { + + @ClassRule + public static CryptoInitRule cryptoInitRule = new CryptoInitRule(); @Test public void publicRs256() throws Exception { - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); String kidRsa1 = "key1"; String kidRsa2 = "key2"; diff --git a/crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java b/crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java index ac91f37313..ad67d92cc9 100644 --- a/crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java +++ b/crypto/default/src/main/java/org/keycloak/crypto/def/DefaultCryptoProvider.java @@ -2,10 +2,14 @@ package org.keycloak.crypto.def; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.security.spec.ECParameterSpec; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.keycloak.common.crypto.CryptoProvider; import org.keycloak.common.crypto.CryptoProviderTypes; @@ -48,4 +52,10 @@ public class DefaultCryptoProvider implements CryptoProvider { return new BCPemUtilsProvider(); } + @Override + public ECParameterSpec createECParams(String curveName) { + ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curveName); + return new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN()); + } + } diff --git a/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoHmacTest.java b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoHmacTest.java new file mode 100644 index 0000000000..fe7c6f25a6 --- /dev/null +++ b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoHmacTest.java @@ -0,0 +1,11 @@ +package org.keycloak.crypto.def.test; + +import org.keycloak.jose.HmacTest; + + +/** + * Test with bouncycastle security provider + * + */ +public class DefaultCryptoHmacTest extends HmacTest { +} diff --git a/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoJWKSUtilsTest.java b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoJWKSUtilsTest.java new file mode 100644 index 0000000000..8a24cd859a --- /dev/null +++ b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoJWKSUtilsTest.java @@ -0,0 +1,10 @@ +package org.keycloak.crypto.def.test; + +import org.keycloak.util.JWKSUtilsTest; + +/** + * Test with bouncycastle security provider + * + */ +public class DefaultCryptoJWKSUtilsTest extends JWKSUtilsTest { +} diff --git a/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoRSAVerifierTest.java b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoRSAVerifierTest.java new file mode 100644 index 0000000000..cb6541286f --- /dev/null +++ b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoRSAVerifierTest.java @@ -0,0 +1,10 @@ +package org.keycloak.crypto.def.test; + +import org.keycloak.RSAVerifierTest; + +/** + * Test with bouncycastle security provider + * + */ +public class DefaultCryptoRSAVerifierTest extends RSAVerifierTest { +} diff --git a/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoUnitTest.java b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoUnitTest.java index 907ab0a32c..6fa4faf7c0 100644 --- a/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoUnitTest.java +++ b/crypto/default/src/test/java/org/keycloak/crypto/def/test/DefaultCryptoUnitTest.java @@ -1,6 +1,7 @@ package org.keycloak.crypto.def.test; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.keycloak.common.crypto.CryptoIntegration; import org.keycloak.common.crypto.CryptoProviderTypes; @@ -12,6 +13,11 @@ import org.keycloak.jose.jwe.alg.JWEAlgorithmProvider; */ public class DefaultCryptoUnitTest { + @Before + public void init() { + CryptoIntegration.init(ClassLoader.getSystemClassLoader()); + } + @Test public void testDefaultCrypto() throws Exception { JWEAlgorithmProvider jweAlg = CryptoIntegration.getProvider().getAlgorithmProvider(JWEAlgorithmProvider.class, CryptoProviderTypes.AES_KEY_WRAP_ALGORITHM_PROVIDER); diff --git a/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java b/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java index 35ea102e96..dc9ad7d998 100644 --- a/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java +++ b/crypto/fips1402/src/main/java/org/keycloak/crypto/fips/FIPS1402Provider.java @@ -3,11 +3,20 @@ package org.keycloak.crypto.fips; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; +import java.security.spec.ECField; +import java.security.spec.ECFieldF2m; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.EllipticCurve; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; +import org.bouncycastle.asn1.x9.ECNamedCurveTable; +import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider; +import org.bouncycastle.math.ec.ECCurve; import org.keycloak.common.crypto.CryptoProvider; import org.keycloak.common.crypto.CryptoProviderTypes; import org.keycloak.common.crypto.CertificateUtilsProvider; @@ -51,4 +60,34 @@ public class FIPS1402Provider implements CryptoProvider { public PemUtilsProvider getPemUtils() { return new BCFIPSPemUtilsProvider(); } + + /* Create EC Params using BC FipS APIs. + * + * @see org.keycloak.common.crypto.CryptoProvider#createECParams(java.lang.String) + */ + @Override + public ECParameterSpec createECParams(String curveName) { + X9ECParameters params = ECNamedCurveTable.getByName(curveName); + ECField field ; + ECCurve ecCurve = params.getCurve(); + if (ecCurve instanceof ECCurve.F2m) { + ECCurve.F2m f2m = (ECCurve.F2m) ecCurve; + field = new ECFieldF2m(f2m.getM(), new int[] { f2m.getK1(), f2m.getK2(), f2m.getK3()}); + } + else + if (ecCurve instanceof ECCurve.Fp) { + ECCurve.Fp fp = (ECCurve.Fp) ecCurve; + field = new ECFieldFp(fp.getQ()); + } + else + throw new RuntimeException("Unsupported curve"); + + + EllipticCurve c = new EllipticCurve(field, + ecCurve.getA().toBigInteger(), + ecCurve.getB().toBigInteger(), + params.getSeed()); + ECPoint point = new ECPoint( params.getG().getXCoord().toBigInteger(), params.getG().getYCoord().toBigInteger()); + return new ECParameterSpec( c,point, params.getN(), params.getH().intValue()); + } } diff --git a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402HmacTest.java b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402HmacTest.java new file mode 100644 index 0000000000..a07307ac3e --- /dev/null +++ b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402HmacTest.java @@ -0,0 +1,36 @@ +package org.keycloak.crypto.fips.test; + +import java.util.UUID; + +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.SecretKeySpec; + +import org.junit.Assert; +import org.junit.Test; +import org.keycloak.common.util.BouncyIntegration; +import org.keycloak.jose.HmacTest; +import org.keycloak.jose.jws.JWSBuilder; +import org.keycloak.jose.jws.JWSInput; +import org.keycloak.jose.jws.crypto.HMACProvider; + + +/** + * Another variation to this test using SecretKeyFactory + * + */ +public class FIPS1402HmacTest extends HmacTest { + + @Test + public void testHmacSignaturesFIPS() throws Exception { + // + + SecretKeyFactory skFact = SecretKeyFactory.getInstance("HmacSHA256", BouncyIntegration.PROVIDER ); + SecretKey secret = skFact.generateSecret(new SecretKeySpec(UUID.randomUUID().toString().getBytes(), "HmacSHA256")); + String encoded = new JWSBuilder().content("12345678901234567890".getBytes()) + .hmac256(secret); + System.out.println("length: " + encoded.length()); + JWSInput input = new JWSInput(encoded); + Assert.assertTrue(HMACProvider.verify(input, secret)); + } +} diff --git a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWETest.java b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWETest.java index 802e85b548..8521e85abf 100644 --- a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWETest.java +++ b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWETest.java @@ -1,6 +1,5 @@ package org.keycloak.crypto.fips.test; -import org.junit.Ignore; import org.keycloak.jose.JWETest; /** @@ -8,6 +7,5 @@ import org.keycloak.jose.JWETest; * * @author Marek Posolda */ -@Ignore("Ignored by default as it does not work on non-fips enabled environment") // TODO: Figure how to test in the FIPS environments, but still keep disabled in the non-FIPS environments public class FIPS1402JWETest extends JWETest { } diff --git a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWKTest.java b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWKTest.java index 182ef0f7da..cd37e9b1c9 100644 --- a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWKTest.java +++ b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402JWKTest.java @@ -1,6 +1,7 @@ package org.keycloak.crypto.fips.test; import org.junit.Ignore; +import org.junit.Test; import org.keycloak.jose.jwk.JWKTest; /** @@ -8,6 +9,12 @@ import org.keycloak.jose.jwk.JWKTest; * * @author Marek Posolda */ -@Ignore("Ignored by default as it does not work on non-fips enabled environment") // TODO: Figure how to test in the FIPS environments, but still keep disabled in the non-FIPS environments public class FIPS1402JWKTest extends JWKTest { + + @Ignore("Test not supported by BC FIPS") + @Test + public void publicEs256() throws Exception { + // Do nothing + } + } diff --git a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402KeyPairVerifierTest.java b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402KeyPairVerifierTest.java index 412234ffe3..ef3ded577c 100644 --- a/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402KeyPairVerifierTest.java +++ b/crypto/fips1402/src/test/java/org/keycloak/crypto/fips/test/FIPS1402KeyPairVerifierTest.java @@ -1,6 +1,6 @@ package org.keycloak.crypto.fips.test; -import org.junit.Ignore; +import org.junit.Before; import org.keycloak.KeyPairVerifierTest; /** @@ -8,6 +8,54 @@ import org.keycloak.KeyPairVerifierTest; * * @author Marek Posolda */ -@Ignore("Ignored by default as it does not work on non-fips enabled environment") // TODO: Figure how to test in the FIPS environments, but still keep disabled in the non-FIPS environments public class FIPS1402KeyPairVerifierTest extends KeyPairVerifierTest { + + @Before + public void initPrivKeys() { + + // The parent private key is not supported in FIPS-140-2, using a PKCS#8 formatted key + privateKey1 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKtWsK5O0CtuBpnM" + + "vWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfd" + + "Q2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5" + + "SZ5z+na+M7Y2OxIBVxYRAxWEnfUvAgMBAAECgYB+Y7yBWHIHF2qXGYi6CVvPxtyN" + + "BuFcktHYShLyeBNeY3VujYv3QzSZQpJ1zuoXXQuARMHOovyNiVAhu357pMfx9wSk" + + "oKNSXKrQx/+9Vt9lI1pXJxjXedPOjbuI/JZAcrk0u4nOfXG/HGtR5cjoDZYWkYQE" + + "tsePCnHlZAb0D7axwQJBAO92f00Tvkc9NU/EGqwR3bPXRMqSX0JnG7XRBvLeJBCZ" + + "YsQn0s2bLdpy8qsTeAyJg1ZvrEc8qIio5HVqzsvbhpMCQQC3K9A6UK+vmQCNWqsQ" + + "pdqWPRPN7CPB67FzSmyS8CtMjY6jTvSHrkamggotz2N/5QDr1xG2q7A/3dpkq1bT" + + "pTx1AkAXZjjiSz+Yrn57IOqKTeSgIjTypoLwdirbBWXsbZCQnqxsBogu1y8P3ZOg" + + "6/IbJ4TR+W+YNnExiW9pmdpDSVxJAkEAplTq6YmLf/F4RuQmox94tyUPbtcYQWg9" + + "42uZ3HSrXQDOng18kBj5nwpHJAJHYEQb6g2K0E5n5hcX0oKkfdx2YQJAcSKAmFiD" + + "7KQ6+vVqJlQwVPvYdTSOeZB7YVV6S4b4slS3ZObsa0yNMWgal/QnCtW5k3f185gC" + + "Wj6dOLGB5btfxg=="; + + // The parent private key is not supported in FIPS-140-2, using a PKCS#8 formatted key + privateKey2048 = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhXcyk6e4qx0Ft" + + "HVTM2Mr2jmZ4QxDizlWnKSG/UOmpOKUo6IQftVD9e2M3HDTKOcUGKUKekrrI32YM" + + "QdsETNpGO12uBWGQh6OJpcUE/kwGFRDmX27wTchkLcTynAONUXRn27RHiUZ5SDaT" + + "o740q6aoi/GgsJO4bTN/ndty0axF3nsu4WKmAKQ3LG+xw6G6WxsQxisvCVvlswaD" + + "H2/5EKfC+6c0RvtEr7mnM/6IfUxF6NGxf5TuH3MdGfaBCEiXtLMb0Zd5u49avgor" + + "B8wdbLQ8S5Cux9ZFeb391MRq9t82S/kTnfNZeNbJ/3d7ORWEFfRiheZ/pQ7s8CW+" + + "yuOejdO7AgMBAAECggEBALmIIA5wK0t6aGls6UAPBeA+0SsWg1NE7IzGNusqsIJI" + + "iOeJrCPygC9+IerfxLHrJ0FwPFERmMX/7CIRIT6ECnohK3k1IuH6WG7cUrtOosWr" + + "GBOf41PfpSab63STbfUsZrmNzPfLkoIMKioXdmIkIfrF4vEYDTSaafgYu+3loX6O" + + "I7zQgIaziJSD30iheFzm79VTSEHknvwGKdaKeQIAG4E2QMuAipz0Ggfgvkw7HfMO" + + "rOYd996r37ZXhfs2IPlDKLJa0AFpCkQhjmRHjxFOejrE3eG8bjz8PCQ7aAAFItD8" + + "4l3ce6m/jCWaZJzXGj3cJpXjiGraLYaxTWKbp3fENbkCgYEA8J+S8+SqvzzGD7wK" + + "7cb/cYWlSxDRUSZ77x0iNcxMkdrXcrvFpGEYcJWDhrygcn8/+81LC8/JHvWJFfhy" + + "yqQpJqmu8mTy/FtTnf26eYdYqR9QevLBCXOrg65c6M528gss5Oy7f/6Tq8AgTpJk" + + "mIOZ/Z4bGL1BubmuXETeHcdEAp8CgYEA78SiAdXzouaclMlvHWE/ch9EeTSpqJKP" + + "fmWOUDP7e/oY38pJRgJZO2nYaNEgpjepDwjuX49VMWDdJjtw+rYL1MT7rGuiJaRR" + + "3YmV08thLGlakU1iWjvT1LOYuq4OGj5/AkKcDGjEqCGxclqvPtNF83IWoNexxLqh" + + "Au6tT0/mVWUCgYEAmHVC8u1Lkme7RnTqp8WSTCdVl75MIZK0q8hVyKhtS2zRXYzD" + + "qWcryQmykEgrkOA3dh+ZER7SW59PAHCuqt5ghHK2ujZkDqj+zffZku7CqkWBBKWS" + + "0Z5Mad6sV4WZr7qM829bTbnLbuMIlUAEJO4dP6hRmtcvMbIIW8X2xf9fhBkCgYEA" + + "gJqnivSHSckIE4Y34zpWHZBH2fs1RQXXkaRHQR2gtk7fKKoHw1VfJ08OlKoXKRCR" + + "zU6tDPSEbYfXFrqrTs52ahl+JG1W+3m3r2wswP1Fkdywh19KcbvFU0FBml/hkJIU" + + "7dFsgftv//6SfxPFC52m131KRdtrrmmsEzaSHwhsM0ECgYBWwq+Su4ftErsKKYNJ" + + "Zx0Aq8cBGqSOz8+h4oQRjxi7rN/Rn1NAzmW4L0TAFqZhxK6xZFx1zP70dgbnxcWe" + + "Zer7cRS4Vsn4uNvxhYGB4+NIcOhL/r7/7OoHVvm5Cn+NgVthCXnRQ9E9MX66XV5C" + + "jLsXjc2CPf/lwNFqsVl7dlPNmg=="; + + } } diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-core/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-core/main/module.xml index 9969fe2da4..d6a4d8c09c 100755 --- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-core/main/module.xml +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-core/main/module.xml @@ -29,7 +29,6 @@ - diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml index 9682ff71cf..9142ab1c35 100755 --- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml +++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml @@ -26,7 +26,6 @@ - diff --git a/distribution/galleon-feature-packs/server-galleon-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml b/distribution/galleon-feature-packs/server-galleon-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml index 9682ff71cf..9142ab1c35 100755 --- a/distribution/galleon-feature-packs/server-galleon-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml +++ b/distribution/galleon-feature-packs/server-galleon-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-core/main/module.xml @@ -26,7 +26,6 @@ -