我想通过使用Sun的MSCAPIProvider从Windows上的Java客户端获得智能卡(PKI)的用户身份。目标是:
我发现了基于this堆栈溢出问题的示例,它列出了我商店中的所有证书,并且我能够用Microsoft提供者PIN提示符签名一些字节。
这是我的密码:
Provider provider = Security.getProvider("SunMSCAPI");
KeyStore store = KeyStore.getInstance("Windows-MY", provider);
store.load(null, null);
System.out.println(store);
Enumeration<?> aliases = store.aliases();
while(aliases.hasMoreElements()) {
String alias = aliases.nextElement().toString();
Certificate[] signerKey = (Certificate[]) store.getCertificateChain(alias);
Object entry = store.getKey(alias, null);
System.out.println(alias + " " + Arrays.toString(signerKey));
System.out.println(entry);
}
Signature sig = Signature.getInstance("SHA1withRSA",provider);
PrivateKey key = (PrivateKey) store.getKey("Michael-O", null);
sig.initSign(key);
sig.update("Test".getBytes());
System.out.println(Arrays.toString(sig.sign()));现在我面临两个问题:
哪些是缺失的部分?
发布于 2016-09-26 12:24:37
对于Windows情况,通常智能卡供应商提供两个驱动程序。
当您使用SunMSCAPI提供程序时,您可以访问本地用户窗口密钥存储库,如果它上安装了一些CSP智能卡驱动程序;您还可以通过它看到智能卡证书(但您无法知道本地和智能卡证书之间的区别,因为windows密钥存储库充当接口)。
如果您试图通过sunMSCAPI访问智能卡的公共证书,则您正在访问一个公钥,因此不需要引入PIN。但是,如果您尝试执行签名,则windows密钥库将此操作委托给智能卡CSP,这将提示您输入PIN。
现在试着回答你的两个具体问题:
一个选项可以是在弹出窗口中打印来自所有证书(例如主题或序列号)的信息(保持别名与所显示的描述之间的关系),让用户选择要使用的证书,然后在内部您可以使用别名来引用所选证书;这就像任何https身份验证需要客户端身份验证时的工作一样;浏览器向您显示可能使用的证书。
在https中,您可以在服务器中设置一些筛选器,只显示与某些条件匹配的证书(例如,apache可以从某些标准筛选证书;例如,为特定CA颁发的证书),但最终用户必须选择所需的证书来执行身份验证。
您还可以进行某种筛选,例如从keystore获取证书属性或证书链,并只显示您认为适合请求者的.但是最后,如果筛选器后面有多个过滤器,则必须让用户决定要选择哪一个。
如果您通过sunMSCAPI提供程序将私钥访问操作委托给智能卡CSP,我认为您可以不关心PIN,让CSP来照顾您。
如果出于某种原因需要保留PIN,那么一个可能的选项是使用不同的提供者(SunPKCS11)直接实例化智能卡(而不是通过CSP),并使用CallbackHandler (正如@Maarten在注释中建议的那样)来处理它。但是,如果在这种情况下,所有客户端都在Windows上,我建议您像使用sunMSCAPI一样使用PKCS11,以避免不同智能卡的不同PKCS11驱动程序实现出现问题。
https://stackoverflow.com/questions/15220976
复制相似问题