From bdc2dc59cdd90b857c52b1adc1929cc3b3cb60d4 Mon Sep 17 00:00:00 2001 From: SMan Date: Fri, 4 Aug 2023 02:38:34 -0500 Subject: [PATCH] feat: BCFIPS support (sub-part 02) (#5779) * feat (jans_bom): bc-fips modules have been added; * feat (jans-auth-server): KeyGenerator has been updated; * feat (jans-auth-server): bc-fips support has been added; --- .../io/jans/as/client/util/KeyGenerator.java | 14 +- .../cert/fingerprint/FingerprintHelper.java | 30 +- .../validation/CRLCertificateVerifier.java | 8 +- .../validation/OCSPCertificateVerifier.java | 391 +++++++++--------- .../validation/PathCertificateVerifier.java | 5 +- .../java/io/jans/as/model/util/CertUtils.java | 25 ++ 6 files changed, 268 insertions(+), 205 deletions(-) diff --git a/jans-auth-server/client/src/main/java/io/jans/as/client/util/KeyGenerator.java b/jans-auth-server/client/src/main/java/io/jans/as/client/util/KeyGenerator.java index e33e036bcaa..c1e44977028 100644 --- a/jans-auth-server/client/src/main/java/io/jans/as/client/util/KeyGenerator.java +++ b/jans-auth-server/client/src/main/java/io/jans/as/client/util/KeyGenerator.java @@ -16,7 +16,13 @@ import io.jans.util.StringHelper; import io.jans.util.security.SecurityProviderUtility; -import org.apache.commons.cli.*; +import org.apache.commons.cli.BasicParser; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; import org.apache.log4j.Logger; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.status.StatusLogger; @@ -94,12 +100,12 @@ public Cli(String[] args) { options.addOption(KEY_STORE_FILE, true, "Key Store file."); options.addOption(KEY_STORE_PASSWORD, true, "Key Store password."); options.addOption(DN_NAME, true, "DN of certificate issuer."); - options.addOption(OXELEVEN_ACCESS_TOKEN, true, "oxEleven Access Token"); + options.addOption(OXELEVEN_ACCESS_TOKEN, true, "oxEleven Access Token."); options.addOption(OXELEVEN_GENERATE_KEY_ENDPOINT, true, "oxEleven Generate Key Endpoint."); options.addOption(EXPIRATION, true, "Expiration in days."); options.addOption(EXPIRATION_HOURS, true, "Expiration in hours."); - options.addOption(KEY_LENGTH, true, "Key length"); - options.addOption(KEY_OPS_TYPE, true, "Key Operations Type"); + options.addOption(KEY_LENGTH, true, "Key length."); + options.addOption(KEY_OPS_TYPE, true, "Key Operations Type."); options.addOption(TEST_PROP_FILE, true, "Tests property file."); options.addOption(HELP, false, "Show help."); } diff --git a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/fingerprint/FingerprintHelper.java b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/fingerprint/FingerprintHelper.java index 91c9e99210a..6d13baef37b 100644 --- a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/fingerprint/FingerprintHelper.java +++ b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/fingerprint/FingerprintHelper.java @@ -18,6 +18,7 @@ import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.interfaces.RSAPublicKey; +import java.security.interfaces.ECPublicKey; /** * Utility which help to calculate SSH RSA public key fingerprint @@ -33,10 +34,18 @@ public class FingerprintHelper { * Return SSH RSA public key fingerprint */ public static String getPublicKeySshFingerprint(PublicKey publicKey) throws NoSuchAlgorithmException, IOException { - if (publicKey instanceof RSAPublicKey) { - return getPublicKeySshFingerprint((RSAPublicKey) publicKey); + if (publicKey instanceof RSAPublicKey || publicKey instanceof ECPublicKey) { + MessageDigest digest = MessageDigest.getInstance("MD5"); + byte[] derEncoded = null; + if(publicKey instanceof RSAPublicKey) { + derEncoded = getDerEncoding((RSAPublicKey)publicKey); + } + else if (publicKey instanceof ECPublicKey) { + derEncoded = getDerEncoding((ECPublicKey)publicKey); + } + byte[] fingerprint = digest.digest(derEncoded); + return Hex.encodeHexString(fingerprint); } - throw new NoSuchAlgorithmException("Unsopported PublicKey type"); } @@ -59,6 +68,21 @@ private static byte[] getDerEncoding(RSAPublicKey key) throws IOException { return buffer.toByteArray(); } + /* + * here is a pseudo SSH encoding (start string is 'ssh-ecdsa'), as format of SSH for EC something like that: + * ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzhFSVzzMlfUih30HB8k7Dpmn95NWQMQRcYpHWhIcMsXQL7TFD8izlr0bRA9XTmBDyKhgA80XMr33r4jeiP+MI= + * or for EDDSA (ed25519) + * ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPZ6PEne43qIHzRihLo4wbo9+E7IFgPp7HLYLFoDiXz + * but current encoding is enough for generating a unique fingerprint. + */ + private static byte[] getDerEncoding(ECPublicKey key) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + DataOutputStream dataOutput = new DataOutputStream(buffer); + writeDataWithLength("ssh-ecdsa".getBytes(), dataOutput); + writeDataWithLength(key.getEncoded(), dataOutput); + return buffer.toByteArray(); + } + private static void writeDataWithLength(byte[] data, DataOutput byteBuffer) throws IOException { byteBuffer.writeInt(data.length); byteBuffer.write(data); diff --git a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/CRLCertificateVerifier.java b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/CRLCertificateVerifier.java index e8e7d28f912..d2fb0a66079 100644 --- a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/CRLCertificateVerifier.java +++ b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/CRLCertificateVerifier.java @@ -27,9 +27,7 @@ import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; -import org.bouncycastle.asn1.x509.X509Extensions; -import org.bouncycastle.x509.NoSuchParserException; -import org.bouncycastle.x509.util.StreamParsingException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,7 +70,7 @@ public CRLCertificateVerifier(final int maxCrlSize) { this.maxCrlSize = maxCrlSize; CacheLoader checkedLoader = new CacheLoader() { - public X509CRL load(String crlURL) throws CertificateException, CRLException, NoSuchProviderException, NoSuchParserException, StreamParsingException, IOException, ExecutionException { + public X509CRL load(String crlURL) throws CertificateException, CRLException, NoSuchProviderException, IOException, ExecutionException { X509CRL result = requestCRL(crlURL); Preconditions.checkNotNull(result); @@ -234,7 +232,7 @@ public X509CRL requestCRL(String url) throws IOException, CertificateException, @SuppressWarnings({"deprecation", "resource"}) private BigInteger getCrlNumber(X509CRL crl) throws IOException { - byte[] crlNumberExtensionValue = crl.getExtensionValue(X509Extensions.CRLNumber.getId()); + byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId()); if (crlNumberExtensionValue == null) { return null; } diff --git a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/OCSPCertificateVerifier.java b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/OCSPCertificateVerifier.java index 8b29065b5c1..65e99e6751a 100644 --- a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/OCSPCertificateVerifier.java +++ b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/OCSPCertificateVerifier.java @@ -6,8 +6,17 @@ package io.jans.as.common.cert.validation; -import io.jans.as.common.cert.validation.model.ValidationStatus; -import io.jans.util.security.SecurityProviderUtility; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.Principal; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.List; import org.apache.commons.io.IOUtils; import org.bouncycastle.asn1.ASN1InputStream; @@ -32,205 +41,207 @@ import org.bouncycastle.cert.ocsp.RevokedStatus; import org.bouncycastle.cert.ocsp.SingleResp; import org.bouncycastle.operator.DigestCalculator; +import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.Principal; -import java.security.cert.X509Certificate; -import java.util.Date; -import java.util.List; +import io.jans.as.common.cert.validation.model.ValidationStatus; +import io.jans.as.common.cert.validation.model.ValidationStatus.CertificateValidity; +import io.jans.as.common.cert.validation.model.ValidationStatus.ValidatorSourceType; +import io.jans.as.model.util.CertUtils; +import io.jans.util.security.SecurityProviderUtility; /** * Certificate verifier based on OCSP - * + * * @author Yuriy Movchan * @version March 10, 2016 */ public class OCSPCertificateVerifier implements CertificateVerifier { - private static final Logger log = LoggerFactory.getLogger(OCSPCertificateVerifier.class); - - public OCSPCertificateVerifier() { - SecurityProviderUtility.installBCProvider(true); - } - - /** - * @param certificate the certificate from which we need the ExtensionValue - * @param oid the Object Identifier value for the extension. - * @return the extension value as an ASN1Primitive object - * @throws IOException - */ - private static ASN1Primitive getExtensionValue(X509Certificate certificate, String oid) throws IOException { - byte[] bytes = certificate.getExtensionValue(oid); - if (bytes == null) { - return null; - } - ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes)); - ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); - aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets())); - return aIn.readObject(); - } - - @Override - public ValidationStatus validate(X509Certificate certificate, List issuers, Date validationDate) { - X509Certificate issuer = issuers.get(0); - ValidationStatus status = new ValidationStatus(certificate, issuer, validationDate, ValidationStatus.ValidatorSourceType.OCSP, ValidationStatus.CertificateValidity.UNKNOWN); - - try { - Principal subjectX500Principal = certificate.getSubjectX500Principal(); - - String ocspUrl = getOCSPUrl(certificate); - if (ocspUrl == null) { - log.error("OCSP URL for '" + subjectX500Principal + "' is empty"); - return status; - } - - log.debug("OCSP URL for '" + subjectX500Principal + "' is '" + ocspUrl + "'"); - - DigestCalculator digestCalculator = new JcaDigestCalculatorProviderBuilder().build().get(CertificateID.HASH_SHA1); - CertificateID certificateId = new CertificateID(digestCalculator, new JcaX509CertificateHolder(certificate), certificate.getSerialNumber()); - - // Generate OCSP request - OCSPReq ocspReq = generateOCSPRequest(certificateId); - - // Get OCSP response from server - OCSPResp ocspResp = requestOCSPResponse(ocspUrl, ocspReq); - if (ocspResp.getStatus() != OCSPRespBuilder.SUCCESSFUL) { - log.error("OCSP response is invalid!"); - status.setValidity(ValidationStatus.CertificateValidity.INVALID); - return status; - } - - boolean foundResponse = false; - BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResp.getResponseObject(); - SingleResp[] singleResps = basicOCSPResp.getResponses(); - for (SingleResp singleResp : singleResps) { - CertificateID responseCertificateId = singleResp.getCertID(); - if (!certificateId.equals(responseCertificateId)) { - continue; - } - - foundResponse = true; - - log.debug("OCSP validationDate: " + validationDate); - log.debug("OCSP thisUpdate: " + singleResp.getThisUpdate()); - log.debug("OCSP nextUpdate: " + singleResp.getNextUpdate()); - - status.setRevocationObjectIssuingTime(basicOCSPResp.getProducedAt()); - - Object certStatus = singleResp.getCertStatus(); - if (certStatus == CertificateStatus.GOOD) { - log.debug("OCSP status is valid for '" + certificate.getSubjectX500Principal() + "'"); - status.setValidity(ValidationStatus.CertificateValidity.VALID); - } else { - if (singleResp.getCertStatus() instanceof RevokedStatus) { - log.warn("OCSP status is revoked for: " + subjectX500Principal); - if (validationDate.before(((RevokedStatus) singleResp.getCertStatus()).getRevocationTime())) { - log.warn("OCSP revocation time after the validation date, the certificate '" + subjectX500Principal + "' was valid at " + validationDate); - status.setValidity(ValidationStatus.CertificateValidity.VALID); - } else { - Date revocationDate = ((RevokedStatus) singleResp.getCertStatus()).getRevocationTime(); - log.info("OCSP for certificate '" + subjectX500Principal + "' is revoked since " + revocationDate); - status.setRevocationDate(revocationDate); - status.setRevocationObjectIssuingTime(singleResp.getThisUpdate()); - status.setValidity(ValidationStatus.CertificateValidity.REVOKED); - } - } - } - } - - if (!foundResponse) { - log.error("There is no matching OCSP response entries"); - } - } catch (Exception ex) { - log.error("OCSP exception: ", ex); - } - - return status; - } - - private OCSPReq generateOCSPRequest(CertificateID certificateId) throws OCSPException { - OCSPReqBuilder ocspReqGenerator = new OCSPReqBuilder(); - - ocspReqGenerator.addRequest(certificateId); - - return ocspReqGenerator.build(); - } - - @SuppressWarnings({"deprecation", "resource"}) - private String getOCSPUrl(X509Certificate certificate) throws IOException { - ASN1Primitive obj; - try { - obj = getExtensionValue(certificate, Extension.authorityInfoAccess.getId()); - } catch (IOException ex) { - log.error("Failed to get OCSP URL", ex); - return null; - } - - if (obj == null) { - return null; - } - - AuthorityInformationAccess authorityInformationAccess = AuthorityInformationAccess.getInstance(obj); - - AccessDescription[] accessDescriptions = authorityInformationAccess.getAccessDescriptions(); - for (AccessDescription accessDescription : accessDescriptions) { - boolean correctAccessMethod = accessDescription.getAccessMethod().equals(X509ObjectIdentifiers.ocspAccessMethod); - if (!correctAccessMethod) { - continue; - } - - GeneralName name = accessDescription.getAccessLocation(); - if (name.getTagNo() != GeneralName.uniformResourceIdentifier) { - continue; - } - - DERIA5String derStr = DERIA5String.getInstance((ASN1TaggedObject) name.toASN1Primitive(), false); - return derStr.getString(); - } - - return null; - - } - - public OCSPResp requestOCSPResponse(String url, OCSPReq ocspReq) throws IOException { - byte[] ocspReqData = ocspReq.getEncoded(); - - HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); - try { - con.setRequestProperty("Content-Type", "application/ocsp-request"); - con.setRequestProperty("Accept", "application/ocsp-response"); - - con.setDoInput(true); - con.setDoOutput(true); - con.setUseCaches(false); - - OutputStream out = con.getOutputStream(); - try { - IOUtils.write(ocspReqData, out); - out.flush(); - } finally { - IOUtils.closeQuietly(out); - } - - byte[] responseBytes = IOUtils.toByteArray(con.getInputStream()); - return new OCSPResp(responseBytes); - } finally { - if (con != null) { - con.disconnect(); - } - } - } - - @Override - public void destroy() { - // nothing to destroy - } + private static final Logger log = LoggerFactory.getLogger(OCSPCertificateVerifier.class); + + public OCSPCertificateVerifier() { + SecurityProviderUtility.installBCProvider(true); + } + + /** + * @param certificate + * the certificate from which we need the ExtensionValue + * @param oid + * the Object Identifier value for the extension. + * @return the extension value as an ASN1Primitive object + * @throws IOException + */ + private static ASN1Primitive getExtensionValue(X509Certificate certificate, String oid) throws IOException { + byte[] bytes = certificate.getExtensionValue(oid); + if (bytes == null) { + return null; + } + ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes)); + ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); + aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets())); + return aIn.readObject(); + } + + @Override + public ValidationStatus validate(X509Certificate certificate, List issuers, Date validationDate) { + + X509Certificate issuer = CertUtils.getIssuer(certificate, issuers); + ValidationStatus status = new ValidationStatus(certificate, issuer, validationDate, ValidatorSourceType.OCSP, CertificateValidity.UNKNOWN); + + try { + Principal subjectX500Principal = certificate.getSubjectX500Principal(); + + String ocspUrl = getOCSPUrl(certificate); + if (ocspUrl == null) { + log.error("OCSP URL for '" + subjectX500Principal + "' is empty"); + return status; + } + + log.debug("OCSP URL for '" + subjectX500Principal + "' is '" + ocspUrl + "'"); + + DigestCalculator digestCalculator = new JcaDigestCalculatorProviderBuilder().build().get(CertificateID.HASH_SHA1); + CertificateID certificateId = new CertificateID(digestCalculator, new JcaX509CertificateHolder(issuer), certificate.getSerialNumber()); + + // Generate OCSP request + OCSPReq ocspReq = generateOCSPRequest(certificateId); + + // Get OCSP response from server + OCSPResp ocspResp = requestOCSPResponse(ocspUrl, ocspReq); + if (ocspResp.getStatus() != OCSPRespBuilder.SUCCESSFUL) { + log.error("OCSP response is invalid!"); + status.setValidity(CertificateValidity.INVALID); + return status; + } + + boolean foundResponse = false; + BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResp.getResponseObject(); + SingleResp[] singleResps = basicOCSPResp.getResponses(); + for (SingleResp singleResp : singleResps) { + CertificateID responseCertificateId = singleResp.getCertID(); + if (!certificateId.equals(responseCertificateId)) { + continue; + } + + foundResponse = true; + + log.debug("OCSP validationDate: " + validationDate); + log.debug("OCSP thisUpdate: " + singleResp.getThisUpdate()); + log.debug("OCSP nextUpdate: " + singleResp.getNextUpdate()); + + status.setRevocationObjectIssuingTime(basicOCSPResp.getProducedAt()); + + Object certStatus = singleResp.getCertStatus(); + if (certStatus == CertificateStatus.GOOD) { + log.debug("OCSP status is valid for '" + certificate.getSubjectX500Principal() + "'"); + status.setValidity(CertificateValidity.VALID); + } else { + if (singleResp.getCertStatus() instanceof RevokedStatus) { + log.warn("OCSP status is revoked for: " + subjectX500Principal); + if (validationDate.before(((RevokedStatus) singleResp.getCertStatus()).getRevocationTime())) { + log.warn("OCSP revocation time after the validation date, the certificate '" + subjectX500Principal + "' was valid at " + validationDate); + status.setValidity(CertificateValidity.VALID); + } else { + Date revocationDate = ((RevokedStatus) singleResp.getCertStatus()).getRevocationTime(); + log.info("OCSP for certificate '" + subjectX500Principal + "' is revoked since " + revocationDate); + status.setRevocationDate(revocationDate); + status.setRevocationObjectIssuingTime(singleResp.getThisUpdate()); + status.setValidity(CertificateValidity.REVOKED); + } + } + } + } + + if (!foundResponse) { + log.error("There is no matching OCSP response entries"); + } + } catch (Exception ex) { + log.error("OCSP exception: ", ex); + } + + return status; + } + + private OCSPReq generateOCSPRequest(CertificateID certificateId) throws OCSPException, OperatorCreationException, CertificateEncodingException { + OCSPReqBuilder ocspReqGenerator = new OCSPReqBuilder(); + + ocspReqGenerator.addRequest(certificateId); + + OCSPReq ocspReq = ocspReqGenerator.build(); + return ocspReq; + } + + @SuppressWarnings({ "deprecation", "resource" }) + private String getOCSPUrl(X509Certificate certificate) throws IOException { + ASN1Primitive obj; + try { + obj = getExtensionValue(certificate, Extension.authorityInfoAccess.getId()); + } catch (IOException ex) { + log.error("Failed to get OCSP URL", ex); + return null; + } + + if (obj == null) { + return null; + } + + AuthorityInformationAccess authorityInformationAccess = AuthorityInformationAccess.getInstance(obj); + + AccessDescription[] accessDescriptions = authorityInformationAccess.getAccessDescriptions(); + for (AccessDescription accessDescription : accessDescriptions) { + boolean correctAccessMethod = accessDescription.getAccessMethod().equals((Object)X509ObjectIdentifiers.ocspAccessMethod); + if (!correctAccessMethod) { + continue; + } + + GeneralName name = accessDescription.getAccessLocation(); + if (name.getTagNo() != GeneralName.uniformResourceIdentifier) { + continue; + } + + DERIA5String derStr = DERIA5String.getInstance((ASN1TaggedObject) name.toASN1Primitive(), false); + return derStr.getString(); + } + + return null; + + } + + public OCSPResp requestOCSPResponse(String url, OCSPReq ocspReq) throws IOException, MalformedURLException { + byte[] ocspReqData = ocspReq.getEncoded(); + + HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); + try { + con.setRequestProperty("Content-Type", "application/ocsp-request"); + con.setRequestProperty("Accept", "application/ocsp-response"); + + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + + OutputStream out = con.getOutputStream(); + try { + IOUtils.write(ocspReqData, out); + out.flush(); + } finally { + IOUtils.closeQuietly(out); + } + + byte[] responseBytes = IOUtils.toByteArray(con.getInputStream()); + OCSPResp ocspResp = new OCSPResp(responseBytes); + + return ocspResp; + } finally { + if (con != null) { + con.disconnect(); + } + } + } + + @Override + public void destroy() { + } } diff --git a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/PathCertificateVerifier.java b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/PathCertificateVerifier.java index 9c3537d13e4..f356ec9e0c9 100644 --- a/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/PathCertificateVerifier.java +++ b/jans-auth-server/common/src/main/java/io/jans/as/common/cert/validation/PathCertificateVerifier.java @@ -9,7 +9,6 @@ import io.jans.as.common.cert.validation.model.ValidationStatus; import io.jans.util.security.SecurityProviderUtility; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -170,11 +169,11 @@ private PKIXCertPathBuilderResult verifyCertificate(X509Certificate certificate, pkixParams.addCertStore(intermediateCertStore); // Build and verify the certification chain - CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME); + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", SecurityProviderUtility.getBCProvider()); PKIXCertPathBuilderResult certPathBuilderResult = (PKIXCertPathBuilderResult) builder.build(pkixParams); // Additional check to Verify cert path - CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME); + CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", SecurityProviderUtility.getBCProvider()); certPathValidator.validate(certPathBuilderResult.getCertPath(), pkixParams); return certPathBuilderResult; diff --git a/jans-auth-server/model/src/main/java/io/jans/as/model/util/CertUtils.java b/jans-auth-server/model/src/main/java/io/jans/as/model/util/CertUtils.java index c9b12ba22a4..242446548c9 100644 --- a/jans-auth-server/model/src/main/java/io/jans/as/model/util/CertUtils.java +++ b/jans-auth-server/model/src/main/java/io/jans/as/model/util/CertUtils.java @@ -25,9 +25,11 @@ import java.io.InputStream; import java.net.URLDecoder; import java.security.AlgorithmParameters; +import java.security.Principal; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.List; /** * @author Yuriy Zabrovarnyy @@ -186,4 +188,27 @@ public static boolean equalsRdn(String rdn1, String rdn2) { return n1.equals(n2); } + + public static X509Certificate getIssuer(final X509Certificate certificate, final List issuers) { + + Principal certPrincipal = certificate.getIssuerDN(); + + X509Certificate issuer = null; + + for (int i = 0; i < issuers.size(); i++) { + X509Certificate currIssuer = issuers.get(i); + Principal currIssuerPrincipal = currIssuer.getSubjectDN(); + + if (certPrincipal.equals(currIssuerPrincipal)) { + issuer = currIssuer; + break; + } + } + + if (issuer == null) { + issuer = certificate; + } + + return issuer; + } }