如何使用 Java 从 Windows (MSCAPI) 上的智能卡获取用户身份?

Posted

技术标签:

【中文标题】如何使用 Java 从 Windows (MSCAPI) 上的智能卡获取用户身份?【英文标题】:How to obtain a user's identity from a smartcard on Windows (MSCAPI) with Java? 【发布时间】:2013-03-05 10:05:50 【问题描述】:

我想使用 Sun 的 MSCAPIProvider 从 Windows 上的 Java 胖客户端的智能卡 (PKI) 获取用户的身份。目标是:

    用户打开应用 提示卡 提示输入 PIN 码 我得到了 Java 中的 X509Certicate 授予访问权限等

我根据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()));

现在我面临两个问题:

    我不知道他的别名可能是什么(chicken-egg-problem) 如何使用 X509Cert 强制 PIN 授权,从而通过 HTTPS 建立 SSL 上下文?

缺少哪些位?

【问题讨论】:

您是否尝试过从商店请求所有密钥来过滤掉别名?您是否尝试过添加CallbackHandler? 1. PrivateKey entry = (PrivateKey) store.getKey(alias, null); 在一个循环中。使用卡,钥匙不打印。当我把卡放进去时,钥匙就列出来了。下次运行时移除卡让我要求它。任何时候都不会要求我输入我的 PIN 码。 2. 当我 1. 不知道别名,2. 想要使用 MS 智能卡提供程序而不是自定义对话框时,CallbackHandler 将如何帮助我? 您可以使用aliases()isKeyEntry() 从KeyStore 请求所有密钥别名,也许这将有助于检索密钥?至于CallbackHandler,是否得到PIN提示可能取决于智能卡附带的软件的实现。我没有看到您要使用提供商的密钥提示的任何要求(我个人不希望在应用程序之外出现 PIN 提示 - 我想知道我使用密钥的目的,但这是个人喜好)。跨度> 但这真的是一个通过枚举交互的解决方案吗? 嗯,从逻辑上讲,如果您无法注册某种类型的侦听器来获得回叫,那么您可以做的就是轮询(如果轮询结果不准确,则检索更多信息)够了)。 【参考方案1】:

对于 Windows 情况,通常智能卡供应商提供两个驱动程序。

使用 PKCS11 协议访问和使用智能卡签名。 另一个使用 Windows 加密服务提供程序(又名 CSP)访问和签名

当您使用SunMSCAPI 提供程序时,您可以访问本地用户windows 密钥库以及是否安装了一些CSP 智能卡驱动程序;您还可以通过它查看智能卡证书(但您无法知道本地和智能卡证书之间的区别,因为 Windows 密钥库充当接口)。

如果您尝试通过 sunMSCAPI 访问智能卡的公共证书,则您访问的是公共密钥,因此无需引入 PIN。但是,如果您尝试执行签名,则 Windows 密钥库会将操作委托给智能卡 CSP,这将提示您输入 PIN

现在尝试回答您的两个具体问题:

    我不知道他的别名可能是什么(chicken-egg-problem)

一个选项可以是在弹出窗口中打印所有证书(例如主题或序列号)的信息(保持别名和您显示的描述之间的关系),让用户选择要使用的证书,然后在内部选择您可以使用别名来引用所选证书;这就像任何https 身份验证在需要客户端身份验证时起作用;浏览器向您显示可能的证书进行身份验证。

https 中,您可以在服务器中创建一些过滤器以仅显示符合某些条件的证书(例如,您可以从某些条件过滤证书;例如为特定 CA 颁发的证书),但最终用户必须选择所需的进行身份验证。

您还可以执行某种过滤器,例如从密钥库获取证书属性或证书链,并仅显示您认为符合要求的那些...但最后,如果您在过滤器之后有多个ve 让用户决定要选择哪一个。

    如何使用 X509Cert 强制 PIN 授权 通过 HTTPS 建立 SSL 上下文?

如果您通过 sunMSCAPI 提供商将私钥访问操作委托给智能卡CSP,我认为您可以不关心 PIN em>,让 CSP 为您处理。

如果由于某种原因您需要保留 PIN,那么一个可能的选择是使用不同的提供商 (SunPKCS11) 直接实例化智能卡(而不是通过 CSP)并使用CallbackHandler(正如@Maarten Bodewes 在cmets 中建议的那样)来处理它。但是恕我直言,如果在这种情况下所有客户端都在 Windows 上,我建议您使用 sunMSCAPI,以避免来自某些不同智能卡的不同 PKCS11 驱动程序实现出现问题。

【讨论】:

以上是关于如何使用 Java 从 Windows (MSCAPI) 上的智能卡获取用户身份?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Kafka (Java) 应用程序从 Windows 连接到 Linux 中的 Confluent

如何从 Windows 上的 Java 控制台应用程序确定当前活动的代码页?

我可以从 Java EE webapp 使用 Windows 身份验证连接到 SQL Server 吗?

如何使用 Windows 登录进行单点登录和桌面 Java 应用程序的 Active Directory 条目?

如何在带有 NetBeans 的 Windows Java 项目中使用 HDF5

java文件从Windows里拖到Vmware的CentOS系统里中文乱码,如图。是啥原因?如何解决?