在JAVA中加载Internet Explorer密钥库时出现问题

在JAVA中加载Internet Explorer密钥库时出现问题,java,security,internet-explorer,x509certificate,pki,Java,Security,Internet Explorer,X509certificate,Pki,我正在构建一个加密web应用程序,它允许用户在浏览器的客户端进行签名和加密。应用程序必须与IE和Firefox兼容。它在IE的Firefox中运行得非常好,我面临一个问题 最近,印度政府开始向个人发放两份数字证书,一份用于签署数据,另一份用于加密。这些证书具有相同的CN。我使用下面的代码循环通过证书 public static Certificate selectedCert = null; KeyStore keystore1 ; keystore1 = KeyStore.getInstanc

我正在构建一个加密web应用程序,它允许用户在浏览器的客户端进行签名和加密。应用程序必须与IE和Firefox兼容。它在IE的Firefox中运行得非常好,我面临一个问题

最近,印度政府开始向个人发放两份数字证书,一份用于签署数据,另一份用于加密。这些证书具有相同的CN。我使用下面的代码循环通过证书

public static Certificate selectedCert = null;
KeyStore keystore1 ;
keystore1 = KeyStore.getInstance("Windows-MY");
keystore1.load(null, null);
if (keystore1 != null) {
    enumeration = keystore1.aliases();
    while (enumeration.hasMoreElements()) {
    alias = enumeration.nextElement();
    selectedCert = keystore1.getCertificate(alias));
            System.out.println(selectedCert.getPublicKey());    
    }
}
从firefox密钥库读取证书时,别名由firefox生成,这是唯一的,但在IE中,它从IE获取证书,并将通用名(CN)作为别名。这样,它将获得两个别名相同的条目。现在,每当我想要获得整个证书对象时,我必须传递alias,因此每当我传递alias时,它总是给我第一个证书,而我无法访问具有相同别名的第二个证书

为了进一步澄清,如果我有两张“Kuntal Shah”和一张“Abhishek Desai”的证书。 然后别名枚举将具有 “Kuntal Shah” “Kuntal Shah” “阿披实·德赛” 当我这样做的时候

selectedCert = keystore1.getCertificate(alias));
它总是把第一个给我,而我永远也得不到第二个

我在C#中尝试了一些代码,在那里我有一个更简单的解决方案

X509Store storeMy = new X509Store(StoreName.My,StoreLocation.CurrentUser);
storeMy.Open(OpenFlags.ReadOnly);
Console.WriteLine("Found certs with the following subject " +"names in the {0} store:", storeMy.Name);
foreach (X509Certificate2 cert in storeMy.Certificates)
{
    Console.WriteLine("\t{0}", cert.SubjectName.Name);
}
但这在firefox上不起作用,在Linux上也不起作用


有人能告诉我如何访问第二个证书吗?或者还有其他不同的方法吗?

我不喜欢这个解决方案,但也许您可以调用deleteEntry。加载所需别名并检查证书是否为所需别名。如果没有,请删除它。然后再次尝试加载它。也许你可以这样读。请确保不要调用KeyStore.store。您不想删除IE中的证书。

此解决方案比我的另一个解决方案更难看,但它实际上可能有效。您可以使用反射直接访问所有密钥和证书项的集合

public void printKeystore() {
    Field spiField = KeyStore.class.getDeclaredField("keyStoreSpi");
    spiField.setAccessible(true);
    KeyStoreSpi spi = (KeyStoreSpi) spiField.get(keystore1);
    Field entriesField = spi.getClass().getSuperclass().getDeclaredField("entries");
    entriesField.setAccessible(true);
    Collection entries = (Collection) entriesField.get(spi);
    for (Object entry : entries) {
        String alias = (String) invokeGetter(entry, "getAlias");
        Key privateKey = (Key) invokeGetter(entry, "getPrivateKey");
        X509Certificate[] certificateChain = (X509Certificate[]) invokeGetter(entry, "getCertificateChain");
        System.out.println(alias + ": " + privateKey + Arrays.toString(certificateChain));
    }
}

private Object invokeGetter(Object instance, String methodName)
        throws NoSuchMethodException, IllegalAccessException,
        InvocationTargetException {
    Method getAlias = instance.getClass().getDeclaredMethod(methodName);
    getAlias.setAccessible(true);
    return getAlias.invoke(instance);
}

谢谢@GregKopff,我会照解释的做。我也试过同样的方法。问题是,如果不使用alias,我无法将IE密钥库复制到其他任何地方,如果使用alias,我将无法将第二个证书复制到任何其他密钥库。在不复制的情况下,它会从浏览器中删除证书。我认为这似乎正在向前推进。我们现在正在迭代条目。条目的类型为sun.security.mscapi.KeyStore$KeyEntry。我们无法强制转换它的对象,因为它在mscapi包外不可见。任何进一步的帮助都将不胜感激。您只需要做一些反思,如上面更新的示例所示。