From ceea11d044e05ef7dfdc2e6638ee1eed77b3926b Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 3 Oct 2023 02:42:57 -0500 Subject: [PATCH] Fix various bugs and issues in crypto/elytron (#23102) closes #23173 --- .../elytron/ElytronCertificateUtils.java | 30 +++++-- .../elytron/ElytronECDSACryptoProvider.java | 30 ++++++- .../crypto/elytron/ElytronOCSPProvider.java | 72 ++++++++++++----- .../ElytronUserIdentityExtractorProvider.java | 39 +++++---- .../test/CRLDistributionPointTest.java | 81 +++++++++++++++++-- .../crypto/elytron/test/ElytronHmacTest.java | 8 +- .../test/ElytronKeyStoreTypesTest.java | 4 +- .../elytron/test/ElytronPemUtilsTest.java | 25 ++++++ .../elytron/test/ElytronSignatureAlgTest.java | 52 ++++++++++++ 9 files changed, 286 insertions(+), 55 deletions(-) create mode 100644 crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java diff --git a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronCertificateUtils.java b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronCertificateUtils.java index 0bf862b937..88add31161 100644 --- a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronCertificateUtils.java +++ b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronCertificateUtils.java @@ -37,6 +37,7 @@ import java.util.List; import javax.security.auth.x500.X500Principal; +import org.jboss.logging.Logger; import org.keycloak.common.crypto.CertificateUtilsProvider; import org.wildfly.security.asn1.ASN1; import org.wildfly.security.asn1.DERDecoder; @@ -60,6 +61,8 @@ import org.wildfly.security.x500.cert.X509CertificateExtension; */ public class ElytronCertificateUtils implements CertificateUtilsProvider { + Logger log = Logger.getLogger(getClass()); + /** * Generates version 3 {@link java.security.cert.X509Certificate}. * @@ -249,16 +252,29 @@ public class ElytronCertificateUtils implements CertificateUtilsProvider { case ASN1.UTF8_STRING_TYPE: distPointUrls.add(der.decodeUtf8String()); break; - case 0xa0: - der.decodeImplicit(0xa0); - byte[] edata = der.decodeOctetString(); - while(!Character.isLetterOrDigit(edata[0])) { - edata = Arrays.copyOfRange(edata, 1, edata.length); - } - distPointUrls.add(new String(edata)); + case 0xa0: // Decode CRLDistributionPoint FullName list + der.startExplicit(0xa0); + break; + case 0x86: // Decode CRLDistributionPoint FullName + der.decodeImplicit(0x86); + distPointUrls.add(der.decodeOctetStringAsString()); + log.debug("Adding Dist point name: " + distPointUrls.get(distPointUrls.size()-1)); break; default: 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); } } diff --git a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronECDSACryptoProvider.java b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronECDSACryptoProvider.java index ca75b06d02..b5f296ebc3 100644 --- a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronECDSACryptoProvider.java +++ b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronECDSACryptoProvider.java @@ -19,6 +19,7 @@ package org.keycloak.crypto.elytron; import java.io.IOException; import java.math.BigInteger; +import org.jboss.logging.Logger; import org.keycloak.common.crypto.ECDSACryptoProvider; import org.wildfly.security.asn1.DERDecoder; import org.wildfly.security.asn1.DEREncoder; @@ -28,6 +29,8 @@ import org.wildfly.security.asn1.DEREncoder; */ public class ElytronECDSACryptoProvider implements ECDSACryptoProvider { + Logger log = Logger.getLogger(getClass()); + @Override public byte[] concatenatedRSToASN1DER(final byte[] signature, int signLength) throws IOException { int len = signLength / 2; @@ -45,6 +48,7 @@ public class ElytronECDSACryptoProvider implements ECDSACryptoProvider { seq.startSequence(); seq.encodeInteger(rBigInteger); seq.encodeInteger(sBigInteger); + seq.endSequence(); return seq.getEncoded(); @@ -56,13 +60,35 @@ public class ElytronECDSACryptoProvider implements ECDSACryptoProvider { DERDecoder der = new DERDecoder(derEncodedSignatureValue); der.startSequence(); - byte[] r = der.decodeInteger().toByteArray(); - byte[] s = der.decodeInteger().toByteArray(); + byte[] r = convertToBytes(der.decodeInteger(),len); + byte[] s = convertToBytes(der.decodeInteger(),len); + der.endSequence(); byte[] concatenatedSignatureValue = new byte[signLength]; + System.arraycopy(r, 0, concatenatedSignatureValue, 0, len); System.arraycopy(s, 0, concatenatedSignatureValue, len, len); 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; + } + } diff --git a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronOCSPProvider.java b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronOCSPProvider.java index 7054578da4..f312ffa3c6 100644 --- a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronOCSPProvider.java +++ b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronOCSPProvider.java @@ -16,24 +16,42 @@ */ package org.keycloak.crypto.elytron; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; +import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; 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.CertPathValidatorResult; +import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; 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.util.Arrays; import java.util.Date; +import java.util.EnumSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import javax.net.ssl.TrustManagerFactory; import org.jboss.logging.Logger; +import org.keycloak.common.util.PemUtils; import org.keycloak.models.KeycloakSession; import org.keycloak.utils.OCSPProvider; import org.wildfly.security.asn1.ASN1; @@ -61,31 +79,46 @@ public class ElytronOCSPProvider extends OCSPProvider { * @throws CertPathValidatorException */ @Override - protected OCSPRevocationStatus check(KeycloakSession session, X509Certificate cert, X509Certificate issuerCertificate, List responderURIs, X509Certificate responderCert, Date date) throws CertPathValidatorException { + protected OCSPRevocationStatus check(KeycloakSession session, X509Certificate cert, + X509Certificate issuerCertificate, List responderURIs, X509Certificate responderCert, Date date) + throws CertPathValidatorException { if (responderURIs == null || responderURIs.size() == 0) throw new IllegalArgumentException("Need at least one responder"); - try { + try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - trustStore.load(null,"pass".toCharArray()); - trustStore.setCertificateEntry("trust", cert); - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - - - X509RevocationTrustManager trustMgr = X509RevocationTrustManager.builder() - .setOcspResponderCert(responderCert) - .setTrustStore(trustStore) - .setTrustManagerFactory(trustManagerFactory) - .build() - ; - - X509Certificate[] certs = { cert }; - trustMgr.checkClientTrusted(certs, cert.getType()); - } catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException e) { + trustStore.load(null, "pass".toCharArray()); + trustStore.setCertificateEntry("trust", issuerCertificate); + + CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX"); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + PKIXRevocationChecker rc = (PKIXRevocationChecker) cpb.getRevocationChecker(); + X509CertSelector certSelector = new X509CertSelector(); + + X509Certificate[] certs = { cert }; + certSelector.setCertificate(cert); + 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); return unknownStatus(); } - + return new OCSPRevocationStatus() { @Override @@ -102,7 +135,7 @@ public class ElytronOCSPProvider extends OCSPProvider { public CRLReason getRevocationReason() { return null; } - + }; } @@ -155,6 +188,7 @@ public class ElytronOCSPProvider extends OCSPProvider { } } + logger.warn("OCSP Responder URIs" + Arrays.toString(responderURIs.toArray())); return responderURIs; } } diff --git a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronUserIdentityExtractorProvider.java b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronUserIdentityExtractorProvider.java index eb5c428332..57ddba578c 100644 --- a/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronUserIdentityExtractorProvider.java +++ b/crypto/elytron/src/main/java/org/keycloak/crypto/elytron/ElytronUserIdentityExtractorProvider.java @@ -39,7 +39,7 @@ import org.wildfly.security.x500.principal.X500AttributePrincipalDecoder; */ 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 { @@ -47,8 +47,13 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor Function x500Name; public X500NameRDNExtractorElytronProvider(String attrName, Function 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); + log.debug("Attribute Name: " + attrName + " X500NameStyle OID: " + x500NameStyle); this.x500Name = x500Name; } @@ -59,6 +64,7 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor throw new IllegalArgumentException(); Principal name = x500Name.apply(certs); + log.debug("Principal Name " + name.getName()); X500AttributePrincipalDecoder xDecoder = new X500AttributePrincipalDecoder(x500NameStyle); String cn = xDecoder.apply(name); @@ -95,13 +101,14 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor } String subjectName = null; - logger.info("SubjPrinc " + certs[0].getSubjectX500Principal()); + log.debug("SubjPrinc " + certs[0].getSubjectX500Principal()); Collection> subjectAlternativeNames; try { subjectAlternativeNames = certs[0].getSubjectAlternativeNames(); if (subjectAlternativeNames == null) { return null; } + log.info(Arrays.toString(subjectAlternativeNames.toArray())); for (List sbjAltName : subjectAlternativeNames) { if (sbjAltName == null) continue; @@ -109,15 +116,13 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor Integer nameType = (Integer) sbjAltName.get(0); if (nameType == generalName) { - logger.info("sbjAltName Type " + nameType); - logger.info("sbjAltName[1]: " + sbjAltName.get(1)); - Object sbjObj = sbjAltName.get(1); switch (nameType) { case GeneralName.RFC_822_NAME: case GeneralName.DNS_NAME: case GeneralName.DIRECTORY_NAME: + case GeneralName.URI_NAME: subjectName = (String) sbjObj; break; case GeneralName.OTHER_NAME: @@ -126,12 +131,12 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor boolean upnOidFound = false; while (derDecoder.hasNextElement() && !upnOidFound) { int asn1Type = derDecoder.peekType(); - logger.info("ASN.1 Type: " + derDecoder.peekType()); + log.debug("ASN.1 Type: " + derDecoder.peekType()); switch (asn1Type) { case ASN1.OBJECT_IDENTIFIER_TYPE: String oid = derDecoder.decodeObjectIdentifier(); - logger.info("OID: " + oid); + log.debug("OID: " + oid); if(UPN_OID.equals(oid)) { derDecoder.decodeImplicit(160); byte[] sb = derDecoder.drainElementValue(); @@ -154,22 +159,28 @@ public class ElytronUserIdentityExtractorProvider extends UserIdentityExtractor case ASN1.OCTET_STRING_TYPE: subjectName = derDecoder.decodeOctetStringAsString(); 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) { - // TODO Auto-generated catch block - e.printStackTrace(); + log.error("Failed to parse Subject Name:",e); } - + + log.debug("Subject Alt Name: " + subjectName); return subjectName; } } diff --git a/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/CRLDistributionPointTest.java b/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/CRLDistributionPointTest.java index d42e60483c..6f5fb4df32 100644 --- a/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/CRLDistributionPointTest.java +++ b/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/CRLDistributionPointTest.java @@ -18,18 +18,22 @@ package org.keycloak.crypto.elytron.test; import static org.junit.Assert.assertArrayEquals; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Base64; import java.util.List; import javax.security.auth.x500.X500Principal; import org.junit.Test; +import org.keycloak.common.util.PemUtils; import org.keycloak.crypto.elytron.ElytronCertificateUtils; import org.wildfly.security.x500.GeneralName; import org.wildfly.security.x500.cert.CRLDistributionPoint; @@ -46,9 +50,9 @@ public class CRLDistributionPointTest { @Test public void getCrlDistPoint() throws CertificateException, NoSuchAlgorithmException, IOException { - X509Certificate cert = createCRLcert(); + X509Certificate cert = createCRLcert(1,1); List expect = new ArrayList<>(); - expect.add("http://crl.test.com"); + expect.add("http://crl0.test0.com"); 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 expect = new ArrayList<>(); + expect.add("http://crl0.test0.com"); + expect.add("http://crl0.test1.com"); + + ElytronCertificateUtils bcutil = new ElytronCertificateUtils(); + List crldp = bcutil.getCRLDistributionPoints(cert); + + assertArrayEquals(expect.toArray(), crldp.toArray()); + + } + + @Test + public void getMultiCrlDistPointMultiNames() throws CertificateException, NoSuchAlgorithmException, IOException { + + X509Certificate cert = createCRLcert(2,2); + List 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 crldp = bcutil.getCRLDistributionPoints(cert); + + assertArrayEquals(expect.toArray(), crldp.toArray()); + + } + + @Test + public void revokedCertCRLDistTest() throws CertificateException, IOException { + X509Certificate cert = revokedCert(); + List expect = new ArrayList<>(); + expect.add("http://localhost:8889/empty.crl"); + expect.add("http://localhost:8889/intermediate-ca.crl"); + + ElytronCertificateUtils bcutil = new ElytronCertificateUtils(); + List 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"); List distributionPoints = new ArrayList<>(); - List fullName = new ArrayList<>(); - fullName.add(new GeneralName.URIName("http://crl.test.com")); - DistributionPointName distributionPoint = new FullNameDistributionPointName(fullName); - CRLDistributionPoint arg0 = new CRLDistributionPoint(distributionPoint, null, null); - distributionPoints.add(arg0); + for(int x = 0; x fullName = new ArrayList<>(); + for(int y = 0; yMarek Posolda */ @@ -44,7 +42,7 @@ public class ElytronKeyStoreTypesTest { @Test public void testKeystoreFormats() { Set supportedKeystoreFormats = CryptoIntegration.getProvider().getSupportedKeyStoreTypes().collect(Collectors.toSet()); - assertThat(supportedKeystoreFormats, Matchers.containsInAnyOrder( + Assert.assertThat(supportedKeystoreFormats, Matchers.containsInAnyOrder( KeystoreUtil.KeystoreFormat.JKS, KeystoreUtil.KeystoreFormat.PKCS12 )); diff --git a/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronPemUtilsTest.java b/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronPemUtilsTest.java index 4653cbc78e..862ec91b92 100644 --- a/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronPemUtilsTest.java +++ b/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronPemUtilsTest.java @@ -18,10 +18,14 @@ package org.keycloak.crypto.elytron.test; import static org.junit.Assert.assertEquals; +import java.security.KeyPair; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; import org.junit.ClassRule; import org.junit.Test; +import org.keycloak.common.crypto.CryptoIntegration; +import org.keycloak.common.crypto.PemUtilsProvider; import org.keycloak.rule.CryptoInitRule; public class ElytronPemUtilsTest { @@ -42,5 +46,26 @@ public class ElytronPemUtilsTest { String encoded = org.keycloak.common.util.PemUtils.generateThumbprint(test, "SHA-256"); 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); + } } diff --git a/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java b/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java new file mode 100644 index 0000000000..a9e27a190e --- /dev/null +++ b/crypto/elytron/src/test/java/org/keycloak/crypto/elytron/test/ElytronSignatureAlgTest.java @@ -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(); + } + +}