parent
9bb1299d89
commit
ee0c67c0c8
22 changed files with 225 additions and 129 deletions
|
@ -3,6 +3,7 @@ package org.keycloak.common.crypto;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.ECParameterSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction to handle differences between the APIs for non-fips and fips mode
|
* Abstraction to handle differences between the APIs for non-fips and fips mode
|
||||||
|
@ -43,4 +44,13 @@ public interface CryptoProvider {
|
||||||
*/
|
*/
|
||||||
public PemUtilsProvider getPemUtils();
|
public PemUtilsProvider getPemUtils();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the param spec for the EC curve
|
||||||
|
*
|
||||||
|
* @param curveName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ECParameterSpec createECParams(String curveName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,14 +46,6 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-common</artifactId>
|
<artifactId>keycloak-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bouncycastle</groupId>
|
|
||||||
<artifactId>bcpkix-jdk15on</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-core</artifactId>
|
<artifactId>jackson-core</artifactId>
|
||||||
|
|
|
@ -36,14 +36,14 @@ public class KeyPairVerifier {
|
||||||
try {
|
try {
|
||||||
privateKey = PemUtils.decodePrivateKey(privateKeyPem);
|
privateKey = PemUtils.decodePrivateKey(privateKeyPem);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new VerificationException("Failed to decode private key");
|
throw new VerificationException("Failed to decode private key", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
PublicKey publicKey;
|
PublicKey publicKey;
|
||||||
try {
|
try {
|
||||||
publicKey = PemUtils.decodePublicKey(publicKeyPem);
|
publicKey = PemUtils.decodePublicKey(publicKeyPem);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new VerificationException("Failed to decode public key");
|
throw new VerificationException("Failed to decode public key", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -17,9 +17,8 @@
|
||||||
|
|
||||||
package org.keycloak.jose.jwk;
|
package org.keycloak.jose.jwk;
|
||||||
|
|
||||||
import org.bouncycastle.jce.ECNamedCurveTable;
|
|
||||||
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
|
import org.keycloak.common.crypto.CryptoIntegration;
|
||||||
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
|
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.crypto.KeyType;
|
import org.keycloak.crypto.KeyType;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
@ -27,6 +26,7 @@ import org.keycloak.util.JsonSerialization;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.ECParameterSpec;
|
||||||
import java.security.spec.ECPoint;
|
import java.security.spec.ECPoint;
|
||||||
import java.security.spec.ECPublicKeySpec;
|
import java.security.spec.ECPublicKeySpec;
|
||||||
import java.security.spec.RSAPublicKeySpec;
|
import java.security.spec.RSAPublicKeySpec;
|
||||||
|
@ -99,9 +99,9 @@ public class JWKParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(name);
|
|
||||||
ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
|
|
||||||
ECPoint point = new ECPoint(x, y);
|
ECPoint point = new ECPoint(x, y);
|
||||||
|
ECParameterSpec params = CryptoIntegration.getProvider().createECParams(name);
|
||||||
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
|
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
|
||||||
|
|
||||||
KeyFactory kf = KeyFactory.getInstance("ECDSA");
|
KeyFactory kf = KeyFactory.getInstance("ECDSA");
|
||||||
|
|
|
@ -19,7 +19,6 @@ package org.keycloak;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
import org.keycloak.rule.CryptoInitRule;
|
import org.keycloak.rule.CryptoInitRule;
|
||||||
|
@ -34,10 +33,10 @@ public abstract class KeyPairVerifierTest {
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static CryptoInitRule cryptoInitRule = new CryptoInitRule();
|
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 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"
|
+ "H7VQ/XtjNxw0yjnFBilCnpK6yN9mDEHbBEzaRjtdrgVhkIejiaXFBP5MBhUQ5l9u\n" + "8E3IZC3E8pwDjVF0Z9u0R4lGeUg2k6O+NKumqIvxoLCTuG0zf53bctGsRd57LuFi\n"
|
||||||
+ "pgCkNyxvscOhulsbEMYrLwlb5bMGgx9v+RCnwvunNEb7RK+5pzP+iH1MRejRsX+U\n" + "7h9zHRn2gQhIl7SzG9GXebuPWr4KKwfMHWy0PEuQrsfWRXm9/dTEavbfNkv5E53z\n"
|
+ "pgCkNyxvscOhulsbEMYrLwlb5bMGgx9v+RCnwvunNEb7RK+5pzP+iH1MRejRsX+U\n" + "7h9zHRn2gQhIl7SzG9GXebuPWr4KKwfMHWy0PEuQrsfWRXm9/dTEavbfNkv5E53z\n"
|
||||||
+ "WXjWyf93ezkVhBX0YoXmf6UO7PAlvsrjno3TuwIDAQABAoIBAQC5iCAOcCtLemhp\n" + "bOlADwXgPtErFoNTROyMxjbrKrCCSIjniawj8oAvfiHq38Sx6ydBcDxREZjF/+wi\n"
|
+ "WXjWyf93ezkVhBX0YoXmf6UO7PAlvsrjno3TuwIDAQABAoIBAQC5iCAOcCtLemhp\n" + "bOlADwXgPtErFoNTROyMxjbrKrCCSIjniawj8oAvfiHq38Sx6ydBcDxREZjF/+wi\n"
|
||||||
|
|
|
@ -17,101 +17,44 @@
|
||||||
|
|
||||||
package org.keycloak;
|
package org.keycloak;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import org.junit.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.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
import org.keycloak.jose.jws.JWSBuilder;
|
import org.keycloak.jose.jws.JWSBuilder;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
|
import org.keycloak.rule.CryptoInitRule;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
import org.keycloak.util.TokenUtil;
|
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.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class RSAVerifierTest {
|
public abstract class RSAVerifierTest {
|
||||||
private static X509Certificate[] idpCertificates;
|
// private static X509Certificate[] idpCertificates;
|
||||||
private static KeyPair idpPair;
|
private static KeyPair idpPair;
|
||||||
private static KeyPair badPair;
|
private static KeyPair badPair;
|
||||||
private static KeyPair clientPair;
|
// private static KeyPair clientPair;
|
||||||
private static X509Certificate[] clientCertificateChain;
|
// private static X509Certificate[] clientCertificateChain;
|
||||||
private AccessToken token;
|
private AccessToken token;
|
||||||
|
|
||||||
public static X509Certificate generateTestCertificate(String subject, String issuer, KeyPair pair)
|
@ClassRule
|
||||||
throws CertificateException, InvalidKeyException, IOException,
|
public static CryptoInitRule cryptoInitRule = new CryptoInitRule();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setupCerts()
|
public static void setupCerts()
|
||||||
throws CertificateException, InvalidKeyException, IOException,
|
throws Exception
|
||||||
NoSuchAlgorithmException, NoSuchProviderException,
|
|
||||||
OperatorCreationException, SignatureException
|
|
||||||
{
|
{
|
||||||
|
// CryptoIntegration.init(ClassLoader.getSystemClassLoader());
|
||||||
badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||||
idpPair = 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
|
@Before
|
||||||
|
@ -124,21 +67,6 @@ public class RSAVerifierTest {
|
||||||
.addAccess("service").addRole("admin");
|
.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 {
|
public void testSimpleVerification() throws Exception {
|
||||||
String encoded = new JWSBuilder()
|
String encoded = new JWSBuilder()
|
||||||
|
@ -154,7 +82,6 @@ public class RSAVerifierTest {
|
||||||
return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "http://localhost:8080/auth/realm");
|
return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "http://localhost:8080/auth/realm");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
public void testSpeed() throws Exception
|
public void testSpeed() throws Exception
|
||||||
{
|
{
|
||||||
|
@ -176,8 +103,6 @@ public class RSAVerifierTest {
|
||||||
System.out.println("took: " + end);
|
System.out.println("took: " + end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadSignature() {
|
public void testBadSignature() {
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,12 @@
|
||||||
package org.keycloak.jose;
|
package org.keycloak.jose;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.jose.jws.JWSBuilder;
|
import org.keycloak.jose.jws.JWSBuilder;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.crypto.HMACProvider;
|
import org.keycloak.jose.jws.crypto.HMACProvider;
|
||||||
|
import org.keycloak.rule.CryptoInitRule;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
@ -31,7 +33,10 @@ import java.util.UUID;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class HmacTest {
|
public abstract class HmacTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static CryptoInitRule cryptoInitRule = new CryptoInitRule();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHmacSignatures() throws Exception {
|
public void testHmacSignatures() throws Exception {
|
||||||
|
@ -43,5 +48,4 @@ public class HmacTest {
|
||||||
Assert.assertTrue(HMACProvider.verify(input, secret));
|
Assert.assertTrue(HMACProvider.verify(input, secret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.common.util.BouncyIntegration;
|
import org.keycloak.common.util.BouncyIntegration;
|
||||||
|
@ -62,7 +61,7 @@ public abstract class JWKTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void publicRs256() throws Exception {
|
public void publicRs256() throws Exception {
|
||||||
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
KeyPair keyPair = KeyPairGenerator.getInstance("RSA", BouncyIntegration.PROVIDER ).generateKeyPair();
|
||||||
PublicKey publicKey = keyPair.getPublic();
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
X509Certificate certificate = generateV1SelfSignedCertificate(keyPair, "Test");
|
X509Certificate certificate = generateV1SelfSignedCertificate(keyPair, "Test");
|
||||||
|
|
||||||
|
@ -97,7 +96,7 @@ public abstract class JWKTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void publicRs256Chain() throws Exception {
|
public void publicRs256Chain() throws Exception {
|
||||||
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
KeyPair keyPair = KeyPairGenerator.getInstance("RSA", BouncyIntegration.PROVIDER).generateKeyPair();
|
||||||
PublicKey publicKey = keyPair.getPublic();
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
List<X509Certificate> certificates = Arrays.asList(generateV1SelfSignedCertificate(keyPair, "Test"), generateV1SelfSignedCertificate(keyPair, "Intermediate"));
|
List<X509Certificate> certificates = Arrays.asList(generateV1SelfSignedCertificate(keyPair, "Test"), generateV1SelfSignedCertificate(keyPair, "Intermediate"));
|
||||||
|
|
||||||
|
|
|
@ -17,30 +17,25 @@
|
||||||
|
|
||||||
package org.keycloak.util;
|
package org.keycloak.util;
|
||||||
|
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
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.KeyUse;
|
||||||
import org.keycloak.crypto.KeyWrapper;
|
import org.keycloak.crypto.KeyWrapper;
|
||||||
import org.keycloak.jose.jwk.*;
|
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 java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
|
||||||
public class JWKSUtilsTest {
|
public abstract class JWKSUtilsTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static CryptoInitRule cryptoInitRule = new CryptoInitRule();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void publicRs256() throws Exception {
|
public void publicRs256() throws Exception {
|
||||||
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
|
||||||
|
|
||||||
String kidRsa1 = "key1";
|
String kidRsa1 = "key1";
|
||||||
String kidRsa2 = "key2";
|
String kidRsa2 = "key2";
|
||||||
|
|
|
@ -2,10 +2,14 @@ package org.keycloak.crypto.def;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.ECParameterSpec;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
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.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.keycloak.common.crypto.CryptoProvider;
|
import org.keycloak.common.crypto.CryptoProvider;
|
||||||
import org.keycloak.common.crypto.CryptoProviderTypes;
|
import org.keycloak.common.crypto.CryptoProviderTypes;
|
||||||
|
@ -48,4 +52,10 @@ public class DefaultCryptoProvider implements CryptoProvider {
|
||||||
return new BCPemUtilsProvider();
|
return new BCPemUtilsProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ECParameterSpec createECParams(String curveName) {
|
||||||
|
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curveName);
|
||||||
|
return new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.keycloak.crypto.def.test;
|
||||||
|
|
||||||
|
import org.keycloak.RSAVerifierTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test with bouncycastle security provider
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DefaultCryptoRSAVerifierTest extends RSAVerifierTest {
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.crypto.def.test;
|
package org.keycloak.crypto.def.test;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.common.crypto.CryptoIntegration;
|
import org.keycloak.common.crypto.CryptoIntegration;
|
||||||
import org.keycloak.common.crypto.CryptoProviderTypes;
|
import org.keycloak.common.crypto.CryptoProviderTypes;
|
||||||
|
@ -12,6 +13,11 @@ import org.keycloak.jose.jwe.alg.JWEAlgorithmProvider;
|
||||||
*/
|
*/
|
||||||
public class DefaultCryptoUnitTest {
|
public class DefaultCryptoUnitTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
CryptoIntegration.init(ClassLoader.getSystemClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDefaultCrypto() throws Exception {
|
public void testDefaultCrypto() throws Exception {
|
||||||
JWEAlgorithmProvider jweAlg = CryptoIntegration.getProvider().getAlgorithmProvider(JWEAlgorithmProvider.class, CryptoProviderTypes.AES_KEY_WRAP_ALGORITHM_PROVIDER);
|
JWEAlgorithmProvider jweAlg = CryptoIntegration.getProvider().getAlgorithmProvider(JWEAlgorithmProvider.class, CryptoProviderTypes.AES_KEY_WRAP_ALGORITHM_PROVIDER);
|
||||||
|
|
|
@ -3,11 +3,20 @@ package org.keycloak.crypto.fips;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.SecureRandom;
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
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.jcajce.provider.BouncyCastleFipsProvider;
|
||||||
|
import org.bouncycastle.math.ec.ECCurve;
|
||||||
import org.keycloak.common.crypto.CryptoProvider;
|
import org.keycloak.common.crypto.CryptoProvider;
|
||||||
import org.keycloak.common.crypto.CryptoProviderTypes;
|
import org.keycloak.common.crypto.CryptoProviderTypes;
|
||||||
import org.keycloak.common.crypto.CertificateUtilsProvider;
|
import org.keycloak.common.crypto.CertificateUtilsProvider;
|
||||||
|
@ -51,4 +60,34 @@ public class FIPS1402Provider implements CryptoProvider {
|
||||||
public PemUtilsProvider getPemUtils() {
|
public PemUtilsProvider getPemUtils() {
|
||||||
return new BCFIPSPemUtilsProvider();
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package org.keycloak.crypto.fips.test;
|
package org.keycloak.crypto.fips.test;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.keycloak.jose.JWETest;
|
import org.keycloak.jose.JWETest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +7,5 @@ import org.keycloak.jose.JWETest;
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@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 {
|
public class FIPS1402JWETest extends JWETest {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.crypto.fips.test;
|
package org.keycloak.crypto.fips.test;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
import org.keycloak.jose.jwk.JWKTest;
|
import org.keycloak.jose.jwk.JWKTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +9,12 @@ import org.keycloak.jose.jwk.JWKTest;
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@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 {
|
public class FIPS1402JWKTest extends JWKTest {
|
||||||
|
|
||||||
|
@Ignore("Test not supported by BC FIPS")
|
||||||
|
@Test
|
||||||
|
public void publicEs256() throws Exception {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.crypto.fips.test;
|
package org.keycloak.crypto.fips.test;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Before;
|
||||||
import org.keycloak.KeyPairVerifierTest;
|
import org.keycloak.KeyPairVerifierTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,54 @@ import org.keycloak.KeyPairVerifierTest;
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
@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 {
|
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==";
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
||||||
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
||||||
<module name="org.keycloak.keycloak-common" />
|
<module name="org.keycloak.keycloak-common" />
|
||||||
<module name="org.bouncycastle" />
|
|
||||||
<module name="org.jboss.logging"/>
|
<module name="org.jboss.logging"/>
|
||||||
<module name="javax.api"/>
|
<module name="javax.api"/>
|
||||||
<module name="javax.activation.api"/>
|
<module name="javax.activation.api"/>
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
||||||
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
||||||
<module name="org.keycloak.keycloak-common"/>
|
<module name="org.keycloak.keycloak-common"/>
|
||||||
<module name="org.bouncycastle" />
|
|
||||||
<module name="org.jboss.logging"/>
|
<module name="org.jboss.logging"/>
|
||||||
<module name="javax.api"/>
|
<module name="javax.api"/>
|
||||||
<module name="javax.activation.api"/>
|
<module name="javax.activation.api"/>
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
||||||
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
||||||
<module name="org.keycloak.keycloak-common"/>
|
<module name="org.keycloak.keycloak-common"/>
|
||||||
<module name="org.bouncycastle" />
|
|
||||||
<module name="org.jboss.logging"/>
|
<module name="org.jboss.logging"/>
|
||||||
<module name="javax.api"/>
|
<module name="javax.api"/>
|
||||||
<module name="javax.activation.api"/>
|
<module name="javax.activation.api"/>
|
||||||
|
|
Loading…
Reference in a new issue