2012-10-17 36 views
12

我想在Java中加载MSCAPI keystore并检查MY商店中的可用证书。然而,这些证书的一些密钥驻留在硬件令牌上,弹出窗口会在加载期间请求令牌。加载MSCAPI Java Keystore时不加载私钥(硬件令牌)

有没有办法推迟加载Windows密钥库时加载私钥?这最终通过驱动器(也由令牌制造商提供通信,以令牌 - 由USB令牌制造商提供的DLL -

keyStore = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 
keystore.load(null,null); 
+0

这个问题没有得到emsworth的很多关注,也许可以在Oracle论坛上提问(链接到这个问题)。 –

回答

7

弹出正在从MS-CAPI加密服务提供商(CSP)激活)。 KeyStore只是打电话,两者之间的层次只是通过它;令牌上的固件是一个抛出了认证弹出并维持会话状态等

关键的Java DLL是sunmscapi.dll它具有执行:

// Use CertEnumCertificatesInStore to get the certificates 
// from the open store. pCertContext must be reset to 
// NULL to retrieve the first certificate in the store. 
while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext)) 
{ 
    // Check if private key available - client authentication certificate 
    // must have private key available. 
    HCRYPTPROV hCryptProv = NULL; 
    DWORD dwKeySpec = 0; 
    HCRYPTKEY hUserKey = NULL; 
    BOOL bCallerFreeProv = FALSE; 
    BOOL bHasNoPrivateKey = FALSE; 
    DWORD dwPublicKeyLength = 0; 

    if (::CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL, 
              &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE) 
    { 
     bHasNoPrivateKey = TRUE; 

    } else { 
     // Private key is available 

    BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); 

    // Skip certificate if cannot find private key 
    if (bGetUserKey == FALSE) 
    { 
     if (bCallerFreeProv) 
      ::CryptReleaseContext(hCryptProv, NULL); 

     continue; 
    } 
    .... 

正如你可以看到它总是检查一个私钥。您将不得不修改此代码并创建sunmscapi.dll的自定义版本以避免此问题或以其他方式击败此检查。

+0

我很害怕这种情况。我最终需要与硬件令牌接口,所以我最终使用smartcardio直接与当前插入终端的令牌进行通信。 Java Windows truststore尝试加载先前插入计算机的令牌的私钥,这对我来说是不可接受的。 – emsworth

+0

好奇心...用智能卡我能够加载密钥库而不用提示使用这个令牌:keyStore = KeyStore.getInstance(“Windows-MY”); keystore.load(NULL,NULL);我想这取决于软件供应商。 – jBilbo