Skip to content

Commit

Permalink
Improved certificate chain detection (issue #421)
Browse files Browse the repository at this point in the history
Algorithm now also checks the signature, making it more precise, but
this comes with two disadvantages:
1. It is slower than before, this is mitigated by keeping the
verification operations as low as possible
2. If the certificate should contain an unsupported signature algorithm
then the keystore content cannot be displayed anymore
  • Loading branch information
kaikramer committed Sep 1, 2023
1 parent ac08ea8 commit 89da822
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 13 deletions.
31 changes: 27 additions & 4 deletions kse/src/org/kse/crypto/x509/X509CertUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -327,22 +327,45 @@ public static X509Certificate[] orderX509CertChain(X509Certificate[] certs) {
}

private static X509Certificate findIssuedCert(X509Certificate issuerCert, X509Certificate[] certs) {
// Find a certificate issued by the supplied certificate based on distiguished name
// Find a certificate issued by the supplied certificate
for (X509Certificate cert : certs) {
if (issuerCert.getSubjectX500Principal().equals(cert.getSubjectX500Principal()) &&
issuerCert.getIssuerX500Principal().equals(cert.getIssuerX500Principal())) {
issuerCert.getIssuerX500Principal().equals(cert.getIssuerX500Principal()) &&
issuerCert.getSerialNumber().equals(cert.getSerialNumber())) {
// Checked certificate is issuer - ignore it
continue;
}

if (issuerCert.getSubjectX500Principal().equals(cert.getIssuerX500Principal())) {
if (isIssuedBy(cert, issuerCert)) {
return cert;
}
}

return null;
}

/**
* Checks if certificate was issued by the other certificate by checking first the DN and only if the issuer DN
* matches the subject DN, then the signature is verified. This avoids the slow verification operation when it is
* impossible that the second certificate has signed the first one.
*
* @param cert The issued certificate
* @param issuerCert The possible issuer certificate
* @return True, if issuerCert has issued cert, false otherwise
*/
public static boolean isIssuedBy(X509Certificate cert, X509Certificate issuerCert) {
if (issuerCert.getSubjectX500Principal().equals(cert.getIssuerX500Principal())) {
// possible candidate found, now check if signature matches the issuer key
try {
if (verifyCertificate(cert, issuerCert)) {
return true;
}
} catch (CryptoException e) {
// wrong certificate, continue
}
}
return false;
}

/**
* X.509 encode a certificate.
*
Expand Down
14 changes: 5 additions & 9 deletions kse/src/org/kse/gui/dialogs/DViewCertificate.java
Original file line number Diff line number Diff line change
Expand Up @@ -442,19 +442,15 @@ private DefaultMutableTreeNode createCertificateNodes(X509Certificate[] certs) {
}

private DefaultMutableTreeNode findIssuer(X509Certificate cert, DefaultMutableTreeNode node) {
// Matches on certificate's distinguished name

// If certificate is self-signed then finding an issuer is irrelevant
if (cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal())) {
return null;
}

Object nodeObj = node.getUserObject();

if (nodeObj instanceof X509Certificate) {
X509Certificate nodeCert = (X509Certificate) nodeObj;
if (node.getUserObject() instanceof X509Certificate) {
X509Certificate possibleIssuerCert = (X509Certificate) node.getUserObject();

if (cert.getIssuerX500Principal().equals(nodeCert.getSubjectX500Principal())) {
if (X509CertUtil.isIssuedBy(cert, possibleIssuerCert)) {
return node;
}
}
Expand All @@ -478,8 +474,8 @@ private boolean isIssuerInSet(X509Certificate cert, Set<X509Certificate> certSet
return false;
}

for (X509Certificate certToTest : certSet) {
if (cert.getIssuerX500Principal().equals(certToTest.getSubjectX500Principal())) {
for (X509Certificate possibleIssuer : certSet) {
if (X509CertUtil.isIssuedBy(cert, possibleIssuer)) {
return true;
}
}
Expand Down

0 comments on commit 89da822

Please sign in to comment.