我正在开发一个使用证书令牌签署文档的java代码。到目前为止,一切都很好,但我想抑制“输入引脚”对话框,因为我存储用户的引脚,所以他/她不需要每次都输入它。这里的真正问题是此代码将以批处理模式运行(无用户交互)。我知道一旦键入,键可能在内存中,因此不需要在短时间内再次键入。但我不能依赖它,我需要提供密码。这是我到目前为止的代码(它只是一个样本,它可能不完整也不起作用):
protected KeyStore loadKeyStoreFromSmartCard() {
keyStore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
keyStore.load(null, null);
return keyStore;
}
public void signDocument(byte[] conteudoParaAssinar, String certAlias) {
char[] pass = (char[]) null;
PrivateKey key = (PrivateKey) loadKeyStoreFromSmartCard.getKey(certAlias, pass);
Certificate[] chain = loadKeyStoreFromSmartCard(true).getCertificateChain(certAlias);
CertStore certsAndCRLs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(chain)), "BC");
X509Certificate cert = (X509Certificate) chain[0];
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addSigner(key, cert, CMSSignedDataGenerator.DIGEST_SHA1);
gen.addCertificatesAndCRLs(certsAndCRLs);
CMSProcessable data = new CMSProcessableByteArray(conteudoParaAssinar);
CMSSignedData signed = gen.generate(data, true, "SunMSCAPI");
byte[] envHex = signed.getEncoded();
}
修改
我听说CryptSetProvParam
PP_KEYEXCHANGE_PIN
女巫可能是解决方案,但我不知道如何从java中调用它。我找到的所有例子都是针对.net。
答案 0 :(得分:3)
我实现了类似于此的一次,但不幸的是智能卡驱动程序有问题,因此驱动程序试图提出驱动程序本身有时实现的原生PIN回调。但是我们假设你的司机在那方面做得更好。
首先,您需要实现CallbackHandler,文档概述了该概念。在你的情况下,这是PasswordCallback案件有趣处理。
接下来,按如下所示创建KeyStore
(省略异常处理)
Provider provider = Security.getProvider("SunMSCAPI");
CallbackHandler cbh = // your implementation
KeyStore.ProtectionParameter protection = new KeyStore.CallbackHandlerProtection(cbh);
//get a handle of the CAPI KeyStore as before
KeyStore.Builder keystoreBuilder = KeyStore.Builder.newInstance("Windows-MY",
provider,
protection);
KeyStore store = keystoreBuilder.getKeyStore();
然后,要访问私钥,请执行以下操作:
KeyStore.Entry ke = store.getEntry(alias, null);
if (!(ke instanceof KeyStore.PrivateKeyEntry))
throw new RuntimeException("The entry is not a private key.");
PrivateKey key = ((KeyStore.PrivateKeyEntry) ke).getPrivateKey();
提供商会自动生成相应的PasswordCallback
以发送给您的CallbackHandler
。处理回调时,您只需传递缓存的密码即可。
毋庸置疑,密码缓存通常不受欢迎;)
答案 1 :(得分:0)
MS CryptoAPI未提供指定PIN的统一方式。您唯一的选择是在可能的情况下从CyrptoAPI切换到PKCS#11 - PKCS#11要求您在代码中“登录”设备并在代码中提供PIN。
更新:某些硬件供应商提供的某些 CSP(加密服务提供商)模块允许您调用特殊的CryptoAPI函数(CSPSetProvParam,http://msdn.microsoft.com/en-us/library/aa379858%28v=VS.85%29.aspx)并将PIN传递给它。如果硬件的CSP支持这种设置PIN的方法,那么您需要联系供应商以获取信息,如果确实如此,确切的参数ID是什么等。