如何使用Java从Windows上的智能卡(MSCAPI)获取用户身份?
我想通过Sun的MSCAPIProvider从Windows上的Java胖客户端的智能卡(PKI)获取用户身份。我们的目标是:如何使用Java从Windows上的智能卡(MSCAPI)获取用户身份?
- 用户打开应用程序
- 提示卡
- 提示输入PIN
- 我得到的X509Certicate在Java中
- 授予访问权限,等等
我已找到基于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()));
现在我面临两个问题:
- 我不知道他的别名可能是什么(鸡蛋的问题)
- 怎么办我强制使用X509Cert进行PIN授权,并通过HTTPS建立SSL上下文?
哪些是缺失的位?
对于Windows的情况,通常智能卡供应商提供两个驱动程序。
- 之一来访问和使用所述PKCS11协议智能卡登入。
- 其他一个访问和使用Windows加密服务提供商签署(又名CSP)
当您使用SunMSCAPI
提供商可以访问本地用户窗口密钥库,如果没有安装一些CSP智能卡驱动程序在上面;你也可以通过它看到智能卡证书(但是你不知道本地和智能卡之间的区别,因为Windows密钥库充当接口)。
如果您尝试访问智能卡的公开证书,但是sunMSCAPI您正在访问公钥,因此不需要引入PIN。但是,如果您尝试执行签名,那么Windows密钥库将操作委托给智能卡CSP,这将提示您输入密码。
现在要回答你的两个具体问题:
- 我不知道他的别名可能是(鸡蛋的问题)
一种选择可能是在弹出窗口中打印所有证书(例如主题或序列号)的信息(保持别名和您显示的描述之间的关系),让用户选择要使用的证书,然后在内部可以使用别名来引用所选 证书;这就像任何https
验证在需要客户端验证时一样工作;浏览器向您显示可能的证书以进行身份验证。
在https
你可以做一些过滤器中的服务器,只显示与某些条件匹配哪些证书(例如,你可以过滤一些标准证书Apache的;对于发行的特定CA的例子证明),但最终用户必须选择所需的一个来执行验证。
你也可以做一些类似的过滤器,例如从keystore获取证书属性或证书链,只显示你认为适合哪些请求者......但最后如果在你过滤后有多个已经让用户决定选择哪一个。
- 如何强制PIN授权与X509Cert与 虽然建立一个HTTPS的SSL上下文的结果?
如果通过sunMSCAPI供应商我认为你可以不关心PIN委托私钥访问操作的智能卡CSP,让CSP照顾它适合你。
如果由于某种原因,你需要保持PIN那么一个可能的选择是使用不同的供应商(SunPKCS11
)直接实例化的智能卡(不通过CSP),并使用CallbackHandler
(如@Maarten Bodewes建议在评论中)照顾它。然而,恕我直言,如果在这种情况下所有的客户端都在Windows上,我建议您像使用sunMSCAPI
一样避免使用不同的智能卡驱动程序实现PKCS11问题。
您是否试图通过请求存储中的所有密钥来过滤掉别名?您是否尝试添加[CallbackHandler](http://docs.oracle.com/javase/7/docs/api/javax/security/auth/callback/CallbackHandler.html)? – 2013-03-06 00:29:16
1.'PrivateKey entry =(PrivateKey)store.getKey(alias,null);'在一个循环中。用卡片钥匙不打印。当我放入卡时,钥匙被列出。下次运行时卸下卡让我问。在任何时候我都被要求输入我的个人识别码。 2. CallbackHandler如何帮助我,1.不知道别名,2.想使用MS智能卡提供程序而不是自定义对话框? – 2013-03-06 08:40:18
您可以使用'aliases()'和'isKeyEntry()'从KeyStore请求所有密钥别名,也许这将有助于检索密钥?至于CallbackHandler,如果您获得PIN提示可能取决于智能卡附带的软件的实施。我没有看到任何需要使用提供者的密钥提示的要求(并且我个人不希望在应用程序之外提供PIN提示 - 我想知道我使用的密钥是什么,但这是个人偏好)。 – 2013-03-07 19:58:33