package org.openstack.atlas.util.ca.util;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.openstack.atlas.util.ca.primitives.RsaConst;
// Nieve chain builder. Experiments suggest its useless for production dont use
@Deprecated
public class X509Chainer {
static {
RsaConst.init();
}
private Set<X509Certificate> x509Certs;
public X509Chainer() {
x509Certs = new HashSet<X509Certificate>();
}
// Nieve O(n) based search.
public List<X509Certificate> getNextIssuer(X509Certificate subjectCert) {
List<X509Certificate> nextIssuer = new ArrayList<X509Certificate>();
for (X509Certificate candidateCrt : x509Certs) {
PublicKey candidateKey = (PublicKey) candidateCrt.getPublicKey();
try {
subjectCert.verify(candidateKey);
} catch (CertificateException ex) {
continue;
} catch (NoSuchAlgorithmException ex) {
continue;
} catch (InvalidKeyException ex) {
continue;
} catch (NoSuchProviderException ex) {
continue;
} catch (SignatureException ex) {
continue;
}
// Looks like we found a hit
nextIssuer.add(candidateCrt);
}
return nextIssuer;
}
// Nieve pathBuilder that only looks at the key for a matching signing key
// O(n*l) where l is the length of this chain and n is the number of certs in x509certs
public List<X509Certificate> buildPath(X509Certificate userCert) {
List<X509Certificate> pathOut = new ArrayList<X509Certificate>();
X509Chainer chainer = new X509Chainer();
chainer.getX509Certs().addAll(this.x509Certs);
List<X509Certificate> next = chainer.getNextIssuer(userCert);
if (next.isEmpty()) {
return pathOut;
}
while (next.size() > 0) {
X509Certificate nextX509 = next.get(0);
pathOut.add(nextX509);
chainer.getX509Certs().remove(nextX509); // We don't want to get stuck in a loop
next = chainer.getNextIssuer(nextX509);
}
return pathOut;
}
public Set<X509Certificate> getX509Certs() {
return x509Certs;
}
public void setX509Certs(Set<X509Certificate> x509Certs) {
this.x509Certs = x509Certs;
}
}