Fix various bugs and issues in crypto/elytron (#23102)

closes #23173
This commit is contained in:
David Anderson 2023-10-03 02:42:57 -05:00 committed by GitHub
parent fbae2251e1
commit ceea11d044
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 286 additions and 55 deletions

View file

@ -37,6 +37,7 @@ import java.util.List;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import org.jboss.logging.Logger;
import org.keycloak.common.crypto.CertificateUtilsProvider; import org.keycloak.common.crypto.CertificateUtilsProvider;
import org.wildfly.security.asn1.ASN1; import org.wildfly.security.asn1.ASN1;
import org.wildfly.security.asn1.DERDecoder; import org.wildfly.security.asn1.DERDecoder;
@ -60,6 +61,8 @@ import org.wildfly.security.x500.cert.X509CertificateExtension;
*/ */
public class ElytronCertificateUtils implements CertificateUtilsProvider { public class ElytronCertificateUtils implements CertificateUtilsProvider {
Logger log = Logger.getLogger(getClass());
/** /**
* Generates version 3 {@link java.security.cert.X509Certificate}. * Generates version 3 {@link java.security.cert.X509Certificate}.
* *
@ -249,16 +252,29 @@ public class ElytronCertificateUtils implements CertificateUtilsProvider {
case ASN1.UTF8_STRING_TYPE: case ASN1.UTF8_STRING_TYPE:
distPointUrls.add(der.decodeUtf8String()); distPointUrls.add(der.decodeUtf8String());
break; break;
case 0xa0: case 0xa0: // Decode CRLDistributionPoint FullName list
der.decodeImplicit(0xa0); der.startExplicit(0xa0);
byte[] edata = der.decodeOctetString(); break;
while(!Character.isLetterOrDigit(edata[0])) { case 0x86: // Decode CRLDistributionPoint FullName
edata = Arrays.copyOfRange(edata, 1, edata.length); der.decodeImplicit(0x86);
} distPointUrls.add(der.decodeOctetStringAsString());
distPointUrls.add(new String(edata)); log.debug("Adding Dist point name: " + distPointUrls.get(distPointUrls.size()-1));
break; break;
default: default:
der.skipElement(); der.skipElement();
}
// Check to see if there is another sequence to process
try {
if(!der.hasNextElement() && der.peekType() == ASN1.SEQUENCE_TYPE) {
der.startSequence();
} else if (!der.hasNextElement() && der.peekType() == 0xa0) {
der.startExplicit(0xa0);
}
} catch(Exception e) {
// Just log this error. Likely the Dist points have been parsed, but
// the end of the cert is failing to parse.
log.warn("There is an issue parsing the certificate for Distribution Points", e);
} }
} }

View file

@ -19,6 +19,7 @@ package org.keycloak.crypto.elytron;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import org.jboss.logging.Logger;
import org.keycloak.common.crypto.ECDSACryptoProvider; import org.keycloak.common.crypto.ECDSACryptoProvider;
import org.wildfly.security.asn1.DERDecoder; import org.wildfly.security.asn1.DERDecoder;
import org.wildfly.security.asn1.DEREncoder; import org.wildfly.security.asn1.DEREncoder;
@ -28,6 +29,8 @@ import org.wildfly.security.asn1.DEREncoder;
*/ */
public class ElytronECDSACryptoProvider implements ECDSACryptoProvider { public class ElytronECDSACryptoProvider implements ECDSACryptoProvider {
Logger log = Logger.getLogger(getClass());
@Override @Override
public byte[] concatenatedRSToASN1DER(final byte[] signature, int signLength) throws IOException { public byte[] concatenatedRSToASN1DER(final byte[] signature, int signLength) throws IOException {
int len = signLength / 2; int len = signLength / 2;
@ -45,6 +48,7 @@ public class ElytronECDSACryptoProvider implements ECDSACryptoProvider {
seq.startSequence(); seq.startSequence();
seq.encodeInteger(rBigInteger); seq.encodeInteger(rBigInteger);
seq.encodeInteger(sBigInteger); seq.encodeInteger(sBigInteger);
seq.endSequence();
return seq.getEncoded(); return seq.getEncoded();
@ -56,13 +60,35 @@ public class ElytronECDSACryptoProvider implements ECDSACryptoProvider {
DERDecoder der = new DERDecoder(derEncodedSignatureValue); DERDecoder der = new DERDecoder(derEncodedSignatureValue);
der.startSequence(); der.startSequence();
byte[] r = der.decodeInteger().toByteArray(); byte[] r = convertToBytes(der.decodeInteger(),len);
byte[] s = der.decodeInteger().toByteArray(); byte[] s = convertToBytes(der.decodeInteger(),len);
der.endSequence();
byte[] concatenatedSignatureValue = new byte[signLength]; byte[] concatenatedSignatureValue = new byte[signLength];
System.arraycopy(r, 0, concatenatedSignatureValue, 0, len); System.arraycopy(r, 0, concatenatedSignatureValue, 0, len);
System.arraycopy(s, 0, concatenatedSignatureValue, len, len); System.arraycopy(s, 0, concatenatedSignatureValue, len, len);
return concatenatedSignatureValue; return concatenatedSignatureValue;
} }
// If byte array length doesn't match expected length, copy to new
// byte array of the expected length
private byte[] convertToBytes(BigInteger decodeInteger, int len) {
byte[] bytes = decodeInteger.toByteArray();
if(len < bytes.length) {
log.debug("Decoded integer byte length greater than expected.");
byte[] t = new byte[len];
System.arraycopy(bytes, bytes.length - len, t, 0, len);
bytes = t;
} else if (len > bytes.length) {
log.debug("Decoded integer byte length less than expected.");
byte[] t = new byte[len];
System.arraycopy(bytes, 0, t, len - bytes.length, bytes.length);
bytes = t;
}
return bytes;
}
} }

View file

@ -16,24 +16,42 @@
*/ */
package org.keycloak.crypto.elytron; package org.keycloak.crypto.elytron;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.cert.CRLReason; import java.security.cert.CRLReason;
import java.security.cert.CertPath;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
import java.security.cert.PKIXRevocationChecker;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.EnumSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.common.util.PemUtils;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.utils.OCSPProvider; import org.keycloak.utils.OCSPProvider;
import org.wildfly.security.asn1.ASN1; import org.wildfly.security.asn1.ASN1;
@ -61,27 +79,42 @@ public class ElytronOCSPProvider extends OCSPProvider {
* @throws CertPathValidatorException * @throws CertPathValidatorException
*/ */
@Override @Override
protected OCSPRevocationStatus check(KeycloakSession session, X509Certificate cert, X509Certificate issuerCertificate, List<URI> responderURIs, X509Certificate responderCert, Date date) throws CertPathValidatorException { protected OCSPRevocationStatus check(KeycloakSession session, X509Certificate cert,
X509Certificate issuerCertificate, List<URI> responderURIs, X509Certificate responderCert, Date date)
throws CertPathValidatorException {
if (responderURIs == null || responderURIs.size() == 0) if (responderURIs == null || responderURIs.size() == 0)
throw new IllegalArgumentException("Need at least one responder"); throw new IllegalArgumentException("Need at least one responder");
try { try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, "pass".toCharArray()); trustStore.load(null, "pass".toCharArray());
trustStore.setCertificateEntry("trust", cert); trustStore.setCertificateEntry("trust", issuerCertificate);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
X509RevocationTrustManager trustMgr = X509RevocationTrustManager.builder() CertificateFactory cf = CertificateFactory.getInstance("X.509");
.setOcspResponderCert(responderCert) CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
.setTrustStore(trustStore) PKIXRevocationChecker rc = (PKIXRevocationChecker) cpb.getRevocationChecker();
.setTrustManagerFactory(trustManagerFactory) X509CertSelector certSelector = new X509CertSelector();
.build()
;
X509Certificate[] certs = { cert }; X509Certificate[] certs = { cert };
trustMgr.checkClientTrusted(certs, cert.getType()); certSelector.setCertificate(cert);
} catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException e) { certSelector.setCertificateValid(date);
CertPath cp = cf.generateCertPath(Arrays.asList(certs));
PKIXParameters params = new PKIXBuilderParameters(trustStore, certSelector);
rc.setOcspResponder(responderURIs.get(0));
rc.setOcspResponderCert(responderCert);
rc.setOptions(EnumSet.noneOf(PKIXRevocationChecker.Option.class));
params.setRevocationEnabled(false);
params.addCertPathChecker(rc);
PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) cpv.validate(cp, params);
logger.debug("Certificate validated by CA: " + result.getTrustAnchor().getCAName());
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | CertificateException | IOException
| KeyStoreException e) {
logger.warn("OSCP Response check failed.", e); logger.warn("OSCP Response check failed.", e);
return unknownStatus(); return unknownStatus();
} }
@ -155,6 +188,7 @@ public class ElytronOCSPProvider extends OCSPProvider {
} }
} }
logger.warn("OCSP Responder URIs" + Arrays.toString(responderURIs.toArray()));
return responderURIs; return responderURIs;
} }
} }

