diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index ddca9f860b..3eaf55059a 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -438,29 +438,24 @@ public Certificate engineGetCertificate( public String engineGetCertificateAlias( Certificate cert) { - Enumeration c = certs.elements(); - Enumeration k = certs.keys(); - - while (c.hasMoreElements()) + // look the certificate up by alias rather than advancing keys() and elements() in + // lockstep - IgnoresCaseHashtable.keys() enumerates a copy of the table while + // elements() enumerates the original, so the two orders are not required to agree. + for (Enumeration k = certs.keys(); k.hasMoreElements();) { - Certificate tc = (Certificate)c.nextElement(); String ta = (String)k.nextElement(); - if (tc.equals(cert)) + if (cert.equals(certs.get(ta))) { return ta; } } - c = keyCerts.elements(); - k = keyCerts.keys(); - - while (c.hasMoreElements()) + for (Enumeration k = keyCerts.keys(); k.hasMoreElements();) { - Certificate tc = (Certificate)c.nextElement(); String ta = (String)k.nextElement(); - if (tc.equals(cert)) + if (cert.equals(keyCerts.get(ta))) { return ta; } diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java index f463a2e63f..620f7b7a70 100644 --- a/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java +++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/PKCS12StoreTest.java @@ -2417,6 +2417,46 @@ private void testChainCycle() keyStore.getEntry("cycle", new KeyStore.PasswordProtection("test".toCharArray())); } + private void testGetCertificateAlias() + throws Exception + { + KeyStore keyStore = KeyStore.getInstance("PKCS12", BC); + + keyStore.load(null, null); + + // enough entries that the backing table has grown past its initial capacity: a copy of + // the table is sized from its entry count instead, so the two end up with different + // bucket layouts and any order-dependent pairing of keys() with elements() diverges. + KeyPair keyPair = TestUtils.generateRSAKeyPair(); + int certCount = 12; + + X509Certificate[] certs = new X509Certificate[certCount]; + String[] aliases = new String[certCount]; + + for (int i = 0; i != certCount; i++) + { + aliases[i] = "cert-" + i; + certs[i] = TestUtils.createSelfSignedCert("CN=Test Certificate " + i, "SHA256withRSA", keyPair); + + keyStore.setCertificateEntry(aliases[i], certs[i]); + } + + for (int i = 0; i != certCount; i++) + { + String alias = keyStore.getCertificateAlias(certs[i]); + + if (!aliases[i].equals(alias)) + { + fail("getCertificateAlias returned wrong alias: expected " + aliases[i] + ", got " + alias); + } + } + + if (keyStore.getCertificateAlias(TestUtils.createSelfSignedCert("CN=Absent", "SHA256withRSA", keyPair)) != null) + { + fail("getCertificateAlias returned an alias for a certificate that is not in the store"); + } + } + private void testOrphanedCertCleanup() throws Exception { @@ -2798,6 +2838,7 @@ public void performTest() testPKCS12Store(); testGOSTStore(); testChainCycle(); + testGetCertificateAlias(); testBCFKSLoad(); testCertsOnly(); testJKS();