0

我正在构建一个加密 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) 作为别名。这样,它会获得两个具有相同别名的此类条目。现在,每当我想获得整个证书对象时,我都必须传递别名,所以每当我传递别名时,它总是会给我第一个证书,而我无法访问具有相同别名的第二个证书。

澄清一下,如果我有两个以“Kuntal Shah”名义的证书和一个以“Abhishek Desai”名义的证书。然后当我这样做时,别名枚举将具有“Kuntal Shah”“Kuntal Shah”“Abhishek Desai”

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。

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

4

2 回答 2

0

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

于 2012-06-14T00:12:04.553 回答
0

这个解决方案比我的另一个更难看,但它可能真的有效。您可以使用反射来直接访问所有密钥和证书条目的集合。

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);
}
于 2012-06-14T01:59:25.510 回答