View file

@ -39,7 +39,7 @@ import org.wildfly.security.x500.principal.X500AttributePrincipalDecoder;
*/ */
public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractorProvider { public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractorProvider {
private static final Logger logger = Logger.getLogger(ElytronUserIdentityExtractorProvider.class.getName()); private Logger log = Logger.getLogger(this.getClass());
class X500NameRDNExtractorElytronProvider extends X500NameRDNExtractor { class X500NameRDNExtractorElytronProvider extends X500NameRDNExtractor {
@ -47,8 +47,13 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor
Function<X509Certificate[],Principal> x500Name; Function<X509Certificate[],Principal> x500Name;
public X500NameRDNExtractorElytronProvider(String attrName, Function<X509Certificate[], Principal> x500Name) { public X500NameRDNExtractorElytronProvider(String attrName, Function<X509Certificate[], Principal> x500Name) {
//this.x500NameStyle = BCStyle.INSTANCE.attrNameToOID(attrName); // The OidsUtil fails to map 'EmailAddress', instead 'E' is mapped to the OID.
// TODO: Open an issue with wildfly-elytron to include 'EmailAddress' in the oid mapping
if(attrName.equals("EmailAddress")) {
attrName = "E";
}
this.x500NameStyle = OidsUtil.attributeNameToOid(OidsUtil.Category.RDN, attrName); this.x500NameStyle = OidsUtil.attributeNameToOid(OidsUtil.Category.RDN, attrName);
log.debug("Attribute Name: " + attrName + " X500NameStyle OID: " + x500NameStyle);
this.x500Name = x500Name; this.x500Name = x500Name;
} }
@ -59,6 +64,7 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor
throw new IllegalArgumentException(); throw new IllegalArgumentException();
Principal name = x500Name.apply(certs); Principal name = x500Name.apply(certs);
log.debug("Principal Name " + name.getName());
X500AttributePrincipalDecoder xDecoder = new X500AttributePrincipalDecoder(x500NameStyle); X500AttributePrincipalDecoder xDecoder = new X500AttributePrincipalDecoder(x500NameStyle);
String cn = xDecoder.apply(name); String cn = xDecoder.apply(name);
@ -95,13 +101,14 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor
} }
String subjectName = null; String subjectName = null;
logger.info("SubjPrinc " + certs[0].getSubjectX500Principal()); log.debug("SubjPrinc " + certs[0].getSubjectX500Principal());
Collection<List<?>> subjectAlternativeNames; Collection<List<?>> subjectAlternativeNames;
try { try {
subjectAlternativeNames = certs[0].getSubjectAlternativeNames(); subjectAlternativeNames = certs[0].getSubjectAlternativeNames();
if (subjectAlternativeNames == null) { if (subjectAlternativeNames == null) {
return null; return null;
} }
log.info(Arrays.toString(subjectAlternativeNames.toArray()));
for (List<?> sbjAltName : subjectAlternativeNames) { for (List<?> sbjAltName : subjectAlternativeNames) {
if (sbjAltName == null) if (sbjAltName == null)
continue; continue;
@ -109,15 +116,13 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor
Integer nameType = (Integer) sbjAltName.get(0); Integer nameType = (Integer) sbjAltName.get(0);
if (nameType == generalName) { if (nameType == generalName) {
logger.info("sbjAltName Type " + nameType);
logger.info("sbjAltName[1]: " + sbjAltName.get(1));
Object sbjObj = sbjAltName.get(1); Object sbjObj = sbjAltName.get(1);
switch (nameType) { switch (nameType) {
case GeneralName.RFC_822_NAME: case GeneralName.RFC_822_NAME:
case GeneralName.DNS_NAME: case GeneralName.DNS_NAME:
case GeneralName.DIRECTORY_NAME: case GeneralName.DIRECTORY_NAME:
case GeneralName.URI_NAME:
subjectName = (String) sbjObj; subjectName = (String) sbjObj;
break; break;
case GeneralName.OTHER_NAME: case GeneralName.OTHER_NAME:
@ -126,12 +131,12 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor
boolean upnOidFound = false; boolean upnOidFound = false;
while (derDecoder.hasNextElement() && !upnOidFound) { while (derDecoder.hasNextElement() && !upnOidFound) {
int asn1Type = derDecoder.peekType(); int asn1Type = derDecoder.peekType();
logger.info("ASN.1 Type: " + derDecoder.peekType()); log.debug("ASN.1 Type: " + derDecoder.peekType());
switch (asn1Type) { switch (asn1Type) {
case ASN1.OBJECT_IDENTIFIER_TYPE: case ASN1.OBJECT_IDENTIFIER_TYPE:
String oid = derDecoder.decodeObjectIdentifier(); String oid = derDecoder.decodeObjectIdentifier();
logger.info("OID: " + oid); log.debug("OID: " + oid);
if(UPN_OID.equals(oid)) { if(UPN_OID.equals(oid)) {
derDecoder.decodeImplicit(160); derDecoder.decodeImplicit(160);
byte[] sb = derDecoder.drainElementValue(); byte[] sb = derDecoder.drainElementValue();
@ -154,22 +159,28 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor
case ASN1.OCTET_STRING_TYPE: case ASN1.OCTET_STRING_TYPE:
subjectName = derDecoder.decodeOctetStringAsString(); subjectName = derDecoder.decodeOctetStringAsString();
break; break;
case 0xa0:
derDecoder.startExplicit(asn1Type);
break;
case ASN1.SEQUENCE_TYPE:
derDecoder.startSequence();
default:
derDecoder.skipElement();
} }
} }
logger.info("Subject Alt Name: " + subjectName);
} }
} }
} }
} catch (CertificateParsingException | UnsupportedEncodingException e) { } catch (CertificateParsingException | UnsupportedEncodingException e) {
// TODO Auto-generated catch block log.error("Failed to parse Subject Name:",e);
e.printStackTrace();
} }
log.debug("Subject Alt Name: " + subjectName);
return subjectName; return subjectName;
} }
} }

