mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-02 04:00:16 +00:00
7194452: Remove "Reverse" PKIX CertPathBuilder implementation
Reviewed-by: mullan
This commit is contained in:
parent
7cbdcf978d
commit
454ec2e69d
@ -102,8 +102,8 @@ public abstract class Builder {
|
||||
|
||||
/**
|
||||
* Verifies whether the input certificate completes the path.
|
||||
* When building forward, a trust anchor will complete the path.
|
||||
* When building reverse, the target certificate will complete the path.
|
||||
* When building in the forward direction, a trust anchor will
|
||||
* complete the path.
|
||||
*
|
||||
* @param cert the certificate to test
|
||||
* @return a boolean value indicating whether the cert completes the path.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,6 @@
|
||||
package sun.security.provider.certpath;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.*;
|
||||
import java.security.interfaces.DSAPublicKey;
|
||||
@ -194,7 +193,6 @@ class PKIX {
|
||||
|
||||
static class BuilderParams extends ValidatorParams {
|
||||
private PKIXBuilderParameters params;
|
||||
private boolean buildForward = true;
|
||||
private List<CertStore> stores;
|
||||
private X500Principal targetSubject;
|
||||
|
||||
@ -213,10 +211,6 @@ class PKIX {
|
||||
+ "targetCertConstraints parameter must be an "
|
||||
+ "X509CertSelector");
|
||||
}
|
||||
if (params instanceof SunCertPathBuilderParameters) {
|
||||
buildForward =
|
||||
((SunCertPathBuilderParameters)params).getBuildForward();
|
||||
}
|
||||
this.params = params;
|
||||
this.targetSubject = getTargetSubject(
|
||||
certStores(), (X509CertSelector)targetCertConstraints());
|
||||
@ -230,7 +224,6 @@ class PKIX {
|
||||
return stores;
|
||||
}
|
||||
int maxPathLength() { return params.getMaxPathLength(); }
|
||||
boolean buildForward() { return buildForward; }
|
||||
PKIXBuilderParameters params() { return params; }
|
||||
X500Principal targetSubject() { return targetSubject; }
|
||||
|
||||
|
||||
@ -1,551 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.provider.certpath;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.Principal;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertStore;
|
||||
import java.security.cert.CertStoreException;
|
||||
import java.security.cert.PKIXBuilderParameters;
|
||||
import java.security.cert.PKIXCertPathChecker;
|
||||
import java.security.cert.PKIXParameters;
|
||||
import java.security.cert.PKIXReason;
|
||||
import java.security.cert.TrustAnchor;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.X509CertSelector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import sun.security.provider.certpath.PKIX.BuilderParams;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.x509.Extension;
|
||||
import static sun.security.x509.PKIXExtensions.*;
|
||||
import sun.security.x509.X500Name;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
import sun.security.x509.PolicyMappingsExtension;
|
||||
|
||||
/**
|
||||
* This class represents a reverse builder, which is able to retrieve
|
||||
* matching certificates from CertStores and verify a particular certificate
|
||||
* against a ReverseState.
|
||||
*
|
||||
* @since 1.4
|
||||
* @author Sean Mullan
|
||||
* @author Yassir Elley
|
||||
*/
|
||||
|
||||
class ReverseBuilder extends Builder {
|
||||
|
||||
private Debug debug = Debug.getInstance("certpath");
|
||||
|
||||
private final Set<String> initPolicies;
|
||||
|
||||
/**
|
||||
* Initialize the builder with the input parameters.
|
||||
*
|
||||
* @param params the parameter set used to build a certification path
|
||||
*/
|
||||
ReverseBuilder(BuilderParams buildParams) {
|
||||
super(buildParams);
|
||||
|
||||
Set<String> initialPolicies = buildParams.initialPolicies();
|
||||
initPolicies = new HashSet<String>();
|
||||
if (initialPolicies.isEmpty()) {
|
||||
// if no initialPolicies are specified by user, set
|
||||
// initPolicies to be anyPolicy by default
|
||||
initPolicies.add(PolicyChecker.ANY_POLICY);
|
||||
} else {
|
||||
initPolicies.addAll(initialPolicies);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all certs from the specified CertStores that satisfy the
|
||||
* requirements specified in the parameters and the current
|
||||
* PKIX state (name constraints, policy constraints, etc).
|
||||
*
|
||||
* @param currentState the current state.
|
||||
* Must be an instance of <code>ReverseState</code>
|
||||
* @param certStores list of CertStores
|
||||
*/
|
||||
@Override
|
||||
Collection<X509Certificate> getMatchingCerts
|
||||
(State currState, List<CertStore> certStores)
|
||||
throws CertStoreException, CertificateException, IOException
|
||||
{
|
||||
ReverseState currentState = (ReverseState) currState;
|
||||
|
||||
if (debug != null)
|
||||
debug.println("In ReverseBuilder.getMatchingCerts.");
|
||||
|
||||
/*
|
||||
* The last certificate could be an EE or a CA certificate
|
||||
* (we may be building a partial certification path or
|
||||
* establishing trust in a CA).
|
||||
*
|
||||
* Try the EE certs before the CA certs. It will be more
|
||||
* common to build a path to an end entity.
|
||||
*/
|
||||
Collection<X509Certificate> certs =
|
||||
getMatchingEECerts(currentState, certStores);
|
||||
certs.addAll(getMatchingCACerts(currentState, certStores));
|
||||
|
||||
return certs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves all end-entity certificates which satisfy constraints
|
||||
* and requirements specified in the parameters and PKIX state.
|
||||
*/
|
||||
private Collection<X509Certificate> getMatchingEECerts
|
||||
(ReverseState currentState, List<CertStore> certStores)
|
||||
throws CertStoreException, CertificateException, IOException {
|
||||
|
||||
/*
|
||||
* Compose a CertSelector to filter out
|
||||
* certs which do not satisfy requirements.
|
||||
*
|
||||
* First, retrieve clone of current target cert constraints, and
|
||||
* then add more selection criteria based on current validation state.
|
||||
*/
|
||||
X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
|
||||
|
||||
/*
|
||||
* Match on issuer (subject of previous cert)
|
||||
*/
|
||||
sel.setIssuer(currentState.subjectDN);
|
||||
|
||||
/*
|
||||
* Match on certificate validity date.
|
||||
*/
|
||||
sel.setCertificateValid(buildParams.date());
|
||||
|
||||
/*
|
||||
* Policy processing optimizations
|
||||
*/
|
||||
if (currentState.explicitPolicy == 0)
|
||||
sel.setPolicy(getMatchingPolicies());
|
||||
|
||||
/*
|
||||
* If previous cert has a subject key identifier extension,
|
||||
* use it to match on authority key identifier extension.
|
||||
*/
|
||||
/*if (currentState.subjKeyId != null) {
|
||||
AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
|
||||
(KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
|
||||
null, null);
|
||||
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
|
||||
}*/
|
||||
|
||||
/*
|
||||
* Require EE certs
|
||||
*/
|
||||
sel.setBasicConstraints(-2);
|
||||
|
||||
/* Retrieve matching certs from CertStores */
|
||||
HashSet<X509Certificate> eeCerts = new HashSet<>();
|
||||
addMatchingCerts(sel, certStores, eeCerts, true);
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("ReverseBuilder.getMatchingEECerts got "
|
||||
+ eeCerts.size() + " certs.");
|
||||
}
|
||||
return eeCerts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves all CA certificates which satisfy constraints
|
||||
* and requirements specified in the parameters and PKIX state.
|
||||
*/
|
||||
private Collection<X509Certificate> getMatchingCACerts
|
||||
(ReverseState currentState, List<CertStore> certStores)
|
||||
throws CertificateException, CertStoreException, IOException {
|
||||
|
||||
/*
|
||||
* Compose a CertSelector to filter out
|
||||
* certs which do not satisfy requirements.
|
||||
*/
|
||||
X509CertSelector sel = new X509CertSelector();
|
||||
|
||||
/*
|
||||
* Match on issuer (subject of previous cert)
|
||||
*/
|
||||
sel.setIssuer(currentState.subjectDN);
|
||||
|
||||
/*
|
||||
* Match on certificate validity date.
|
||||
*/
|
||||
sel.setCertificateValid(buildParams.date());
|
||||
|
||||
/*
|
||||
* Match on target subject name (checks that current cert's
|
||||
* name constraints permit it to certify target).
|
||||
* (4 is the integer type for DIRECTORY name).
|
||||
*/
|
||||
byte[] subject = targetCertConstraints.getSubjectAsBytes();
|
||||
if (subject != null) {
|
||||
sel.addPathToName(4, subject);
|
||||
} else {
|
||||
X509Certificate cert = targetCertConstraints.getCertificate();
|
||||
if (cert != null) {
|
||||
sel.addPathToName(4,
|
||||
cert.getSubjectX500Principal().getEncoded());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Policy processing optimizations
|
||||
*/
|
||||
if (currentState.explicitPolicy == 0)
|
||||
sel.setPolicy(getMatchingPolicies());
|
||||
|
||||
/*
|
||||
* If previous cert has a subject key identifier extension,
|
||||
* use it to match on authority key identifier extension.
|
||||
*/
|
||||
/*if (currentState.subjKeyId != null) {
|
||||
AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
|
||||
(KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
|
||||
null, null);
|
||||
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
|
||||
}*/
|
||||
|
||||
/*
|
||||
* Require CA certs
|
||||
*/
|
||||
sel.setBasicConstraints(0);
|
||||
|
||||
/* Retrieve matching certs from CertStores */
|
||||
ArrayList<X509Certificate> reverseCerts = new ArrayList<>();
|
||||
addMatchingCerts(sel, certStores, reverseCerts, true);
|
||||
|
||||
/* Sort remaining certs using name constraints */
|
||||
Collections.sort(reverseCerts, new PKIXCertComparator());
|
||||
|
||||
if (debug != null)
|
||||
debug.println("ReverseBuilder.getMatchingCACerts got " +
|
||||
reverseCerts.size() + " certs.");
|
||||
return reverseCerts;
|
||||
}
|
||||
|
||||
/*
|
||||
* This inner class compares 2 PKIX certificates according to which
|
||||
* should be tried first when building a path to the target. For
|
||||
* now, the algorithm is to look at name constraints in each cert and those
|
||||
* which constrain the path closer to the target should be
|
||||
* ranked higher. Later, we may want to consider other components,
|
||||
* such as key identifiers.
|
||||
*/
|
||||
class PKIXCertComparator implements Comparator<X509Certificate> {
|
||||
|
||||
private Debug debug = Debug.getInstance("certpath");
|
||||
|
||||
@Override
|
||||
public int compare(X509Certificate cert1, X509Certificate cert2) {
|
||||
|
||||
/*
|
||||
* if either cert certifies the target, always
|
||||
* put at head of list.
|
||||
*/
|
||||
X500Principal targetSubject = buildParams.targetSubject();
|
||||
if (cert1.getSubjectX500Principal().equals(targetSubject)) {
|
||||
return -1;
|
||||
}
|
||||
if (cert2.getSubjectX500Principal().equals(targetSubject)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int targetDist1;
|
||||
int targetDist2;
|
||||
try {
|
||||
X500Name targetSubjectName = X500Name.asX500Name(targetSubject);
|
||||
targetDist1 = Builder.targetDistance(
|
||||
null, cert1, targetSubjectName);
|
||||
targetDist2 = Builder.targetDistance(
|
||||
null, cert2, targetSubjectName);
|
||||
} catch (IOException e) {
|
||||
if (debug != null) {
|
||||
debug.println("IOException in call to Builder.targetDistance");
|
||||
e.printStackTrace();
|
||||
}
|
||||
throw new ClassCastException
|
||||
("Invalid target subject distinguished name");
|
||||
}
|
||||
|
||||
if (targetDist1 == targetDist2)
|
||||
return 0;
|
||||
|
||||
if (targetDist1 == -1)
|
||||
return 1;
|
||||
|
||||
if (targetDist1 < targetDist2)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a matching certificate.
|
||||
*
|
||||
* This method executes any of the validation steps in the PKIX path validation
|
||||
* algorithm which were not satisfied via filtering out non-compliant
|
||||
* certificates with certificate matching rules.
|
||||
*
|
||||
* If the last certificate is being verified (the one whose subject
|
||||
* matches the target subject, then the steps in Section 6.1.4 of the
|
||||
* Certification Path Validation algorithm are NOT executed,
|
||||
* regardless of whether or not the last cert is an end-entity
|
||||
* cert or not. This allows callers to certify CA certs as
|
||||
* well as EE certs.
|
||||
*
|
||||
* @param cert the certificate to be verified
|
||||
* @param currentState the current state against which the cert is verified
|
||||
* @param certPathList the certPathList generated thus far
|
||||
*/
|
||||
@Override
|
||||
void verifyCert(X509Certificate cert, State currState,
|
||||
List<X509Certificate> certPathList)
|
||||
throws GeneralSecurityException
|
||||
{
|
||||
if (debug != null) {
|
||||
debug.println("ReverseBuilder.verifyCert(SN: "
|
||||
+ Debug.toHexString(cert.getSerialNumber())
|
||||
+ "\n Subject: " + cert.getSubjectX500Principal() + ")");
|
||||
}
|
||||
|
||||
ReverseState currentState = (ReverseState) currState;
|
||||
|
||||
/* we don't perform any validation of the trusted cert */
|
||||
if (currentState.isInitial()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't bother to verify untrusted certificate more.
|
||||
currentState.untrustedChecker.check(cert,
|
||||
Collections.<String>emptySet());
|
||||
|
||||
/*
|
||||
* check for looping - abort a loop if
|
||||
* ((we encounter the same certificate twice) AND
|
||||
* ((policyMappingInhibited = true) OR (no policy mapping
|
||||
* extensions can be found between the occurrences of the same
|
||||
* certificate)))
|
||||
* in order to facilitate the check to see if there are
|
||||
* any policy mapping extensions found between the occurrences
|
||||
* of the same certificate, we reverse the certpathlist first
|
||||
*/
|
||||
if ((certPathList != null) && (!certPathList.isEmpty())) {
|
||||
List<X509Certificate> reverseCertList = new ArrayList<>();
|
||||
for (X509Certificate c : certPathList) {
|
||||
reverseCertList.add(0, c);
|
||||
}
|
||||
|
||||
boolean policyMappingFound = false;
|
||||
for (X509Certificate cpListCert : reverseCertList) {
|
||||
X509CertImpl cpListCertImpl = X509CertImpl.toImpl(cpListCert);
|
||||
PolicyMappingsExtension policyMappingsExt =
|
||||
cpListCertImpl.getPolicyMappingsExtension();
|
||||
if (policyMappingsExt != null) {
|
||||
policyMappingFound = true;
|
||||
}
|
||||
if (debug != null)
|
||||
debug.println("policyMappingFound = " + policyMappingFound);
|
||||
if (cert.equals(cpListCert)) {
|
||||
if ((buildParams.policyMappingInhibited()) ||
|
||||
(!policyMappingFound)){
|
||||
if (debug != null)
|
||||
debug.println("loop detected!!");
|
||||
throw new CertPathValidatorException("loop detected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check if target cert */
|
||||
boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject());
|
||||
|
||||
/* check if CA cert */
|
||||
boolean caCert = (cert.getBasicConstraints() != -1 ? true : false);
|
||||
|
||||
/* if there are more certs to follow, verify certain constraints */
|
||||
if (!finalCert) {
|
||||
|
||||
/* check if CA cert */
|
||||
if (!caCert)
|
||||
throw new CertPathValidatorException("cert is NOT a CA cert");
|
||||
|
||||
/* If the certificate was not self-issued, verify that
|
||||
* remainingCerts is greater than zero
|
||||
*/
|
||||
if ((currentState.remainingCACerts <= 0) && !X509CertImpl.isSelfIssued(cert)) {
|
||||
throw new CertPathValidatorException
|
||||
("pathLenConstraint violated, path too long", null,
|
||||
null, -1, PKIXReason.PATH_TOO_LONG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check keyUsage extension (only if CA cert and not final cert)
|
||||
*/
|
||||
KeyChecker.verifyCAKeyUsage(cert);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* If final cert, check that it satisfies specified target
|
||||
* constraints
|
||||
*/
|
||||
if (targetCertConstraints.match(cert) == false) {
|
||||
throw new CertPathValidatorException("target certificate " +
|
||||
"constraints check failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check revocation.
|
||||
*/
|
||||
if (buildParams.revocationEnabled() && currentState.revChecker != null) {
|
||||
currentState.revChecker.check(cert, Collections.<String>emptySet());
|
||||
}
|
||||
|
||||
/* Check name constraints if this is not a self-issued cert */
|
||||
if (finalCert || !X509CertImpl.isSelfIssued(cert)){
|
||||
if (currentState.nc != null) {
|
||||
try {
|
||||
if (!currentState.nc.verify(cert)){
|
||||
throw new CertPathValidatorException
|
||||
("name constraints check failed", null, null, -1,
|
||||
PKIXReason.INVALID_NAME);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new CertPathValidatorException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check policy
|
||||
*/
|
||||
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
|
||||
currentState.rootNode = PolicyChecker.processPolicies
|
||||
(currentState.certIndex, initPolicies,
|
||||
currentState.explicitPolicy, currentState.policyMapping,
|
||||
currentState.inhibitAnyPolicy,
|
||||
buildParams.policyQualifiersRejected(), currentState.rootNode,
|
||||
certImpl, finalCert);
|
||||
|
||||
/*
|
||||
* Check CRITICAL private extensions
|
||||
*/
|
||||
Set<String> unresolvedCritExts = cert.getCriticalExtensionOIDs();
|
||||
if (unresolvedCritExts == null) {
|
||||
unresolvedCritExts = Collections.<String>emptySet();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the signature algorithm is not disabled.
|
||||
*/
|
||||
currentState.algorithmChecker.check(cert, unresolvedCritExts);
|
||||
|
||||
for (PKIXCertPathChecker checker : currentState.userCheckers) {
|
||||
checker.check(cert, unresolvedCritExts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at the remaining extensions and remove any ones we have
|
||||
* already checked. If there are any left, throw an exception!
|
||||
*/
|
||||
if (!unresolvedCritExts.isEmpty()) {
|
||||
unresolvedCritExts.remove(BasicConstraints_Id.toString());
|
||||
unresolvedCritExts.remove(NameConstraints_Id.toString());
|
||||
unresolvedCritExts.remove(CertificatePolicies_Id.toString());
|
||||
unresolvedCritExts.remove(PolicyMappings_Id.toString());
|
||||
unresolvedCritExts.remove(PolicyConstraints_Id.toString());
|
||||
unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString());
|
||||
unresolvedCritExts.remove(SubjectAlternativeName_Id.toString());
|
||||
unresolvedCritExts.remove(KeyUsage_Id.toString());
|
||||
unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString());
|
||||
|
||||
if (!unresolvedCritExts.isEmpty())
|
||||
throw new CertPathValidatorException
|
||||
("Unrecognized critical extension(s)", null, null, -1,
|
||||
PKIXReason.UNRECOGNIZED_CRIT_EXT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check signature.
|
||||
*/
|
||||
if (buildParams.sigProvider() != null) {
|
||||
cert.verify(currentState.pubKey, buildParams.sigProvider());
|
||||
} else {
|
||||
cert.verify(currentState.pubKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies whether the input certificate completes the path.
|
||||
* This checks whether the cert is the target certificate.
|
||||
*
|
||||
* @param cert the certificate to test
|
||||
* @return a boolean value indicating whether the cert completes the path.
|
||||
*/
|
||||
@Override
|
||||
boolean isPathCompleted(X509Certificate cert) {
|
||||
return cert.getSubjectX500Principal().equals(buildParams.targetSubject());
|
||||
}
|
||||
|
||||
/** Adds the certificate to the certPathList
|
||||
*
|
||||
* @param cert the certificate to be added
|
||||
* @param certPathList the certification path list
|
||||
*/
|
||||
@Override
|
||||
void addCertToPath(X509Certificate cert,
|
||||
LinkedList<X509Certificate> certPathList) {
|
||||
certPathList.addLast(cert);
|
||||
}
|
||||
|
||||
/** Removes final certificate from the certPathList
|
||||
*
|
||||
* @param certPathList the certification path list
|
||||
*/
|
||||
@Override
|
||||
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
|
||||
certPathList.removeLast();
|
||||
}
|
||||
}
|
||||
@ -1,406 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.provider.certpath;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.PKIXCertPathChecker;
|
||||
import java.security.cert.PKIXRevocationChecker;
|
||||
import java.security.cert.TrustAnchor;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import sun.security.provider.certpath.PKIX.BuilderParams;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.x509.NameConstraintsExtension;
|
||||
import sun.security.x509.SubjectKeyIdentifierExtension;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
|
||||
/**
|
||||
* A specification of a reverse PKIX validation state
|
||||
* which is initialized by each build and updated each time a
|
||||
* certificate is added to the current path.
|
||||
* @since 1.4
|
||||
* @author Sean Mullan
|
||||
* @author Yassir Elley
|
||||
*/
|
||||
|
||||
class ReverseState implements State {
|
||||
|
||||
private static final Debug debug = Debug.getInstance("certpath");
|
||||
|
||||
/* The subject DN of the last cert in the path */
|
||||
X500Principal subjectDN;
|
||||
|
||||
/* The subject public key of the last cert */
|
||||
PublicKey pubKey;
|
||||
|
||||
/* The subject key identifier extension (if any) of the last cert */
|
||||
SubjectKeyIdentifierExtension subjKeyId;
|
||||
|
||||
/* The PKIX constrained/excluded subtrees state variable */
|
||||
NameConstraintsExtension nc;
|
||||
|
||||
/* The PKIX explicit policy, policy mapping, and inhibit_any-policy
|
||||
state variables */
|
||||
int explicitPolicy;
|
||||
int policyMapping;
|
||||
int inhibitAnyPolicy;
|
||||
int certIndex;
|
||||
PolicyNodeImpl rootNode;
|
||||
|
||||
/* The number of remaining CA certs which may follow in the path.
|
||||
* -1: previous cert was an EE cert
|
||||
* 0: only EE certs may follow.
|
||||
* >0 and <Integer.MAX_VALUE:no more than this number of CA certs may follow
|
||||
* Integer.MAX_VALUE: unlimited
|
||||
*/
|
||||
int remainingCACerts;
|
||||
|
||||
/* The list of user-defined checkers retrieved from the PKIXParameters
|
||||
* instance */
|
||||
ArrayList<PKIXCertPathChecker> userCheckers;
|
||||
|
||||
/* Flag indicating if state is initial (path is just starting) */
|
||||
private boolean init = true;
|
||||
|
||||
/* the checker used for revocation status */
|
||||
RevocationChecker revChecker;
|
||||
|
||||
/* the algorithm checker */
|
||||
AlgorithmChecker algorithmChecker;
|
||||
|
||||
/* the untrusted certificates checker */
|
||||
UntrustedChecker untrustedChecker;
|
||||
|
||||
/* the trust anchor used to validate the path */
|
||||
TrustAnchor trustAnchor;
|
||||
|
||||
/* Flag indicating if current cert can vouch for the CRL for
|
||||
* the next cert
|
||||
*/
|
||||
boolean crlSign = true;
|
||||
|
||||
/**
|
||||
* Returns a boolean flag indicating if the state is initial
|
||||
* (just starting)
|
||||
*
|
||||
* @return boolean flag indicating if the state is initial (just starting)
|
||||
*/
|
||||
@Override
|
||||
public boolean isInitial() {
|
||||
return init;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display state for debugging purposes
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("State [");
|
||||
sb.append("\n subjectDN of last cert: ").append(subjectDN);
|
||||
sb.append("\n subjectKeyIdentifier: ").append
|
||||
(String.valueOf(subjKeyId));
|
||||
sb.append("\n nameConstraints: ").append(String.valueOf(nc));
|
||||
sb.append("\n certIndex: ").append(certIndex);
|
||||
sb.append("\n explicitPolicy: ").append(explicitPolicy);
|
||||
sb.append("\n policyMapping: ").append(policyMapping);
|
||||
sb.append("\n inhibitAnyPolicy: ").append(inhibitAnyPolicy);
|
||||
sb.append("\n rootNode: ").append(rootNode);
|
||||
sb.append("\n remainingCACerts: ").append(remainingCACerts);
|
||||
sb.append("\n crlSign: ").append(crlSign);
|
||||
sb.append("\n init: ").append(init);
|
||||
sb.append("\n]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the state.
|
||||
*
|
||||
* @param buildParams builder parameters
|
||||
*/
|
||||
public void initState(BuilderParams buildParams)
|
||||
throws CertPathValidatorException
|
||||
{
|
||||
/*
|
||||
* Initialize number of remainingCACerts.
|
||||
* Note that -1 maxPathLen implies unlimited.
|
||||
* 0 implies only an EE cert is acceptable.
|
||||
*/
|
||||
int maxPathLen = buildParams.maxPathLength();
|
||||
remainingCACerts = (maxPathLen == -1) ? Integer.MAX_VALUE
|
||||
: maxPathLen;
|
||||
|
||||
/* Initialize explicit policy state variable */
|
||||
if (buildParams.explicitPolicyRequired()) {
|
||||
explicitPolicy = 0;
|
||||
} else {
|
||||
// unconstrained if maxPathLen is -1,
|
||||
// otherwise, we want to initialize this to the value of the
|
||||
// longest possible path + 1 (i.e. maxpathlen + finalcert + 1)
|
||||
explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
|
||||
}
|
||||
|
||||
/* Initialize policy mapping state variable */
|
||||
if (buildParams.policyMappingInhibited()) {
|
||||
policyMapping = 0;
|
||||
} else {
|
||||
policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
|
||||
}
|
||||
|
||||
/* Initialize inhibit any policy state variable */
|
||||
if (buildParams.anyPolicyInhibited()) {
|
||||
inhibitAnyPolicy = 0;
|
||||
} else {
|
||||
inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
|
||||
}
|
||||
|
||||
/* Initialize certIndex */
|
||||
certIndex = 1;
|
||||
|
||||
/* Initialize policy tree */
|
||||
Set<String> initExpPolSet = new HashSet<>(1);
|
||||
initExpPolSet.add(PolicyChecker.ANY_POLICY);
|
||||
|
||||
rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null,
|
||||
false, initExpPolSet, false);
|
||||
|
||||
/*
|
||||
* Initialize each user-defined checker
|
||||
* Shallow copy the checkers
|
||||
*/
|
||||
userCheckers = new ArrayList<>(buildParams.certPathCheckers());
|
||||
/* initialize each checker (just in case) */
|
||||
for (PKIXCertPathChecker checker : userCheckers) {
|
||||
checker.init(false);
|
||||
}
|
||||
|
||||
/* Start by trusting the cert to sign CRLs */
|
||||
crlSign = true;
|
||||
|
||||
init = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state with the specified trust anchor.
|
||||
*
|
||||
* @param anchor the most-trusted CA
|
||||
* @param buildParams builder parameters
|
||||
*/
|
||||
public void updateState(TrustAnchor anchor, BuilderParams buildParams)
|
||||
throws CertificateException, IOException, CertPathValidatorException
|
||||
{
|
||||
trustAnchor = anchor;
|
||||
X509Certificate trustedCert = anchor.getTrustedCert();
|
||||
if (trustedCert != null) {
|
||||
updateState(trustedCert);
|
||||
} else {
|
||||
X500Principal caName = anchor.getCA();
|
||||
updateState(anchor.getCAPublicKey(), caName);
|
||||
}
|
||||
|
||||
// The user specified AlgorithmChecker and RevocationChecker may not be
|
||||
// able to set the trust anchor until now.
|
||||
boolean revCheckerAdded = false;
|
||||
for (PKIXCertPathChecker checker : userCheckers) {
|
||||
if (checker instanceof AlgorithmChecker) {
|
||||
((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
|
||||
} else if (checker instanceof PKIXRevocationChecker) {
|
||||
if (revCheckerAdded) {
|
||||
throw new CertPathValidatorException(
|
||||
"Only one PKIXRevocationChecker can be specified");
|
||||
}
|
||||
// if it's our own, initialize it
|
||||
if (checker instanceof RevocationChecker) {
|
||||
((RevocationChecker)checker).init(anchor, buildParams);
|
||||
}
|
||||
((PKIXRevocationChecker)checker).init(false);
|
||||
revCheckerAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
// only create a RevocationChecker if revocation is enabled and
|
||||
// a PKIXRevocationChecker has not already been added
|
||||
if (buildParams.revocationEnabled() && !revCheckerAdded) {
|
||||
revChecker = new RevocationChecker(anchor, buildParams);
|
||||
revChecker.init(false);
|
||||
}
|
||||
|
||||
init = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state. This method is used when the most-trusted CA is
|
||||
* a trusted public-key and caName, instead of a trusted cert.
|
||||
*
|
||||
* @param pubKey the public key of the trusted CA
|
||||
* @param subjectDN the subject distinguished name of the trusted CA
|
||||
*/
|
||||
private void updateState(PublicKey pubKey, X500Principal subjectDN) {
|
||||
|
||||
/* update subject DN */
|
||||
this.subjectDN = subjectDN;
|
||||
|
||||
/* update subject public key */
|
||||
this.pubKey = pubKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state with the next certificate added to the path.
|
||||
*
|
||||
* @param cert the certificate which is used to update the state
|
||||
*/
|
||||
public void updateState(X509Certificate cert)
|
||||
throws CertificateException, IOException, CertPathValidatorException {
|
||||
|
||||
if (cert == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* update subject DN */
|
||||
subjectDN = cert.getSubjectX500Principal();
|
||||
|
||||
/* check for key needing to inherit alg parameters */
|
||||
X509CertImpl icert = X509CertImpl.toImpl(cert);
|
||||
PublicKey newKey = cert.getPublicKey();
|
||||
if (PKIX.isDSAPublicKeyWithoutParams(newKey)) {
|
||||
newKey = BasicChecker.makeInheritedParamsKey(newKey, pubKey);
|
||||
}
|
||||
|
||||
/* update subject public key */
|
||||
pubKey = newKey;
|
||||
|
||||
/*
|
||||
* if this is a trusted cert (init == true), then we
|
||||
* don't update any of the remaining fields
|
||||
*/
|
||||
if (init) {
|
||||
init = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* update subject key identifier */
|
||||
subjKeyId = icert.getSubjectKeyIdentifierExtension();
|
||||
|
||||
/* update crlSign */
|
||||
crlSign = RevocationChecker.certCanSignCrl(cert);
|
||||
|
||||
/* update current name constraints */
|
||||
if (nc != null) {
|
||||
nc.merge(icert.getNameConstraintsExtension());
|
||||
} else {
|
||||
nc = icert.getNameConstraintsExtension();
|
||||
if (nc != null) {
|
||||
// Make sure we do a clone here, because we're probably
|
||||
// going to modify this object later and we don't want to
|
||||
// be sharing it with a Certificate object!
|
||||
nc = (NameConstraintsExtension) nc.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/* update policy state variables */
|
||||
explicitPolicy =
|
||||
PolicyChecker.mergeExplicitPolicy(explicitPolicy, icert, false);
|
||||
policyMapping =
|
||||
PolicyChecker.mergePolicyMapping(policyMapping, icert);
|
||||
inhibitAnyPolicy =
|
||||
PolicyChecker.mergeInhibitAnyPolicy(inhibitAnyPolicy, icert);
|
||||
certIndex++;
|
||||
|
||||
/*
|
||||
* Update remaining CA certs
|
||||
*/
|
||||
remainingCACerts =
|
||||
ConstraintsChecker.mergeBasicConstraints(cert, remainingCACerts);
|
||||
|
||||
init = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean flag indicating if a key lacking necessary key
|
||||
* algorithm parameters has been encountered.
|
||||
*
|
||||
* @return boolean flag indicating if key lacking parameters encountered.
|
||||
*/
|
||||
@Override
|
||||
public boolean keyParamsNeeded() {
|
||||
/* when building in reverse, we immediately get parameters needed
|
||||
* or else throw an exception
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clone current state. The state is cloned as each cert is
|
||||
* added to the path. This is necessary if backtracking occurs,
|
||||
* and a prior state needs to be restored.
|
||||
*
|
||||
* Note that this is a SMART clone. Not all fields are fully copied,
|
||||
* because some of them (e.g., subjKeyId) will
|
||||
* not have their contents modified by subsequent calls to updateState.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
|
||||
public Object clone() {
|
||||
try {
|
||||
ReverseState clonedState = (ReverseState) super.clone();
|
||||
|
||||
/* clone checkers, if cloneable */
|
||||
clonedState.userCheckers =
|
||||
(ArrayList<PKIXCertPathChecker>)userCheckers.clone();
|
||||
ListIterator<PKIXCertPathChecker> li =
|
||||
clonedState.userCheckers.listIterator();
|
||||
while (li.hasNext()) {
|
||||
PKIXCertPathChecker checker = li.next();
|
||||
if (checker instanceof Cloneable) {
|
||||
li.set((PKIXCertPathChecker)checker.clone());
|
||||
}
|
||||
}
|
||||
|
||||
/* make copy of name constraints */
|
||||
if (nc != null) {
|
||||
clonedState.nc = (NameConstraintsExtension) nc.clone();
|
||||
}
|
||||
|
||||
/* make copy of policy tree */
|
||||
if (rootNode != null) {
|
||||
clonedState.rootNode = rootNode.copyTree();
|
||||
}
|
||||
|
||||
return clonedState;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,8 +35,6 @@ import java.security.cert.PKIXReason;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
@ -47,8 +45,7 @@ import static sun.security.x509.PKIXExtensions.*;
|
||||
import sun.security.util.Debug;
|
||||
|
||||
/**
|
||||
* This class is able to build certification paths in either the forward
|
||||
* or reverse directions.
|
||||
* This class builds certification paths in the forward direction.
|
||||
*
|
||||
* <p> If successful, it returns a certification path which has successfully
|
||||
* satisfied all the constraints and requirements specified in the
|
||||
@ -102,10 +99,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
|
||||
/**
|
||||
* Attempts to build a certification path using the Sun build
|
||||
* algorithm from a trusted anchor(s) to a target subject, which must both
|
||||
* be specified in the input parameter set. By default, this method will
|
||||
* attempt to build in the forward direction. In order to build in the
|
||||
* reverse direction, the caller needs to pass in an instance of
|
||||
* SunCertPathBuilderParameters with the buildForward flag set to false.
|
||||
* be specified in the input parameter set. This method will
|
||||
* attempt to build in the forward direction: from the target to the CA.
|
||||
*
|
||||
* <p>The certification path that is constructed is validated
|
||||
* according to the PKIX specification.
|
||||
@ -162,11 +157,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
|
||||
policyTreeResult = null;
|
||||
LinkedList<X509Certificate> certPathList = new LinkedList<>();
|
||||
try {
|
||||
if (buildParams.buildForward()) {
|
||||
buildForward(adjList, certPathList, searchAllCertStores);
|
||||
} else {
|
||||
buildReverse(adjList, certPathList);
|
||||
}
|
||||
buildForward(adjList, certPathList, searchAllCertStores);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
if (debug != null) {
|
||||
debug.println("SunCertPathBuilder.engineBuild() exception in "
|
||||
@ -209,81 +200,6 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private build reverse method.
|
||||
*/
|
||||
private void buildReverse(List<List<Vertex>> adjacencyList,
|
||||
LinkedList<X509Certificate> certPathList)
|
||||
throws GeneralSecurityException, IOException
|
||||
{
|
||||
if (debug != null) {
|
||||
debug.println("SunCertPathBuilder.buildReverse()...");
|
||||
debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: "
|
||||
+ buildParams.initialPolicies());
|
||||
}
|
||||
|
||||
ReverseState currentState = new ReverseState();
|
||||
/* Initialize adjacency list */
|
||||
adjacencyList.clear();
|
||||
adjacencyList.add(new LinkedList<Vertex>());
|
||||
|
||||
/*
|
||||
* Perform a search using each trust anchor, until a valid
|
||||
* path is found
|
||||
*/
|
||||
Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator();
|
||||
while (iter.hasNext()) {
|
||||
TrustAnchor anchor = iter.next();
|
||||
|
||||
/* check if anchor satisfies target constraints */
|
||||
if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) {
|
||||
this.trustAnchor = anchor;
|
||||
this.pathCompleted = true;
|
||||
this.finalPublicKey = anchor.getTrustedCert().getPublicKey();
|
||||
break;
|
||||
}
|
||||
|
||||
// skip anchor if it contains a DSA key with no DSA params
|
||||
X509Certificate trustedCert = anchor.getTrustedCert();
|
||||
PublicKey pubKey = trustedCert != null ? trustedCert.getPublicKey()
|
||||
: anchor.getCAPublicKey();
|
||||
|
||||
if (PKIX.isDSAPublicKeyWithoutParams(pubKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialize current state */
|
||||
currentState.initState(buildParams);
|
||||
currentState.updateState(anchor, buildParams);
|
||||
|
||||
currentState.algorithmChecker = new AlgorithmChecker(anchor);
|
||||
currentState.untrustedChecker = new UntrustedChecker();
|
||||
try {
|
||||
depthFirstSearchReverse(null, currentState,
|
||||
new ReverseBuilder(buildParams),
|
||||
adjacencyList, certPathList);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
// continue on error if more anchors to try
|
||||
if (iter.hasNext())
|
||||
continue;
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
|
||||
// break out of loop if search is successful
|
||||
if (pathCompleted) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("SunCertPathBuilder.buildReverse() returned from "
|
||||
+ "depthFirstSearchReverse()");
|
||||
debug.println("SunCertPathBuilder.buildReverse() "
|
||||
+ "certPathList.size: " + certPathList.size());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Private build forward method.
|
||||
*/
|
||||
@ -631,147 +547,6 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method performs a depth first search for a certification
|
||||
* path while building reverse which meets the requirements set in
|
||||
* the parameters object.
|
||||
* It uses an adjacency list to store all certificates which were
|
||||
* tried (i.e. at one time added to the path - they may not end up in
|
||||
* the final path if backtracking occurs). This information can
|
||||
* be used later to debug or demo the build.
|
||||
*
|
||||
* See "Data Structure and Algorithms, by Aho, Hopcroft, and Ullman"
|
||||
* for an explanation of the DFS algorithm.
|
||||
*
|
||||
* @param dN the distinguished name being currently searched for certs
|
||||
* @param currentState the current PKIX validation state
|
||||
*/
|
||||
private void depthFirstSearchReverse(X500Principal dN,
|
||||
ReverseState currentState,
|
||||
ReverseBuilder builder,
|
||||
List<List<Vertex>> adjList,
|
||||
LinkedList<X509Certificate> cpList)
|
||||
throws GeneralSecurityException, IOException
|
||||
{
|
||||
if (debug != null)
|
||||
debug.println("SunCertPathBuilder.depthFirstSearchReverse(" + dN
|
||||
+ ", " + currentState.toString() + ")");
|
||||
|
||||
/*
|
||||
* Find all the certificates issued by dN which
|
||||
* satisfy the PKIX certification path constraints.
|
||||
*/
|
||||
Collection<X509Certificate> certs =
|
||||
builder.getMatchingCerts(currentState, buildParams.certStores());
|
||||
List<Vertex> vertices = addVertices(certs, adjList);
|
||||
if (debug != null)
|
||||
debug.println("SunCertPathBuilder.depthFirstSearchReverse(): "
|
||||
+ "certs.size=" + vertices.size());
|
||||
|
||||
/*
|
||||
* For each cert in the collection, verify anything
|
||||
* that hasn't been checked yet (signature, revocation, etc)
|
||||
* and check for loops. Call depthFirstSearchReverse()
|
||||
* recursively for each good cert.
|
||||
*/
|
||||
for (Vertex vertex : vertices) {
|
||||
/**
|
||||
* Restore state to currentState each time through the loop.
|
||||
* This is important because some of the user-defined
|
||||
* checkers modify the state, which MUST be restored if
|
||||
* the cert eventually fails to lead to the target and
|
||||
* the next matching cert is tried.
|
||||
*/
|
||||
ReverseState nextState = (ReverseState) currentState.clone();
|
||||
X509Certificate cert = vertex.getCertificate();
|
||||
try {
|
||||
builder.verifyCert(cert, nextState, cpList);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
if (debug != null)
|
||||
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
|
||||
+ ": validation failed: " + gse);
|
||||
vertex.setThrowable(gse);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Certificate is good, add it to the path (if it isn't a
|
||||
* self-signed cert) and update state
|
||||
*/
|
||||
if (!currentState.isInitial())
|
||||
builder.addCertToPath(cert, cpList);
|
||||
// save trust anchor
|
||||
this.trustAnchor = currentState.trustAnchor;
|
||||
|
||||
/*
|
||||
* Check if path is completed, return ASAP if so.
|
||||
*/
|
||||
if (builder.isPathCompleted(cert)) {
|
||||
if (debug != null)
|
||||
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
|
||||
+ ": path completed!");
|
||||
pathCompleted = true;
|
||||
|
||||
PolicyNodeImpl rootNode = nextState.rootNode;
|
||||
|
||||
if (rootNode == null)
|
||||
policyTreeResult = null;
|
||||
else {
|
||||
policyTreeResult = rootNode.copyTree();
|
||||
((PolicyNodeImpl)policyTreeResult).setImmutable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract and save the final target public key
|
||||
*/
|
||||
finalPublicKey = cert.getPublicKey();
|
||||
if (PKIX.isDSAPublicKeyWithoutParams(finalPublicKey)) {
|
||||
finalPublicKey =
|
||||
BasicChecker.makeInheritedParamsKey
|
||||
(finalPublicKey, currentState.pubKey);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update the PKIX state */
|
||||
nextState.updateState(cert);
|
||||
|
||||
/*
|
||||
* Append an entry for cert in adjacency list and
|
||||
* set index for current vertex.
|
||||
*/
|
||||
adjList.add(new LinkedList<Vertex>());
|
||||
vertex.setIndex(adjList.size() - 1);
|
||||
|
||||
/* recursively search for matching certs at next dN */
|
||||
depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState,
|
||||
builder, adjList, cpList);
|
||||
|
||||
/*
|
||||
* If path has been completed, return ASAP!
|
||||
*/
|
||||
if (pathCompleted) {
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* If we get here, it means we have searched all possible
|
||||
* certs issued by the dN w/o finding any matching certs. This
|
||||
* means we have to backtrack to the previous cert in the path
|
||||
* and try some other paths.
|
||||
*/
|
||||
if (debug != null)
|
||||
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
|
||||
+ ": backtracking");
|
||||
if (!currentState.isInitial())
|
||||
builder.removeFinalCertFromPath(cpList);
|
||||
}
|
||||
}
|
||||
if (debug != null)
|
||||
debug.println("SunCertPathBuilder.depthFirstSearchReverse() all "
|
||||
+ "certs in this adjacency list checked");
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a collection of matching certificates to the
|
||||
* adjacency list.
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.provider.certpath;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class specifies the set of parameters used as input for the Sun
|
||||
* certification path build algorithm. It is identical to PKIXBuilderParameters
|
||||
* with the addition of a <code>buildForward</code> parameter which allows
|
||||
* the caller to specify whether or not the path should be constructed in
|
||||
* the forward direction.
|
||||
*
|
||||
* The default for the <code>buildForward</code> parameter is
|
||||
* true, which means that the build algorithm should construct paths
|
||||
* from the target subject back to the trusted anchor.
|
||||
*
|
||||
* @since 1.4
|
||||
* @author Sean Mullan
|
||||
* @author Yassir Elley
|
||||
*/
|
||||
public class SunCertPathBuilderParameters extends PKIXBuilderParameters {
|
||||
|
||||
private boolean buildForward = true;
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>SunCertPathBuilderParameters</code> with the
|
||||
* specified parameter values.
|
||||
*
|
||||
* @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
|
||||
* @param targetConstraints a <code>CertSelector</code> specifying the
|
||||
* constraints on the target certificate
|
||||
* @throws InvalidAlgorithmParameterException if the specified
|
||||
* <code>Set</code> is empty <code>(trustAnchors.isEmpty() == true)</code>
|
||||
* @throws NullPointerException if the specified <code>Set</code> is
|
||||
* <code>null</code>
|
||||
* @throws ClassCastException if any of the elements in the <code>Set</code>
|
||||
* are not of type <code>java.security.cert.TrustAnchor</code>
|
||||
*/
|
||||
public SunCertPathBuilderParameters(Set<TrustAnchor> trustAnchors,
|
||||
CertSelector targetConstraints) throws InvalidAlgorithmParameterException
|
||||
{
|
||||
super(trustAnchors, targetConstraints);
|
||||
setBuildForward(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>SunCertPathBuilderParameters</code> that
|
||||
* uses the specified <code>KeyStore</code> to populate the set
|
||||
* of most-trusted CA certificates.
|
||||
*
|
||||
* @param keystore A keystore from which the set of most-trusted
|
||||
* CA certificates will be populated.
|
||||
* @param targetConstraints a <code>CertSelector</code> specifying the
|
||||
* constraints on the target certificate
|
||||
* @throws KeyStoreException if the keystore has not been initialized.
|
||||
* @throws InvalidAlgorithmParameterException if the keystore does
|
||||
* not contain at least one trusted certificate entry
|
||||
* @throws NullPointerException if the keystore is <code>null</code>
|
||||
*/
|
||||
public SunCertPathBuilderParameters(KeyStore keystore,
|
||||
CertSelector targetConstraints)
|
||||
throws KeyStoreException, InvalidAlgorithmParameterException
|
||||
{
|
||||
super(keystore, targetConstraints);
|
||||
setBuildForward(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the buildForward flag.
|
||||
*
|
||||
* @return the value of the buildForward flag
|
||||
*/
|
||||
public boolean getBuildForward() {
|
||||
return this.buildForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the buildForward flag. If true, paths
|
||||
* are built from the target subject to the trusted anchor.
|
||||
* If false, paths are built from the trusted anchor to the
|
||||
* target subject. The default value if not specified is true.
|
||||
*
|
||||
* @param buildForward the value of the buildForward flag
|
||||
*/
|
||||
public void setBuildForward(boolean buildForward) {
|
||||
this.buildForward = buildForward;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted string describing the parameters.
|
||||
*
|
||||
* @return a formatted string describing the parameters.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[\n");
|
||||
sb.append(super.toString());
|
||||
sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n");
|
||||
sb.append("]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6511784
|
||||
* @summary Make sure that building a path to a CRL issuer works in the
|
||||
* reverse direction
|
||||
* @library ../../../../../java/security/testlibrary
|
||||
* @build CertUtils
|
||||
* @run main BuildPath
|
||||
*/
|
||||
import java.security.cert.*;
|
||||
import java.util.Collections;
|
||||
import sun.security.provider.certpath.SunCertPathBuilderParameters;
|
||||
|
||||
public class BuildPath {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
TrustAnchor anchor =
|
||||
new TrustAnchor(CertUtils.getCertFromFile("mgrM2mgrM"), null);
|
||||
X509Certificate target = CertUtils.getCertFromFile("mgrM2leadMA");
|
||||
X509CertSelector xcs = new X509CertSelector();
|
||||
xcs.setSubject("CN=leadMA,CN=mgrM,OU=prjM,OU=divE,OU=Comp,O=sun,C=us");
|
||||
xcs.setCertificate(target);
|
||||
SunCertPathBuilderParameters params =
|
||||
new SunCertPathBuilderParameters(Collections.singleton(anchor),xcs);
|
||||
params.setBuildForward(false);
|
||||
CertStore cs = CertUtils.createStore(new String[]
|
||||
{"mgrM2prjM", "prjM2mgrM", "prjM2divE", "mgrM2leadMA" });
|
||||
params.addCertStore(cs);
|
||||
CertStore cs2 = CertUtils.createCRLStore
|
||||
(new String[] {"mgrMcrl", "prjMcrl"});
|
||||
params.addCertStore(cs2);
|
||||
PKIXCertPathBuilderResult res = CertUtils.build(params);
|
||||
}
|
||||
}
|
||||
@ -1,356 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
//
|
||||
// Security properties, once set, cannot revert to unset. To avoid
|
||||
// conflicts with tests running in the same VM isolate this test by
|
||||
// running it in otherVM mode.
|
||||
//
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7167988
|
||||
* @summary PKIX CertPathBuilder in reverse mode doesn't work if more than
|
||||
* one trust anchor is specified
|
||||
* @run main/othervm ReverseBuild
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.security.cert.*;
|
||||
import java.security.Security;
|
||||
|
||||
import sun.security.provider.certpath.SunCertPathBuilderParameters;
|
||||
|
||||
public class ReverseBuild {
|
||||
// Certificate information:
|
||||
// Issuer: C=US, ST=Some-State, L=Some-City, O=Some-Org
|
||||
// Validity
|
||||
// Not Before: Dec 8 02:43:36 2008 GMT
|
||||
// Not After : Aug 25 02:43:36 2028 GMT
|
||||
// Subject: C=US, ST=Some-State, L=Some-City, O=Some-Org
|
||||
// X509v3 Subject Key Identifier:
|
||||
// FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
|
||||
// X509v3 Authority Key Identifier:
|
||||
// keyid:FA:B9:51:BF:4C:E7:D9:86:98:33:F9:E7:CB:1E:F1:33:49:F7:A8:14
|
||||
// DirName:/C=US/ST=Some-State/L=Some-City/O=Some-Org
|
||||
// serial:00
|
||||
static String NoiceTrusedCertStr =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICrDCCAhWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBJMQswCQYDVQQGEwJVUzET\n" +
|
||||
"MBEGA1UECBMKU29tZS1TdGF0ZTESMBAGA1UEBxMJU29tZS1DaXR5MREwDwYDVQQK\n" +
|
||||
"EwhTb21lLU9yZzAeFw0wODEyMDgwMjQzMzZaFw0yODA4MjUwMjQzMzZaMEkxCzAJ\n" +
|
||||
"BgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMRIwEAYDVQQHEwlTb21lLUNp\n" +
|
||||
"dHkxETAPBgNVBAoTCFNvbWUtT3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
|
||||
"gQDLxDggB76Ip5OwoUNRLdeOha9U3a2ieyNbz5kTU5lFfe5tui2/461uPZ8a+QOX\n" +
|
||||
"4BdVrhEmV94BKY4FPyH35zboLjfXSKxT1mAOx1Bt9sWF94umxZE1cjyU7vEX8HHj\n" +
|
||||
"7BvOyk5AQrBt7moO1uWtPA/JuoJPePiJl4kqlRJM2Akq6QIDAQABo4GjMIGgMB0G\n" +
|
||||
"A1UdDgQWBBT6uVG/TOfZhpgz+efLHvEzSfeoFDBxBgNVHSMEajBogBT6uVG/TOfZ\n" +
|
||||
"hpgz+efLHvEzSfeoFKFNpEswSTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUt\n" +
|
||||
"U3RhdGUxEjAQBgNVBAcTCVNvbWUtQ2l0eTERMA8GA1UEChMIU29tZS1PcmeCAQAw\n" +
|
||||
"DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBcIm534U123Hz+rtyYO5uA\n" +
|
||||
"ofd81G6FnTfEAV8Kw9fGyyEbQZclBv34A9JsFKeMvU4OFIaixD7nLZ/NZ+IWbhmZ\n" +
|
||||
"LovmJXyCkOufea73pNiZ+f/4/ScZaIlM/PRycQSqbFNd4j9Wott+08qxHPLpsf3P\n" +
|
||||
"6Mvf0r1PNTY2hwTJLJmKtg==\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
// Certificate information:
|
||||
// Issuer: C=US, O=Java, OU=SunJSSE Test Serivce
|
||||
// Validity
|
||||
// Not Before: Aug 19 01:52:19 2011 GMT
|
||||
// Not After : Jul 29 01:52:19 2032 GMT
|
||||
// Subject: C=US, O=Java, OU=SunJSSE Test Serivce
|
||||
|
||||
// X509v3 Subject Key Identifier:
|
||||
// B9:7C:D5:D9:DF:A7:4C:03:AE:FD:0E:27:5B:31:95:6C:C7:F3:75:E1
|
||||
// X509v3 Authority Key Identifier:
|
||||
// keyid:B9:7C:D5:D9:DF:A7:4C:03:AE:FD:0E:27:5B:31:95:6C:C7:F3:75:E1
|
||||
// DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
|
||||
// serial:00
|
||||
static String NoiceTrusedCertStr_2nd =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
|
||||
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
|
||||
"MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
|
||||
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
|
||||
"KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" +
|
||||
"ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" +
|
||||
"iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" +
|
||||
"vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" +
|
||||
"MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" +
|
||||
"EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
|
||||
"Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" +
|
||||
"BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" +
|
||||
"pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" +
|
||||
"XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
|
||||
|
||||
// Certificate information:
|
||||
// Issuer: C=US, O=Java, OU=SunJSSE Test Serivce
|
||||
// Validity
|
||||
// Not Before: May 5 02:40:50 2012 GMT
|
||||
// Not After : Apr 15 02:40:50 2033 GMT
|
||||
// Subject: C=US, O=Java, OU=SunJSSE Test Serivce
|
||||
// X509v3 Subject Key Identifier:
|
||||
// DD:4E:8D:2A:11:C0:83:03:F0:AC:EB:A2:BF:F9:F2:7D:C8:69:1F:9B
|
||||
// X509v3 Authority Key Identifier:
|
||||
// keyid:DD:4E:8D:2A:11:C0:83:03:F0:AC:EB:A2:BF:F9:F2:7D:C8:69:1F:9B
|
||||
// DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
|
||||
// serial:00
|
||||
static String trustedCertStr =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
|
||||
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
|
||||
"MTIwNTA1MDI0MDUwWhcNMzMwNDE1MDI0MDUwWjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
|
||||
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
|
||||
"KoZIhvcNAQEBBQADgY0AMIGJAoGBANtiq0AIJK+iVRwFrqcD7fYXTCbMYC5Qz/k6\n" +
|
||||
"AXBy7/1rI8wDhEJLE3m/+NSqiJwZcmdq2dNh/1fJFrwvzuURbc9+paOBWeHbN+Sc\n" +
|
||||
"x3huw91oPZme385VpoK3G13rSE114S/rF4DM9mz4EStFhSHXATjtdbskNOAYGLTV\n" +
|
||||
"x8uEy9GbAgMBAAGjgaUwgaIwHQYDVR0OBBYEFN1OjSoRwIMD8Kzror/58n3IaR+b\n" +
|
||||
"MGMGA1UdIwRcMFqAFN1OjSoRwIMD8Kzror/58n3IaR+boT+kPTA7MQswCQYDVQQG\n" +
|
||||
"EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
|
||||
"Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
|
||||
"BQADgYEAjjkJesQrkbr36N40egybaIxw7RcqT6iy5fkAGS1JYlBDk8uSCK1o6bCH\n" +
|
||||
"ls5EpYcGeEoabSS73WRdkO1lgeyWDduO4ef8cCCSpmpT6/YdZG0QS1PtcREeVig+\n" +
|
||||
"Zr25jNemS4ADHX0aaXP4kiV/G80cR7nX5t5XCUm4bYdbwM07NgI=\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
static String trustedPrivateKey = // Private key in the format of PKCS#8
|
||||
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANtiq0AIJK+iVRwF\n" +
|
||||
"rqcD7fYXTCbMYC5Qz/k6AXBy7/1rI8wDhEJLE3m/+NSqiJwZcmdq2dNh/1fJFrwv\n" +
|
||||
"zuURbc9+paOBWeHbN+Scx3huw91oPZme385VpoK3G13rSE114S/rF4DM9mz4EStF\n" +
|
||||
"hSHXATjtdbskNOAYGLTVx8uEy9GbAgMBAAECgYEA2VjHkIiA0ABjkX+PqKeb+VLb\n" +
|
||||
"fxS7tSca5C8zfdRhLxAWRui0/3ihst0eCJNrBDuxvAOACovsDWyLuaUjtI2v2ysz\n" +
|
||||
"vz6SPyGy82PhQOFzyKQuQ814N6EpothpiZzF0yFchfKIGhUsdY89UrGs9nM7m6NT\n" +
|
||||
"rztYvgIu4avg2VPR2AECQQD+pFAqipR2BplQRIuuRSZfHRxvoEyDjT1xnHJsC6WP\n" +
|
||||
"I5hCLghL91MhQGWbP4EJMKYQOTRVukWlcp2Kycpf+P5hAkEA3I43gmVUAPEdyZdY\n" +
|
||||
"fatW7OaLlbbYJb6qEtpCZ1Rwe/BIvm6H6E3qSi/lpz7Ia7WDulpbF6BawHH3pRFq\n" +
|
||||
"CUY5ewJBAP3pUDqrRpBN0jB0uSeDslhjSciQ+dqvSpZv3rSYBHUvlBJhnkpJiy37\n" +
|
||||
"7ZUZhIxqYxyIPgRBolLwb+FFh7OdL+ECQCtldDic9WVmC+VheRDpCKZ+SlK/8lGi\n" +
|
||||
"7VXeShiIvcU1JysJFoa35fSI7hf1O3wt7+hX5PqGG7Un94EsJwACKEcCQQC1TWt6\n" +
|
||||
"ArKH6tRxKjOxFtqfs8fgEVYUaOr3j1jF4KBUuX2mtQtddZe3VfJ2wPsuKMMxmhkB\n" +
|
||||
"e7xWWZnJsErt2e+E";
|
||||
|
||||
// Certificate information:
|
||||
// Issuer: C=US, O=Java, OU=SunJSSE Test Serivce
|
||||
// Validity
|
||||
// Not Before: May 5 02:40:53 2012 GMT
|
||||
// Not After : Jan 21 02:40:53 2032 GMT
|
||||
// Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=casigner
|
||||
// X509v3 Subject Key Identifier:
|
||||
// 13:07:E0:11:07:DB:EB:33:23:87:31:D0:DB:7E:16:56:BE:11:90:0A
|
||||
// X509v3 Authority Key Identifier:
|
||||
// keyid:DD:4E:8D:2A:11:C0:83:03:F0:AC:EB:A2:BF:F9:F2:7D:C8:69:1F:9B
|
||||
// DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
|
||||
// serial:00
|
||||
static String caSignerStr =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICqDCCAhGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
|
||||
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
|
||||
"MTIwNTA1MDI0MDUzWhcNMzIwMTIxMDI0MDUzWjBOMQswCQYDVQQGEwJVUzENMAsG\n" +
|
||||
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxETAPBgNV\n" +
|
||||
"BAMTCGNhc2lnbmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+x8+o7oM0\n" +
|
||||
"ct/LZmZLXBL4CQ8jrULD5P7NtEW0hg/zxBFZfBHf+44Oo2eMPYZj+7xaREOH5BmV\n" +
|
||||
"KRYlzRtONAaC5Ng4Mrm5UKNPcMIIUjUOvm7vWM4oSTMSfoEcSX+vp99uUAkw3w7Z\n" +
|
||||
"+frYDm1M4At/j0b+lLij71GFN2L8drpgPQIDAQABo4GoMIGlMB0GA1UdDgQWBBQT\n" +
|
||||
"B+ARB9vrMyOHMdDbfhZWvhGQCjBjBgNVHSMEXDBagBTdTo0qEcCDA/Cs66K/+fJ9\n" +
|
||||
"yGkfm6E/pD0wOzELMAkGA1UEBhMCVVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsT\n" +
|
||||
"FFN1bkpTU0UgVGVzdCBTZXJpdmNlggEAMBIGA1UdEwEB/wQIMAYBAf8CAQEwCwYD\n" +
|
||||
"VR0PBAQDAgEGMA0GCSqGSIb3DQEBBAUAA4GBAI+LXA/UCPkTANablUkt80JNPWsl\n" +
|
||||
"pS4XLNgPxWaN0bkRDs5oI4ooWAz1rwpeJ/nfetOvWlpmrVjSeovBFja5Hl+dUHTf\n" +
|
||||
"VfuyzkxXbhuNiJIpo1mVBpNsjwu9YRxuwX6UA2LTUQpgvtVJEE012x3zRvxBCbu2\n" +
|
||||
"Y/v1R5fZ4c+hXDfC\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
static String caSignerPrivateKey = // Private key in the format of PKCS#8
|
||||
"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL7Hz6jugzRy38tm\n" +
|
||||
"ZktcEvgJDyOtQsPk/s20RbSGD/PEEVl8Ed/7jg6jZ4w9hmP7vFpEQ4fkGZUpFiXN\n" +
|
||||
"G040BoLk2DgyublQo09wwghSNQ6+bu9YzihJMxJ+gRxJf6+n325QCTDfDtn5+tgO\n" +
|
||||
"bUzgC3+PRv6UuKPvUYU3Yvx2umA9AgMBAAECgYBYvu30cW8LONyt62Zua9hPFTe7\n" +
|
||||
"qt9B7QYyfkdmoG5PQMepTrOp84SzfoOukvgvDm0huFuJnSvhXQl2cCDhkgXskvFj\n" +
|
||||
"Hh7KBCFViVXokGdq5YoS0/KYMyQV0TZfJUvILBl51uc4/siQ2tClC/N4sa+1JhgW\n" +
|
||||
"a6dFGfRjiUKSSlmMwQJBAPWpIz3Q/c+DYMvoQr5OD8EaYwYIevlTdXb97RnJJh2b\n" +
|
||||
"UnhB9jrqesJiHYVzPmP0ukyPOXOwlp2T5Am4Kw0LFOkCQQDGz150NoHOp28Mvyc4\n" +
|
||||
"CTqz/zYzUhy2eCJESl196uyP4N65Y01VYQ3JDww4DlsXiU17tVSbgA9TCcfTYOzy\n" +
|
||||
"vyw1AkARUky+1hafZCcWGZljK8PmnMKwsTZikCTvL/Zg5BMA8Wu+OQBwpQnk3OAy\n" +
|
||||
"Aa87gw0DyvGFG8Vy9POWT9sRP1/JAkBqP0hrMvYMSs6+MSn0eHo2151PsAJIQcuO\n" +
|
||||
"U2/Da1khSzu8N6WMi2GiobgV/RYRbf9KrY2ZzMZjykZQYOxAjopBAkEAghCu38cN\n" +
|
||||
"aOsW6ueo24uzsWI1FTdE+qWNVEi3RSP120xXBCyhaBjIq4WVSlJK9K2aBaJpit3j\n" +
|
||||
"iQ5tl6zrLlxQhg==";
|
||||
|
||||
// Certificate information:
|
||||
// Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=casigner
|
||||
// Validity
|
||||
// Not Before: May 5 02:40:57 2012 GMT
|
||||
// Not After : Jan 21 02:40:57 2032 GMT
|
||||
// Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer
|
||||
// X509v3 Subject Key Identifier:
|
||||
// 39:0E:C6:33:B1:50:BC:73:07:31:E5:D8:04:F7:BB:97:55:CF:9B:C8
|
||||
// X509v3 Authority Key Identifier:
|
||||
// keyid:13:07:E0:11:07:DB:EB:33:23:87:31:D0:DB:7E:16:56:BE:11:90:0A
|
||||
// DirName:/C=US/O=Java/OU=SunJSSE Test Serivce
|
||||
// serial:02
|
||||
static String certIssuerStr =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICvjCCAiegAwIBAgIBAzANBgkqhkiG9w0BAQQFADBOMQswCQYDVQQGEwJVUzEN\n" +
|
||||
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxETAP\n" +
|
||||
"BgNVBAMTCGNhc2lnbmVyMB4XDTEyMDUwNTAyNDA1N1oXDTMyMDEyMTAyNDA1N1ow\n" +
|
||||
"UDELMAkGA1UEBhMCVVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0Ug\n" +
|
||||
"VGVzdCBTZXJpdmNlMRMwEQYDVQQDEwpjZXJ0aXNzdWVyMIGfMA0GCSqGSIb3DQEB\n" +
|
||||
"AQUAA4GNADCBiQKBgQCyz55zinU6kNL/LeiTNiBI0QWYmDG0YTotuC4D75liBNqs\n" +
|
||||
"7Mmladsh2mTtQUAwmuGaGzaZV25a+cUax0DXZoyBwdbTI09u1bUYsZcaUUKbPoCC\n" +
|
||||
"HH26e4jLFL4olW13Sv4ZAd57tIYevMw+Fp5f4fLPFGegCJTFlv2Qjpmic/cuvQID\n" +
|
||||
"AQABo4GpMIGmMB0GA1UdDgQWBBQ5DsYzsVC8cwcx5dgE97uXVc+byDBjBgNVHSME\n" +
|
||||
"XDBagBQTB+ARB9vrMyOHMdDbfhZWvhGQCqE/pD0wOzELMAkGA1UEBhMCVVMxDTAL\n" +
|
||||
"BgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0UgVGVzdCBTZXJpdmNlggECMBMG\n" +
|
||||
"A1UdEwEB/wQJMAcBAf8CAgQAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQQFAAOB\n" +
|
||||
"gQCQTagenCdClT98C+oTJGJrw/dUBD9K3tE6ZJKPMc/2bUia8G5ei1C0eXj4mWG2\n" +
|
||||
"lu9umR6C90/A6qB050QB2h50qtqxSrkpu+ym1yypauZpg7U3nUY9wZWJNI1vqrQZ\n" +
|
||||
"pqUMRcXY3iQIVKx+Qj+4/Za1wwFQzpEoGmqRW31V1SdMEw==\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
static String certIssuerPrivateKey = // Private key in the format of PKCS#8
|
||||
"MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBALLPnnOKdTqQ0v8t\n" +
|
||||
"6JM2IEjRBZiYMbRhOi24LgPvmWIE2qzsyaVp2yHaZO1BQDCa4ZobNplXblr5xRrH\n" +
|
||||
"QNdmjIHB1tMjT27VtRixlxpRQps+gIIcfbp7iMsUviiVbXdK/hkB3nu0hh68zD4W\n" +
|
||||
"nl/h8s8UZ6AIlMWW/ZCOmaJz9y69AgMBAAECgYEAjtew2tgm4gxDojqIauF4VPM1\n" +
|
||||
"pzsdqd1p3pAdomNLgrQiBLZ8N7oiph6TNb1EjA+OXc+ThFgF/oM9ZDD8qZZwcvjN\n" +
|
||||
"qDZlpTkFs2TaGcyEZfUaMB45NHVs6Nn+pSkagSNwwy3xeyAct7sQEzGNTDlEwVv5\n" +
|
||||
"7V9LQutQtBd6xT48KzkCQQDpNRfv2OFNG/6GtzJoO68oJhpnpl2MsYNi4ntRkre/\n" +
|
||||
"6uXpiCYaDskcrPMRwOOs0m7mxG+Ev+uKnLnSoEMm1GCbAkEAxEmDtiD0Psb8Z9BL\n" +
|
||||
"ZRb83Jqho3xe2MCAh3xUfz9b/Mhae9dZ44o4OCgQZuwvW1mczF0NtpgZl93BmYa2\n" +
|
||||
"hTwHhwJBAKHrEj6ep/fA6x0gD2idoATRR94VfbiU+7NpqtO9ecVP0+gsdr/66hn1\n" +
|
||||
"3yLBeZLh3MxvMTrLgkAQh1i9m0JXjOcCQQClLXAHHegrw+u3uNMZeKTFR+Lp3sk6\n" +
|
||||
"AZSnbvr0Me9I45kxSeG81x3ENALJecvIRbrrRws5MvmmkNhQR8rkh8WVAkEAk6b+\n" +
|
||||
"aVtmBgUaTS5+FFlHGHJY9HFrfT1a1C/dwyMuqlmbC3YsBmZaMOlKli5TXNybLff8\n" +
|
||||
"5KMeGEpXMzgC7AscGA==";
|
||||
|
||||
// Certificate information:
|
||||
// Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer
|
||||
// Validity
|
||||
// Not Before: May 5 02:41:01 2012 GMT
|
||||
// Not After : Jan 21 02:41:01 2032 GMT
|
||||
// Subject: C=US, O=Java, OU=SunJSSE Test Serivce, CN=localhost
|
||||
// X509v3 Subject Key Identifier:
|
||||
// AD:C0:2C:4C:E4:C2:2E:A1:BB:5D:92:BE:66:E0:4E:E0:0D:2F:11:EF
|
||||
// X509v3 Authority Key Identifier:
|
||||
// keyid:39:0E:C6:33:B1:50:BC:73:07:31:E5:D8:04:F7:BB:97:55:CF:9B:C8
|
||||
static String targetCertStr =
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIICjTCCAfagAwIBAgIBBDANBgkqhkiG9w0BAQQFADBQMQswCQYDVQQGEwJVUzEN\n" +
|
||||
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEzAR\n" +
|
||||
"BgNVBAMTCmNlcnRpc3N1ZXIwHhcNMTIwNTA1MDI0MTAxWhcNMzIwMTIxMDI0MTAx\n" +
|
||||
"WjBPMQswCQYDVQQGEwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNT\n" +
|
||||
"RSBUZXN0IFNlcml2Y2UxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0B\n" +
|
||||
"AQEFAAOBjQAwgYkCgYEAvwaUd7wmBSKqycEstYLWD26vkU08DM39EtaT8wL9HnQ0\n" +
|
||||
"fgPblwBFI4zdLa2cuYXRZcFUb04N8nrkcpR0D6kkE+AlFAoRWrrZF80B7JTbtEK4\n" +
|
||||
"1PIeurihXvUT+4MpzGLOojIihMfvM4ufelblD56SInso4WFHm7t4qCln88J1gjkC\n" +
|
||||
"AwEAAaN4MHYwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBStwCxM5MIuobtdkr5m4E7g\n" +
|
||||
"DS8R7zAfBgNVHSMEGDAWgBQ5DsYzsVC8cwcx5dgE97uXVc+byDAnBgNVHSUEIDAe\n" +
|
||||
"BggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GB\n" +
|
||||
"AGfwcfdvEG/nSCiAn2MGbYHp34mgF3OA1SJLWUW0LvWJhwm2cn4AXlSoyvbwrkaB\n" +
|
||||
"IDDCwhJvvc0vUyL2kTx7sqVaFTq3mDs+ktlB/FfH0Pb+i8FE+g+7T42Iw/j0qxHL\n" +
|
||||
"YmgbrjBQf5WYN1AvBE/rrPt9aOtS3UsqtVGW574b0shW\n" +
|
||||
"-----END CERTIFICATE-----";
|
||||
static String targetPrivateKey = // Private key in the format of PKCS#8
|
||||
"MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAL8GlHe8JgUiqsnB\n" +
|
||||
"LLWC1g9ur5FNPAzN/RLWk/MC/R50NH4D25cARSOM3S2tnLmF0WXBVG9ODfJ65HKU\n" +
|
||||
"dA+pJBPgJRQKEVq62RfNAeyU27RCuNTyHrq4oV71E/uDKcxizqIyIoTH7zOLn3pW\n" +
|
||||
"5Q+ekiJ7KOFhR5u7eKgpZ/PCdYI5AgMBAAECf3CscOYvFD3zNMnMJ5LomVqA7w3F\n" +
|
||||
"gKYM2jlCWAH+wU41PMEXhW6Lujw92jgXL1o+lERwxFzirVdZJWZwKgUSvzP1G0h3\n" +
|
||||
"fkucq1/UWnToK+8NSXNM/yS8hXbBgSEoJo5f7LKcIi1Ev6doBVofMxs+njzyWKbM\n" +
|
||||
"Nb7rOLHadghoon0CQQDgQzbzzSN8Dc1YmmylhI5v+0sQRHH0DL7D24k4Weh4vInG\n" +
|
||||
"EAbt4x8M7ZKEo8/dv0s4hbmNmAnJl93/RRxIyEqLAkEA2g87DiswSQam2pZ8GlrO\n" +
|
||||
"+w4Qg9mH8uxx8ou2rl0XlHzH1XiTNbkjfY0EZoL7L31BHFk9n11Fb2P85g6ws+Hy\n" +
|
||||
"ywJAM/xgyLNM/nzUlS128geAXUULaYH0SHaL4isJ7B4rXZGW/mrIsGxtzjlkNYsj\n" +
|
||||
"rGujrD6TfNc5rZmexIXowJZtcQJBAIww+pCzZ4mrgx5JXWQ8OZHiiu+ZrPOa2+9J\n" +
|
||||
"r5sOMpi+WGN/73S8oHqZbNjTINZ5OqEVJq8MchWZPQBTNXuQql0CQHEjUzzkCQa3\n" +
|
||||
"j6JTa2KAdqyvLOx0XF9zcc1gA069uNQI2gPUHS8V215z57f/gMGnDNhVfLs/vMKz\n" +
|
||||
"sFkVZ3zg7As=";
|
||||
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// MD5 is used in this test case, don't disable MD5 algorithm.
|
||||
Security.setProperty(
|
||||
"jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024");
|
||||
|
||||
// generate certificate from cert string
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
|
||||
// create a set of trust anchors
|
||||
LinkedHashSet<TrustAnchor> trustAnchors = new LinkedHashSet<>();
|
||||
|
||||
ByteArrayInputStream is =
|
||||
new ByteArrayInputStream(NoiceTrusedCertStr.getBytes());
|
||||
Certificate trustedCert = cf.generateCertificate(is);
|
||||
is.close();
|
||||
TrustAnchor anchor =
|
||||
new TrustAnchor((X509Certificate)trustedCert, null);
|
||||
trustAnchors.add(anchor);
|
||||
|
||||
is = new ByteArrayInputStream(trustedCertStr.getBytes());
|
||||
trustedCert = cf.generateCertificate(is);
|
||||
is.close();
|
||||
anchor = new TrustAnchor((X509Certificate)trustedCert, null);
|
||||
trustAnchors.add(anchor);
|
||||
|
||||
is = new ByteArrayInputStream(NoiceTrusedCertStr_2nd.getBytes());
|
||||
trustedCert = cf.generateCertificate(is);
|
||||
is.close();
|
||||
anchor = new TrustAnchor((X509Certificate)trustedCert, null);
|
||||
trustAnchors.add(anchor);
|
||||
|
||||
// create a list of certificates
|
||||
List<Certificate> chainList = new ArrayList<>();
|
||||
|
||||
is = new ByteArrayInputStream(targetCertStr.getBytes());
|
||||
Certificate cert = cf.generateCertificate(is);
|
||||
is.close();
|
||||
chainList.add(cert);
|
||||
|
||||
is = new ByteArrayInputStream(certIssuerStr.getBytes());
|
||||
cert = cf.generateCertificate(is);
|
||||
is.close();
|
||||
chainList.add(cert);
|
||||
|
||||
is = new ByteArrayInputStream(caSignerStr.getBytes());
|
||||
cert = cf.generateCertificate(is);
|
||||
is.close();
|
||||
chainList.add(cert);
|
||||
|
||||
// create a certificate selector
|
||||
X509CertSelector xcs = new X509CertSelector();
|
||||
X509Certificate eeCert = (X509Certificate)chainList.get(0);
|
||||
xcs.setSubject(eeCert.getSubjectX500Principal());
|
||||
|
||||
// reverse build
|
||||
SunCertPathBuilderParameters params =
|
||||
new SunCertPathBuilderParameters(trustAnchors, xcs);
|
||||
params.setBuildForward(false);
|
||||
params.setRevocationEnabled(false);
|
||||
|
||||
CollectionCertStoreParameters ccsp =
|
||||
new CollectionCertStoreParameters(chainList);
|
||||
params.addCertStore(CertStore.getInstance("Collection", ccsp));
|
||||
|
||||
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
|
||||
CertPathBuilderResult res = cpb.build(params);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user