Загрузка MSCAPI Java Keystore без загрузки личных ключей (жесткий токен)
Я хотел бы загрузить MSCAPI keystore
в Java и проверьте доступные сертификаты в магазине MY. Однако некоторые ключи для этих сертификатов находятся на аппаратных токенах, и во время загрузки всплывающее окно запрашивает токен.
Есть ли способ отложить загрузку закрытых ключей при загрузке хранилища ключей Windows?
keyStore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
keystore.load(null,null);
2 ответа
Всплывающее окно активируется из MS-CAPI Cryptographic Service Provider (CSP) - библиотеки DLL, поставляемой производителем USB-токена, - которая в итоге обменивается данными с токеном через драйвер (также предоставленный производителем токена). KeyStore просто выполняет вызов, а промежуточные слои просто пропускают его; микропрограмма на токене выдает всплывающее окно аутентификации и поддерживает состояние сеанса и т. д.
Ключевой Java-файл является 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, чтобы избежать этого или иным образом отменить эту проверку.
Эта проблема была решена в JDK 9.