View file

@ -18,18 +18,22 @@ package org.keycloak.crypto.elytron.test;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.List; import java.util.List;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import org.junit.Test; import org.junit.Test;
import org.keycloak.common.util.PemUtils;
import org.keycloak.crypto.elytron.ElytronCertificateUtils; import org.keycloak.crypto.elytron.ElytronCertificateUtils;
import org.wildfly.security.x500.GeneralName; import org.wildfly.security.x500.GeneralName;
import org.wildfly.security.x500.cert.CRLDistributionPoint; import org.wildfly.security.x500.cert.CRLDistributionPoint;
@ -46,9 +50,9 @@ public class CRLDistributionPointTest {
@Test @Test
public void getCrlDistPoint() throws CertificateException, NoSuchAlgorithmException, IOException { public void getCrlDistPoint() throws CertificateException, NoSuchAlgorithmException, IOException {
X509Certificate cert = createCRLcert(); X509Certificate cert = createCRLcert(1,1);
List<String> expect = new ArrayList<>(); List<String> expect = new ArrayList<>();
expect.add("http://crl.test.com"); expect.add("http://crl0.test0.com");
ElytronCertificateUtils bcutil = new ElytronCertificateUtils(); ElytronCertificateUtils bcutil = new ElytronCertificateUtils();
@ -58,16 +62,67 @@ public class CRLDistributionPointTest {
} }
private X509Certificate createCRLcert() throws CertificateException, NoSuchAlgorithmException { @Test
public void getCrlDistPointMultiNames() throws CertificateException, NoSuchAlgorithmException, IOException {
X509Certificate cert = createCRLcert(1,2);
List<String> expect = new ArrayList<>();
expect.add("http://crl0.test0.com");
expect.add("http://crl0.test1.com");
ElytronCertificateUtils bcutil = new ElytronCertificateUtils();
List<String> crldp = bcutil.getCRLDistributionPoints(cert);
assertArrayEquals(expect.toArray(), crldp.toArray());
}
@Test
public void getMultiCrlDistPointMultiNames() throws CertificateException, NoSuchAlgorithmException, IOException {
X509Certificate cert = createCRLcert(2,2);
List<String> expect = new ArrayList<>();
expect.add("http://crl0.test0.com");
expect.add("http://crl0.test1.com");
expect.add("http://crl1.test0.com");
expect.add("http://crl1.test1.com");
ElytronCertificateUtils bcutil = new ElytronCertificateUtils();
List<String> crldp = bcutil.getCRLDistributionPoints(cert);
assertArrayEquals(expect.toArray(), crldp.toArray());
}
@Test
public void revokedCertCRLDistTest() throws CertificateException, IOException {
X509Certificate cert = revokedCert();
List<String> expect = new ArrayList<>();
expect.add("http://localhost:8889/empty.crl");
expect.add("http://localhost:8889/intermediate-ca.crl");
ElytronCertificateUtils bcutil = new ElytronCertificateUtils();
List<String> crldp = bcutil.getCRLDistributionPoints(cert);
assertArrayEquals(expect.toArray(), crldp.toArray());
}
private X509Certificate createCRLcert(int crldistcount, int namecount) throws CertificateException, NoSuchAlgorithmException {
X500Principal dn = new X500Principal("CN=testuser,OU=UNIT,O=TST"); X500Principal dn = new X500Principal("CN=testuser,OU=UNIT,O=TST");
List<CRLDistributionPoint> distributionPoints = new ArrayList<>(); List<CRLDistributionPoint> distributionPoints = new ArrayList<>();
for(int x = 0; x<crldistcount;x++) {
List<GeneralName> fullName = new ArrayList<>(); List<GeneralName> fullName = new ArrayList<>();
fullName.add(new GeneralName.URIName("http://crl.test.com")); for(int y = 0; y<namecount; y++) {
fullName.add(new GeneralName.URIName("http://crl"+x+".test"+y+".com"));
}
DistributionPointName distributionPoint = new FullNameDistributionPointName(fullName); DistributionPointName distributionPoint = new FullNameDistributionPointName(fullName);
CRLDistributionPoint arg0 = new CRLDistributionPoint(distributionPoint, null, null); CRLDistributionPoint arg0 = new CRLDistributionPoint(distributionPoint, null, null);
distributionPoints.add(arg0); distributionPoints.add(arg0);
}
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").genKeyPair(); KeyPair keyPair = KeyPairGenerator.getInstance("RSA").genKeyPair();
X509CertificateBuilder cbuilder = new X509CertificateBuilder() X509CertificateBuilder cbuilder = new X509CertificateBuilder()
.setSubjectDn(dn) .setSubjectDn(dn)
@ -83,6 +138,16 @@ public class CRLDistributionPointTest {
return cbuilder.build(); return cbuilder.build();
} }
X509Certificate revokedCert() throws CertificateException {
String certStr = "-----BEGIN CERTIFICATE-----\n" +
"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"
+ "\n-----END CERTIFICATE-----";
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certStr.getBytes()));
}
} }

