-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
11, 16
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
We have encountered with an Error during trying to validate the revocation status of a certificate.
Java delivers an Exception with message: "Undetermined Revocation Status" for a given certificate.
After we debug the JVM Code, we have seen that CRL can be downloaded from the URL but during the verification steps of the CRL List, DistributionPointFetcher.verifyCRL method rejects the CRL.
So it never lands into the crls list in the RevocationChecker class and since no further CRLs can be found, status is undetermined.
Here is the code part where CRL is rejected because of indirect_crl flag is not set to "true":
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java#L366
CA defines the Optional crlIssuer (CRL Issuer) flag inside of their application certificate, but they point out the direct issuer certificate on this optional extension.
Here is the crl distribution point section from the certificate under check:
[1]CRL Distribution Point
Distribution Point Name:
Full Name:
URL=http://crl.protectr.de/crl/procilon_GROUP_Test_CA_DocSigner
CRL Issuer:
Directory Address:
C=DE
O=proTECTr
OU=Sub CA
CN=procilon GROUP Test CA - DocSigner
CA delivers the additional extension (Issuing Distribution Point) for the CRL,
but it is not an indirect_crl since it only contains revocations directly related with the issuer certificate.
Distribution Point Name:
Full Name:
URL=http://crl.protectr.de/crl/procilon_GROUP_Test_CA_DocSigner
Only Contains User Certs=No
Only Contains CA Certs=No
Indirect CRL=No
As far as we can see, DistributionPointFetcher.verifyCRL implements the following check, which is defined on RFC 5280 Section 6.3.3 (b) (1):
https://tools.ietf.org/html/rfc5280
(1) If the DP includes cRLIssuer, then verify that the issuer
field in the complete CRL matches cRLIssuer in the DP and
that the complete CRL contains an issuing distribution
point extension with the indirectCRL boolean asserted.
Otherwise, verify that the CRL issuer matches the
certificate issuer.
However, Java implementation for verification expects the indirect CRL flag to be always set to true in this case, even though in our case the delivered CRL is not an indirect CRL.
From our understanding of the RFC, it really asks for the indirect CRL flag to be set, true and false both being valid values here.
We have written also a small program that can reproduce the issue with some example certificates which can be run it with OpenJDK 11.
If the "CRL Issuer" optional field is not set in the certificate, then the certificate is accepted by the JVM with this CRL, but if it is set then the CRL does not pass verification according to JVM.
We understand that providing a "CRL issuer" in a certificate which does not differ from the certificate's issuer is uncommon and we already talked to the affected CA about it.
However, we could not find a single reference in the RFC that explicitly prohibits a CA to do this.
Therefore it is our understanding that the JVM implementation contradicts the RFC specification in this case.
Can you please fix this problem on the JVM side?
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the Main Program attached on the Source Code section and see that verification fails for a certificate with "CRL Issuer"
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Certificate with "CRL Issuer" flag set to certificate's issuer should be verified as valid without revocation problems regardless of the Indirect CRL value, if the CRL is issued by the certificate's issuer.
ACTUAL -
Certificate's revocation status can not be determined.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.util.Arrays;
import java.util.Date;
public class MainWithTestCertificate {
private static final String APPLICATION_WITH_CRLISSUER = "-----BEGIN CERTIFICATE-----\r\n" +
"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\r\n" +
"2A1FvDhuuWvbVHiJ\r\n" +
"-----END CERTIFICATE-----";
private static final String APPLICATION_WITHOUT_CRLISSUER = "-----BEGIN CERTIFICATE-----\r\n" +
"MIIFYjCCAxagAwIBAgIUE1vBGX9UcEZvgTLs3mTtjhWsLcMwQQYJKoZIhvcNAQEK\r\n" +
"MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF\r\n" +
"AKIDAgEgMF4xKzApBgNVBAMMInByb2NpbG9uIEdST1VQIFRlc3QgQ0EgLSBEb2NT\r\n" +
"aWduZXIxDzANBgNVBAsMBlN1YiBDQTERMA8GA1UECgwIcHJvVEVDVHIxCzAJBgNV\r\n" +
"BAYTAkRFMB4XDTIwMTIxMDA3MTgzN1oXDTIyMTIxMDA3MTgzNlowITEfMB0GA1UE\r\n" +
"AwwWVGVzdCB3aXRob3V0IENSTElzc3VlcjCCASIwDQYJKoZIhvcNAQEBBQADggEP\r\n" +
"ADCCAQoCggEBAKUdWbX+rAU8MjwtoEGeXzAFZE0ZZzdbOcFzOUG7OKboTfJUr7rM\r\n" +
"Jp0vTpbMt+/RHPMylpBVdBTYUhta0LnoqG4yklX4Fn0T23/5WQP7vORDPdBWWBmt\r\n" +
"6smJ34QqRRkmcTKsvEIu9r5sVGU+ujopg8cTvCiGueDnx8YO83Iacv+hNOi0SOpd\r\n" +
"eITrlNwCMowlqPpcoHeq/4qBiYccxvRjUvBG5OLY0VElDDtVavBAfLOC+TwCHpuB\r\n" +
"apV1XLGOumWSWP3wkL8IZDiVcV1luEJDycFn63huVU2naIVqSDKWmqhk6PdrUVbQ\r\n" +
"OTjAWAhJ5jMahzlYnVtIbQzO6waw0JbFmicCAwEAAaOB7DCB6TAMBgNVHRMBAf8E\r\n" +
"AjAAMB8GA1UdIwQYMBaAFPbc00ynmPHuACczhafMXyJZGmdwMDsGCCsGAQUFBwEB\r\n" +
"BC8wLTArBggrBgEFBQcwAYYfaHR0cDovL29jc3AucHJvdGVjdHIuZGUvc3RhdHVz\r\n" +
"LzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLnByb3RlY3RyLmRlL2NybC9w\r\n" +
"cm9jaWxvbl9HUk9VUF9UZXN0X0NBX0RvY1NpZ25lcjAdBgNVHQ4EFgQUlj3aBDUS\r\n" +
"GR3uFskwPUITb1ioMZMwDgYDVR0PAQH/BAQDAgbAMEEGCSqGSIb3DQEBCjA0oA8w\r\n" +
"DQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIB\r\n" +
"IAOCAgEArvjYYP5QKmlTKH5Uzy4QMkmMtu0rUxKzj6xE7mi4Viw7IuA6KkhGp0zh\r\n" +
"s+Xz2S+Gq4KogkZ/3ZQaIfV+t6rAAYv3LMySULQ+SHC3AQwiFmbFNA56wmSm+8qo\r\n" +
"BXBnH6zc4MgawPNw7fp1O8Di2naLQpVoVyjUN4DLIEU88M2XYqEkwEU9jh2GJuDd\r\n" +
"mWBqb3mtLExnboWFICs/2bv0bFUcpLE6ZTJayE/qE+D9pVEeS5JNQrzi+woPsYQS\r\n" +
"FAd6yZSCQZ3Yx1vtcrj+2yO5OIiE4WAZopl/gnrJ7QrxxZC3Mc5a0j3Z2UR81j3Z\r\n" +
"4tjcYtpUS6XkEW1IuYu9Y8k75Y5gjVr4D3/WxpORXzLRD2oXlAG7lHMAQfEBRoAx\r\n" +
"e4URuiWn1mHriJnL2657jj0Ity6ueWmgGUYrC/sJzr0cGPZIv+OhVFIvJ6aCCoq4\r\n" +
"PI7d+f6K20hhrp9U/kROgT5BQ4s3/AZJRg7amyUdYKv0fUCfl5B5j2gPM7PF52sy\r\n" +
"QQDtwtZFo7hFzRqUsRSE9s0gy3kTI4+qFDSLizawwVFtxW1cd8s4H0N3nzX1h2yE\r\n" +
"u79f/KhtKpN4ZIAD86rRiMupwc0RCwff0D82iaSjOdJ3O47CSXK6PmzL/HHjJx8C\r\n" +
"Ww43N96NPhjAuvlmH5eSwTSIYOxzTviwkmrJfIRMzRFNGqd3rsY=\r\n" +
"-----END CERTIFICATE-----";
private static final String INTERMEDIATE = "-----BEGIN CERTIFICATE-----\r\n" +
"MIIHMDCCBOSgAwIBAgIUZd/hQcJl9LbtHRRLt6t8Yww3nSswQQYJKoZIhvcNAQEK\r\n" +
"MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF\r\n" +
"AKIDAgEgMFoxJjAkBgNVBAMMHXByb2NpbG9uIEdST1VQIFRlc3QgUm9vdENBIDAy\r\n" +
"MRAwDgYDVQQLDAdSb290IENBMREwDwYDVQQKDAhwcm9URUNUcjELMAkGA1UEBhMC\r\n" +
"REUwHhcNMjAxMTA5MTAxMDQ5WhcNMzQxMDA2MTAyMjMxWjBeMSswKQYDVQQDDCJw\r\n" +
"cm9jaWxvbiBHUk9VUCBUZXN0IENBIC0gRG9jU2lnbmVyMQ8wDQYDVQQLDAZTdWIg\r\n" +
"Q0ExETAPBgNVBAoMCHByb1RFQ1RyMQswCQYDVQQGEwJERTCCAiIwDQYJKoZIhvcN\r\n" +
"AQEBBQADggIPADCCAgoCggIBALbhm0+Lu20C1b5CkUaP6SPaTXIKbyeqi7yv6X6n\r\n" +
"4BGzXOugLXoIsgUTLtOPbz6LoSgkpOl+1p0M1anIye/htibkyygtKkal0dmmvpmI\r\n" +
"mG4v94BY7gukyLNIhjoNY51SEWPA1HurxCPlDiN3g5AtVWcu6qWGTNCVrboSQ/xb\r\n" +
"IYU1T9MKOMI0OjF1MxSvjhLNFUZmskYZww/X9HFiHVptwjwbvEz3jEdYR+6PsCJC\r\n" +
"d9In4A+YLy4LvSVef9HMqv+5WHffn9ZAmSEywQp0LuCkx0FHDx24Whl6iw6jpsWp\r\n" +
"OsI8aG8WnmAHmdKt4zZ6Bt1eSmneTwGoM3NwWkIwjeUX4YqE6OovTyIaJ9m2+I9m\r\n" +
"6nIDNJ/fcjBsUOVEw0Wp7jd8IwOhFAXIOqh2NkGUtN4k1SPohAByzFe4d7+jDtis\r\n" +
"g9dwj8OkUrZ5ajoscBlnkKZwybmJjCAsyf4hFVX/dxz/zUpsTHbeMeJBAy7EJmez\r\n" +
"wNJWLnIHYBQUJrsbYBn4Xu/qlbvyfsZru6UGc1VqsH+XnAG0URPCY3YiSTZSYqjy\r\n" +
"zy4qJnTxJVBI7jDsLrA3/meSGfyhtjvuBUgXmWSfXYXJn0tgxDbsT3I6hxvBKajg\r\n" +
"7EreApxUO8Z6KEJgs4jwGQv8acE9oIYxUTjHyXGCUnwFujnewa11hxtQSBE09jlW\r\n" +
"jRF1AgMBAAGjggGAMIIBfDASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaA\r\n" +
"FIdOO7ofYT3TScPp3Y82ptYIExN7MGcGCCsGAQUFBwEBBFswWTAqBggrBgEFBQcw\r\n" +
"AoYeaHR0cHM6Ly9wa2kucHJvdGVjdHIuZGUvaXNzdWVyMCsGCCsGAQUFBzABhh9o\r\n" +
"dHRwOi8vb2NzcC5wcm90ZWN0ci5kZS9zdGF0dXMvMIGsBgNVHR8EgaQwgaEwgZ6g\r\n" +
"PKA6hjhodHRwOi8vY3JsLnByb3RlY3RyLmRlL2NybC9wcm9jaWxvbl9HUk9VUF9U\r\n" +
"ZXN0X1Jvb3RDQV8wMqJepFwwWjEmMCQGA1UEAwwdcHJvY2lsb24gR1JPVVAgVGVz\r\n" +
"dCBSb290Q0EgMDIxEDAOBgNVBAsMB1Jvb3QgQ0ExETAPBgNVBAoMCHByb1RFQ1Ry\r\n" +
"MQswCQYDVQQGEwJERTAdBgNVHQ4EFgQU9tzTTKeY8e4AJzOFp8xfIlkaZ3AwDgYD\r\n" +
"VR0PAQH/BAQDAgEGMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAa\r\n" +
"BgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAgEAUuVwmG18AUfdrzEf\r\n" +
"M/7T+f5Is32Mb1sCeKhYIyRDDoLgntenWDQOMoiw1L5xdgft/RIQLdyYe6OC++SB\r\n" +
"dofy4pnIOS45AJcd5mVI9hFb5i9xGICijYvE6mcXpzMxVr8UBQ7I6tNaN+VdOB2/\r\n" +
"zE84Tbz6T+joGgPrCJwj3RiRKKs/P63goYR0ZANacR9aSilkdAfwsy7XFd7ZdFQt\r\n" +
"MiJBja3umZTnhsjuUzVHq8L9/j99eftQLG7CiQftopMjJvnYzuYxabXeqgBpSobL\r\n" +
"WeNeKb63sVCQUftvLvgKM6qU9aImuKN7D7cWyR/8AAXlS8DJfYXpBgh+6l3LpvmS\r\n" +
"FRa7DkO9w+hGzQI5ZuGOMAf1QOaZnEVqLLAbxJSqsvMxRL147nGfpE+K18MA2yDO\r\n" +
"PQJIMtw3tIb/xkSHCl0QZtt/YRFNEKOf8VH2vYymAnCH7dBzneb1KC75ezFp1VrS\r\n" +
"ji7vXuKvzo7EK+JswhE1oiABE3oxwbDLkl73QxeMXnSVQhKhUb2wLMVRLuhD9QdC\r\n" +
"UlB/ruvzcaN4mFM8Z3bOjbAUccB/IuzRrDH5NvH+/Yh56eYcxRrcc1Do6ryCBUFM\r\n" +
"WcSJimEqS3+h9CJXVNaxpg1ZZWssA11r3MQGo9ZNfqm6GQAtEYddRIzIMrdzp3ES\r\n" +
"PJUnwGW19MtA2/PEUYFbEtHC1mE=\r\n" +
"-----END CERTIFICATE-----";
private static final String ROOT = "-----BEGIN CERTIFICATE-----\r\n" +
"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\r\n" +
"8F0vlRCo0BKROJnBc3HRBvViNQ==\r\n" +
"-----END CERTIFICATE-----";
public static void main(String[] args) {
System.out.println("start program");
// Execute with
// -Djava.security.auth.debug=certpath
// to see debug output from java
executeValidation(APPLICATION_WITHOUT_CRLISSUER, INTERMEDIATE, ROOT);
executeValidation(APPLICATION_WITH_CRLISSUER, INTERMEDIATE, ROOT);
System.out.println("end program");
}
private static void executeValidation(String application, String intermediate, String root) {
try {
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(null, "".toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X509");
Certificate applicationCertificate = cf
.generateCertificate(new ByteArrayInputStream(application.getBytes()));
Certificate intermediateCertificate = cf
.generateCertificate(new ByteArrayInputStream(intermediate.getBytes()));
Certificate rootCertificate = cf.generateCertificate(new ByteArrayInputStream(root.getBytes()));
keyStore.setCertificateEntry("application", applicationCertificate);
keyStore.setCertificateEntry("intermediate", intermediateCertificate);
keyStore.setCertificateEntry("root", rootCertificate);
String result = processValidationInternal(keyStore, applicationCertificate, true, false, false);
System.out.println(result);
} catch (IOException | GeneralSecurityException e) {
e.printStackTrace();
}
}
private static String processValidationInternal(KeyStore keyStore, Certificate certificate,
boolean revocationCheckEnabled,
boolean ignoreRevocationCheckFailures,
boolean oscpCheckEnabled) {
if (revocationCheckEnabled) {
System.setProperty("com.sun.security.enableCRLDP", "true");
if (oscpCheckEnabled) {
Security.setProperty("ocsp.enable", "true");
}
} else {
System.setProperty("com.sun.security.enableCRLDP", "false");
Security.setProperty("ocsp.enable", "false");
}
String warning = null;
try {
CertificateFactory cf = CertificateFactory.getInstance(certificate.getType());
CertPath certificatePath = cf.generateCertPath(Arrays.asList(certificate));
CertPathValidator cpv = CertPathValidator.getInstance(CertPathValidator.getDefaultType());
PKIXParameters defaultStoreParams = new PKIXParameters(keyStore);
defaultStoreParams.setRevocationEnabled(revocationCheckEnabled);
defaultStoreParams.setDate(new Date(System.currentTimeMillis()));
CertPathValidatorResult defaultStoreResult = cpv.validate(certificatePath, defaultStoreParams);
if (defaultStoreResult != null) {
// Default key store validates the certificate chain.
warning = "success";
}
} catch (CertPathValidatorException e) {
warning = e.getCause().getMessage();
} catch (RuntimeException | GeneralSecurityException e) {
System.out.println("Key store can not validate certificate:" + e.getMessage());
warning = e.getCause().getMessage();
}
return warning;
}
}
---------- END SOURCE ----------
FREQUENCY : always
We have encountered with an Error during trying to validate the revocation status of a certificate.
Java delivers an Exception with message: "Undetermined Revocation Status" for a given certificate.
After we debug the JVM Code, we have seen that CRL can be downloaded from the URL but during the verification steps of the CRL List, DistributionPointFetcher.verifyCRL method rejects the CRL.
So it never lands into the crls list in the RevocationChecker class and since no further CRLs can be found, status is undetermined.
Here is the code part where CRL is rejected because of indirect_crl flag is not set to "true":
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java#L366
CA defines the Optional crlIssuer (CRL Issuer) flag inside of their application certificate, but they point out the direct issuer certificate on this optional extension.
Here is the crl distribution point section from the certificate under check:
[1]CRL Distribution Point
Distribution Point Name:
Full Name:
URL=http://crl.protectr.de/crl/procilon_GROUP_Test_CA_DocSigner
CRL Issuer:
Directory Address:
C=DE
O=proTECTr
OU=Sub CA
CN=procilon GROUP Test CA - DocSigner
CA delivers the additional extension (Issuing Distribution Point) for the CRL,
but it is not an indirect_crl since it only contains revocations directly related with the issuer certificate.
Distribution Point Name:
Full Name:
URL=http://crl.protectr.de/crl/procilon_GROUP_Test_CA_DocSigner
Only Contains User Certs=No
Only Contains CA Certs=No
Indirect CRL=No
As far as we can see, DistributionPointFetcher.verifyCRL implements the following check, which is defined on RFC 5280 Section 6.3.3 (b) (1):
https://tools.ietf.org/html/rfc5280
(1) If the DP includes cRLIssuer, then verify that the issuer
field in the complete CRL matches cRLIssuer in the DP and
that the complete CRL contains an issuing distribution
point extension with the indirectCRL boolean asserted.
Otherwise, verify that the CRL issuer matches the
certificate issuer.
However, Java implementation for verification expects the indirect CRL flag to be always set to true in this case, even though in our case the delivered CRL is not an indirect CRL.
From our understanding of the RFC, it really asks for the indirect CRL flag to be set, true and false both being valid values here.
We have written also a small program that can reproduce the issue with some example certificates which can be run it with OpenJDK 11.
If the "CRL Issuer" optional field is not set in the certificate, then the certificate is accepted by the JVM with this CRL, but if it is set then the CRL does not pass verification according to JVM.
We understand that providing a "CRL issuer" in a certificate which does not differ from the certificate's issuer is uncommon and we already talked to the affected CA about it.
However, we could not find a single reference in the RFC that explicitly prohibits a CA to do this.
Therefore it is our understanding that the JVM implementation contradicts the RFC specification in this case.
Can you please fix this problem on the JVM side?
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the Main Program attached on the Source Code section and see that verification fails for a certificate with "CRL Issuer"
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Certificate with "CRL Issuer" flag set to certificate's issuer should be verified as valid without revocation problems regardless of the Indirect CRL value, if the CRL is issued by the certificate's issuer.
ACTUAL -
Certificate's revocation status can not be determined.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.util.Arrays;
import java.util.Date;
public class MainWithTestCertificate {
private static final String APPLICATION_WITH_CRLISSUER = "-----BEGIN CERTIFICATE-----\r\n" +
"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\r\n" +
"2A1FvDhuuWvbVHiJ\r\n" +
"-----END CERTIFICATE-----";
private static final String APPLICATION_WITHOUT_CRLISSUER = "-----BEGIN CERTIFICATE-----\r\n" +
"MIIFYjCCAxagAwIBAgIUE1vBGX9UcEZvgTLs3mTtjhWsLcMwQQYJKoZIhvcNAQEK\r\n" +
"MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF\r\n" +
"AKIDAgEgMF4xKzApBgNVBAMMInByb2NpbG9uIEdST1VQIFRlc3QgQ0EgLSBEb2NT\r\n" +
"aWduZXIxDzANBgNVBAsMBlN1YiBDQTERMA8GA1UECgwIcHJvVEVDVHIxCzAJBgNV\r\n" +
"BAYTAkRFMB4XDTIwMTIxMDA3MTgzN1oXDTIyMTIxMDA3MTgzNlowITEfMB0GA1UE\r\n" +
"AwwWVGVzdCB3aXRob3V0IENSTElzc3VlcjCCASIwDQYJKoZIhvcNAQEBBQADggEP\r\n" +
"ADCCAQoCggEBAKUdWbX+rAU8MjwtoEGeXzAFZE0ZZzdbOcFzOUG7OKboTfJUr7rM\r\n" +
"Jp0vTpbMt+/RHPMylpBVdBTYUhta0LnoqG4yklX4Fn0T23/5WQP7vORDPdBWWBmt\r\n" +
"6smJ34QqRRkmcTKsvEIu9r5sVGU+ujopg8cTvCiGueDnx8YO83Iacv+hNOi0SOpd\r\n" +
"eITrlNwCMowlqPpcoHeq/4qBiYccxvRjUvBG5OLY0VElDDtVavBAfLOC+TwCHpuB\r\n" +
"apV1XLGOumWSWP3wkL8IZDiVcV1luEJDycFn63huVU2naIVqSDKWmqhk6PdrUVbQ\r\n" +
"OTjAWAhJ5jMahzlYnVtIbQzO6waw0JbFmicCAwEAAaOB7DCB6TAMBgNVHRMBAf8E\r\n" +
"AjAAMB8GA1UdIwQYMBaAFPbc00ynmPHuACczhafMXyJZGmdwMDsGCCsGAQUFBwEB\r\n" +
"BC8wLTArBggrBgEFBQcwAYYfaHR0cDovL29jc3AucHJvdGVjdHIuZGUvc3RhdHVz\r\n" +
"LzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLnByb3RlY3RyLmRlL2NybC9w\r\n" +
"cm9jaWxvbl9HUk9VUF9UZXN0X0NBX0RvY1NpZ25lcjAdBgNVHQ4EFgQUlj3aBDUS\r\n" +
"GR3uFskwPUITb1ioMZMwDgYDVR0PAQH/BAQDAgbAMEEGCSqGSIb3DQEBCjA0oA8w\r\n" +
"DQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIB\r\n" +
"IAOCAgEArvjYYP5QKmlTKH5Uzy4QMkmMtu0rUxKzj6xE7mi4Viw7IuA6KkhGp0zh\r\n" +
"s+Xz2S+Gq4KogkZ/3ZQaIfV+t6rAAYv3LMySULQ+SHC3AQwiFmbFNA56wmSm+8qo\r\n" +
"BXBnH6zc4MgawPNw7fp1O8Di2naLQpVoVyjUN4DLIEU88M2XYqEkwEU9jh2GJuDd\r\n" +
"mWBqb3mtLExnboWFICs/2bv0bFUcpLE6ZTJayE/qE+D9pVEeS5JNQrzi+woPsYQS\r\n" +
"FAd6yZSCQZ3Yx1vtcrj+2yO5OIiE4WAZopl/gnrJ7QrxxZC3Mc5a0j3Z2UR81j3Z\r\n" +
"4tjcYtpUS6XkEW1IuYu9Y8k75Y5gjVr4D3/WxpORXzLRD2oXlAG7lHMAQfEBRoAx\r\n" +
"e4URuiWn1mHriJnL2657jj0Ity6ueWmgGUYrC/sJzr0cGPZIv+OhVFIvJ6aCCoq4\r\n" +
"PI7d+f6K20hhrp9U/kROgT5BQ4s3/AZJRg7amyUdYKv0fUCfl5B5j2gPM7PF52sy\r\n" +
"QQDtwtZFo7hFzRqUsRSE9s0gy3kTI4+qFDSLizawwVFtxW1cd8s4H0N3nzX1h2yE\r\n" +
"u79f/KhtKpN4ZIAD86rRiMupwc0RCwff0D82iaSjOdJ3O47CSXK6PmzL/HHjJx8C\r\n" +
"Ww43N96NPhjAuvlmH5eSwTSIYOxzTviwkmrJfIRMzRFNGqd3rsY=\r\n" +
"-----END CERTIFICATE-----";
private static final String INTERMEDIATE = "-----BEGIN CERTIFICATE-----\r\n" +
"MIIHMDCCBOSgAwIBAgIUZd/hQcJl9LbtHRRLt6t8Yww3nSswQQYJKoZIhvcNAQEK\r\n" +
"MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF\r\n" +
"AKIDAgEgMFoxJjAkBgNVBAMMHXByb2NpbG9uIEdST1VQIFRlc3QgUm9vdENBIDAy\r\n" +
"MRAwDgYDVQQLDAdSb290IENBMREwDwYDVQQKDAhwcm9URUNUcjELMAkGA1UEBhMC\r\n" +
"REUwHhcNMjAxMTA5MTAxMDQ5WhcNMzQxMDA2MTAyMjMxWjBeMSswKQYDVQQDDCJw\r\n" +
"cm9jaWxvbiBHUk9VUCBUZXN0IENBIC0gRG9jU2lnbmVyMQ8wDQYDVQQLDAZTdWIg\r\n" +
"Q0ExETAPBgNVBAoMCHByb1RFQ1RyMQswCQYDVQQGEwJERTCCAiIwDQYJKoZIhvcN\r\n" +
"AQEBBQADggIPADCCAgoCggIBALbhm0+Lu20C1b5CkUaP6SPaTXIKbyeqi7yv6X6n\r\n" +
"4BGzXOugLXoIsgUTLtOPbz6LoSgkpOl+1p0M1anIye/htibkyygtKkal0dmmvpmI\r\n" +
"mG4v94BY7gukyLNIhjoNY51SEWPA1HurxCPlDiN3g5AtVWcu6qWGTNCVrboSQ/xb\r\n" +
"IYU1T9MKOMI0OjF1MxSvjhLNFUZmskYZww/X9HFiHVptwjwbvEz3jEdYR+6PsCJC\r\n" +
"d9In4A+YLy4LvSVef9HMqv+5WHffn9ZAmSEywQp0LuCkx0FHDx24Whl6iw6jpsWp\r\n" +
"OsI8aG8WnmAHmdKt4zZ6Bt1eSmneTwGoM3NwWkIwjeUX4YqE6OovTyIaJ9m2+I9m\r\n" +
"6nIDNJ/fcjBsUOVEw0Wp7jd8IwOhFAXIOqh2NkGUtN4k1SPohAByzFe4d7+jDtis\r\n" +
"g9dwj8OkUrZ5ajoscBlnkKZwybmJjCAsyf4hFVX/dxz/zUpsTHbeMeJBAy7EJmez\r\n" +
"wNJWLnIHYBQUJrsbYBn4Xu/qlbvyfsZru6UGc1VqsH+XnAG0URPCY3YiSTZSYqjy\r\n" +
"zy4qJnTxJVBI7jDsLrA3/meSGfyhtjvuBUgXmWSfXYXJn0tgxDbsT3I6hxvBKajg\r\n" +
"7EreApxUO8Z6KEJgs4jwGQv8acE9oIYxUTjHyXGCUnwFujnewa11hxtQSBE09jlW\r\n" +
"jRF1AgMBAAGjggGAMIIBfDASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaA\r\n" +
"FIdOO7ofYT3TScPp3Y82ptYIExN7MGcGCCsGAQUFBwEBBFswWTAqBggrBgEFBQcw\r\n" +
"AoYeaHR0cHM6Ly9wa2kucHJvdGVjdHIuZGUvaXNzdWVyMCsGCCsGAQUFBzABhh9o\r\n" +
"dHRwOi8vb2NzcC5wcm90ZWN0ci5kZS9zdGF0dXMvMIGsBgNVHR8EgaQwgaEwgZ6g\r\n" +
"PKA6hjhodHRwOi8vY3JsLnByb3RlY3RyLmRlL2NybC9wcm9jaWxvbl9HUk9VUF9U\r\n" +
"ZXN0X1Jvb3RDQV8wMqJepFwwWjEmMCQGA1UEAwwdcHJvY2lsb24gR1JPVVAgVGVz\r\n" +
"dCBSb290Q0EgMDIxEDAOBgNVBAsMB1Jvb3QgQ0ExETAPBgNVBAoMCHByb1RFQ1Ry\r\n" +
"MQswCQYDVQQGEwJERTAdBgNVHQ4EFgQU9tzTTKeY8e4AJzOFp8xfIlkaZ3AwDgYD\r\n" +
"VR0PAQH/BAQDAgEGMEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAa\r\n" +
"BgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAgEAUuVwmG18AUfdrzEf\r\n" +
"M/7T+f5Is32Mb1sCeKhYIyRDDoLgntenWDQOMoiw1L5xdgft/RIQLdyYe6OC++SB\r\n" +
"dofy4pnIOS45AJcd5mVI9hFb5i9xGICijYvE6mcXpzMxVr8UBQ7I6tNaN+VdOB2/\r\n" +
"zE84Tbz6T+joGgPrCJwj3RiRKKs/P63goYR0ZANacR9aSilkdAfwsy7XFd7ZdFQt\r\n" +
"MiJBja3umZTnhsjuUzVHq8L9/j99eftQLG7CiQftopMjJvnYzuYxabXeqgBpSobL\r\n" +
"WeNeKb63sVCQUftvLvgKM6qU9aImuKN7D7cWyR/8AAXlS8DJfYXpBgh+6l3LpvmS\r\n" +
"FRa7DkO9w+hGzQI5ZuGOMAf1QOaZnEVqLLAbxJSqsvMxRL147nGfpE+K18MA2yDO\r\n" +
"PQJIMtw3tIb/xkSHCl0QZtt/YRFNEKOf8VH2vYymAnCH7dBzneb1KC75ezFp1VrS\r\n" +
"ji7vXuKvzo7EK+JswhE1oiABE3oxwbDLkl73QxeMXnSVQhKhUb2wLMVRLuhD9QdC\r\n" +
"UlB/ruvzcaN4mFM8Z3bOjbAUccB/IuzRrDH5NvH+/Yh56eYcxRrcc1Do6ryCBUFM\r\n" +
"WcSJimEqS3+h9CJXVNaxpg1ZZWssA11r3MQGo9ZNfqm6GQAtEYddRIzIMrdzp3ES\r\n" +
"PJUnwGW19MtA2/PEUYFbEtHC1mE=\r\n" +
"-----END CERTIFICATE-----";
private static final String ROOT = "-----BEGIN CERTIFICATE-----\r\n" +
"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\r\n" +
"8F0vlRCo0BKROJnBc3HRBvViNQ==\r\n" +
"-----END CERTIFICATE-----";
public static void main(String[] args) {
System.out.println("start program");
// Execute with
// -Djava.security.auth.debug=certpath
// to see debug output from java
executeValidation(APPLICATION_WITHOUT_CRLISSUER, INTERMEDIATE, ROOT);
executeValidation(APPLICATION_WITH_CRLISSUER, INTERMEDIATE, ROOT);
System.out.println("end program");
}
private static void executeValidation(String application, String intermediate, String root) {
try {
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(null, "".toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X509");
Certificate applicationCertificate = cf
.generateCertificate(new ByteArrayInputStream(application.getBytes()));
Certificate intermediateCertificate = cf
.generateCertificate(new ByteArrayInputStream(intermediate.getBytes()));
Certificate rootCertificate = cf.generateCertificate(new ByteArrayInputStream(root.getBytes()));
keyStore.setCertificateEntry("application", applicationCertificate);
keyStore.setCertificateEntry("intermediate", intermediateCertificate);
keyStore.setCertificateEntry("root", rootCertificate);
String result = processValidationInternal(keyStore, applicationCertificate, true, false, false);
System.out.println(result);
} catch (IOException | GeneralSecurityException e) {
e.printStackTrace();
}
}
private static String processValidationInternal(KeyStore keyStore, Certificate certificate,
boolean revocationCheckEnabled,
boolean ignoreRevocationCheckFailures,
boolean oscpCheckEnabled) {
if (revocationCheckEnabled) {
System.setProperty("com.sun.security.enableCRLDP", "true");
if (oscpCheckEnabled) {
Security.setProperty("ocsp.enable", "true");
}
} else {
System.setProperty("com.sun.security.enableCRLDP", "false");
Security.setProperty("ocsp.enable", "false");
}
String warning = null;
try {
CertificateFactory cf = CertificateFactory.getInstance(certificate.getType());
CertPath certificatePath = cf.generateCertPath(Arrays.asList(certificate));
CertPathValidator cpv = CertPathValidator.getInstance(CertPathValidator.getDefaultType());
PKIXParameters defaultStoreParams = new PKIXParameters(keyStore);
defaultStoreParams.setRevocationEnabled(revocationCheckEnabled);
defaultStoreParams.setDate(new Date(System.currentTimeMillis()));
CertPathValidatorResult defaultStoreResult = cpv.validate(certificatePath, defaultStoreParams);
if (defaultStoreResult != null) {
// Default key store validates the certificate chain.
warning = "success";
}
} catch (CertPathValidatorException e) {
warning = e.getCause().getMessage();
} catch (RuntimeException | GeneralSecurityException e) {
System.out.println("Key store can not validate certificate:" + e.getMessage());
warning = e.getCause().getMessage();
}
return warning;
}
}
---------- END SOURCE ----------
FREQUENCY : always