View file

@ -42,9 +42,13 @@ public class ElytronHmacTest extends HmacTest {
SecureRandom random = isWindows() ? SecureRandom.getInstance("Windows-PRNG") : SecureRandom.getInstance("NativePRNG"); SecureRandom random = isWindows() ? SecureRandom.getInstance("Windows-PRNG") : SecureRandom.getInstance("NativePRNG");
random.setSeed(UUID.randomUUID().toString().getBytes()); random.setSeed(UUID.randomUUID().toString().getBytes());
keygen.init(random); keygen.init(random);
SecretKey secretKey = keygen.generateKey(); SecretKey secret = keygen.generateKey();
testHMACSignAndVerify(secretKey, "testHmacSignaturesUsingKeyGen"); 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));
} }
private boolean isWindows(){ private boolean isWindows(){
return System.getProperty("os.name").startsWith("Windows"); return System.getProperty("os.name").startsWith("Windows");

View file

@ -30,8 +30,6 @@ import org.keycloak.common.crypto.CryptoIntegration;
import org.keycloak.common.util.KeystoreUtil; import org.keycloak.common.util.KeystoreUtil;
import org.keycloak.rule.CryptoInitRule; import org.keycloak.rule.CryptoInitRule;
import static org.hamcrest.MatcherAssert.assertThat;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/ */
@ -44,7 +42,7 @@ public class ElytronKeyStoreTypesTest {
@Test @Test
public void testKeystoreFormats() { public void testKeystoreFormats() {
Set<KeystoreUtil.KeystoreFormat> supportedKeystoreFormats = CryptoIntegration.getProvider().getSupportedKeyStoreTypes().collect(Collectors.toSet()); Set<KeystoreUtil.KeystoreFormat> supportedKeystoreFormats = CryptoIntegration.getProvider().getSupportedKeyStoreTypes().collect(Collectors.toSet());
assertThat(supportedKeystoreFormats, Matchers.containsInAnyOrder( Assert.assertThat(supportedKeystoreFormats, Matchers.containsInAnyOrder(
KeystoreUtil.KeystoreFormat.JKS, KeystoreUtil.KeystoreFormat.JKS,
KeystoreUtil.KeystoreFormat.PKCS12 KeystoreUtil.KeystoreFormat.PKCS12
)); ));

View file

@ -18,10 +18,14 @@ package org.keycloak.crypto.elytron.test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.common.crypto.CryptoIntegration;
import org.keycloak.common.crypto.PemUtilsProvider;
import org.keycloak.rule.CryptoInitRule; import org.keycloak.rule.CryptoInitRule;
public class ElytronPemUtilsTest { public class ElytronPemUtilsTest {
@ -42,5 +46,26 @@ public class ElytronPemUtilsTest {
String encoded = org.keycloak.common.util.PemUtils.generateThumbprint(test, "SHA-256"); String encoded = org.keycloak.common.util.PemUtils.generateThumbprint(test, "SHA-256");
assertEquals(43, encoded.length()); assertEquals(43, encoded.length());
} }
@Test
public void testenocdedecode() throws NoSuchAlgorithmException, NoSuchProviderException {
PemUtilsProvider pemutil = CryptoIntegration.getProvider().getPemUtils();
KeyPair keypair = CryptoIntegration.getProvider().getKeyPairGen("RSA").generateKeyPair();
String pem = pemutil.encodeKey(keypair.getPrivate());
Object decodekey = pemutil.decodePrivateKey(pem);
}
@Test
public void testtrkey() {
String key = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKtWsK5O0CtuBpnMvWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfdQ2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5SZ5z+na+M7Y2OxIBVxYRAxWEnfUvAgMBAAECgYB+Y7yBWHIHF2qXGYi6CVvPxtyNBuFcktHYShLyeBNeY3VujYv3QzSZQpJ1zuoXXQuARMHOovyNiVAhu357pMfx9wSkoKNSXKrQx/+9Vt9lI1pXJxjXedPOjbuI/JZAcrk0u4nOfXG/HGtR5cjoDZYWkYQEtsePCnHlZAb0D7axwQJBAO92f00Tvkc9NU/EGqwR3bPXRMqSX0JnG7XRBvLeJBCZYsQn0s2bLdpy8qsTeAyJg1ZvrEc8qIio5HVqzsvbhpMCQQC3K9A6UK+vmQCNWqsQpdqWPRPN7CPB67FzSmyS8CtMjY6jTvSHrkamggotz2N/5QDr1xG2q7A/3dpkq1bTpTx1AkAXZjjiSz+Yrn57IOqKTeSgIjTypoLwdirbBWXsbZCQnqxsBogu1y8P3ZOg6/IbJ4TR+W+YNnExiW9pmdpDSVxJAkEAplTq6YmLf/F4RuQmox94tyUPbtcYQWg942uZ3HSrXQDOng18kBj5nwpHJAJHYEQb6g2K0E5n5hcX0oKkfdx2YQJAcSKAmFiD7KQ6+vVqJlQwVPvYdTSOeZB7YVV6S4b4slS3ZObsa0yNMWgal/QnCtW5k3f185gCWj6dOLGB5btfxg==";
PemUtilsProvider pemutil = CryptoIntegration.getProvider().getPemUtils();
pemutil.decodePrivateKey(key);
}
} }

View file

@ -0,0 +1,52 @@
package org.keycloak.crypto.elytron.test;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.PSSParameterSpec;
import org.junit.Test;
import org.keycloak.common.crypto.CryptoIntegration;
import org.keycloak.crypto.JavaAlgorithm;
import org.keycloak.crypto.KeyWrapper;
public class ElytronSignatureAlgTest {
private byte[] data = "Test String to Encrypt".getBytes();
@Test
public void signatureDefaultAlg() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, InvalidAlgorithmParameterException, InvalidKeySpecException {
KeyPair keyPair = KeyPairGenerator.getInstance("RSASSA-PSS").genKeyPair();
KeyWrapper key = new KeyWrapper();
//key.setPrivateKey(keyPair.getPrivate());
key.setAlgorithm("PS256");
KeySpec kspec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
key.setPrivateKey(KeyFactory.getInstance("RSASSA-PSS").generatePrivate(kspec));
Signature signature = Signature.getInstance("RSASSA-PSS");
MGF1ParameterSpec ps = MGF1ParameterSpec.SHA256;
AlgorithmParameterSpec params = new PSSParameterSpec(ps.getDigestAlgorithm(), "MGF1", ps, 32, 1);
signature.setParameter(params);
signature.initSign(keyPair.getPrivate());
//signature.initSign((PrivateKey) key.getPrivateKey());
signature.update(data);
System.out.println(signature.getProvider() + " Alg ###########");
if(signature.getAlgorithm().equals("RSASSA-PSS")) {
}
signature.sign();
}
}