Здравствуйте! У меня ошибка при попытке достать приватный ключ с КазТокена.
java.security.UnrecoverableKeyException: kz.gov.pki.kalkan.exception.KalkanException [INVALID_PIN_VALUE]
Пароль правильный, это подтверждает проверка с помощью вашей тестовой странички, то есть с помощью самого NCALayer, а не модуля, и если запустить модуль в среде эклипс. Но если модуль загрузить в NCALayer, то появляется ошибка. Сертификат и token alias с токена экспортируется удачно.
Может быть вы предоставите пример, как надо работать с токеном, в частности получить приватный ключ ?
Код, который это делает
private PrivateKey userPrivateKey;
private X509Certificate userCertificate;
private KeyStore tstore;
/**
* Возвращает список алиасов и сертификатов Перед вызовом этого метода
* необходимо вызвать {@link #load(String, char[])}.
*
* @param algorithm
* алгоритм
* @return доступные алиасы и сертификаты
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
*/
public Map<String, X509Certificate> getCertificates(String algorithm)
throws KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException {
Map<String, X509Certificate> certs = new HashMap<String, X509Certificate>();
for (Enumeration<String> en = tstore.aliases(); en.hasMoreElements();) {
String al = en.nextElement();
X509Certificate cert = getCertificate(al);
if (cert != null) {
System.out.println("token alias: " + al + "; cert: "
+ cert.getSubjectDN() + "; cert alg: "
+ cert.getPublicKey().getAlgorithm());
if ((cert.getPublicKey().getAlgorithm()
.startsWith(algorithm))) {
try {
cert.checkValidity();
certs.put(al, cert);
} catch (CertificateExpiredException e) {
e.printStackTrace();
} catch (CertificateNotYetValidException e) {
e.printStackTrace();
}
}
}
}
return certs;
}
/**
* Возвращает сертификат из устройства для указанного алиаса
*
* @param alias
* алиас, для которого нужно получить сертификат
* @return
* @throws KeyStoreException
*/
public X509Certificate getCertificate(String alias) throws KeyStoreException {
return (X509Certificate) tstore.getCertificate(alias);
}
/**
* Возвращает список всех подключенных устройств Казтокен.
*
* @return
* @throws CardException
*/
public List<String> getTokenList() throws CardException {
TerminalFactory factory = TerminalFactory.getDefault();
List<String> tokens = new ArrayList<String>();
List<CardTerminal> lReaders = factory.terminals().list();
for (CardTerminal terminal : lReaders) {
System.out.println("found terminal: " + terminal.getName() + "; isPresent: " + terminal.isCardPresent());
if (terminal.isCardPresent()) {
tokens.add(terminal.getName());
}
}
return tokens;
}
/**
* Метод подгружает указанный токен с указанным пролем. Необходимо вызывать
* данный метод перед вызовом методов {@link #getCertificates()} или
* {@link #getKey(String)}.
*
* @param tokenName
* название токена
* @param password
* пароль от указанного токена
* @throws NoSuchAlgorithmException
* @throws CertificateException
* @throws IOException
* @throws KeyStoreException
* @throws NoSuchProviderException
*/
public void load(String tokenName, char[] password) throws NoSuchAlgorithmException, CertificateException,
IOException, KeyStoreException, NoSuchProviderException {
if (tstore == null)
tstore = KeyStore.getInstance("AKKaztokenStore", KalkanProvider.PROVIDER_NAME);
tstore.load(Streams.fromString(tokenName), password);
}
/**
* Возвращает закрытый ключ из устройства для указанного алиаса
*
* @param alias
* алиас, для которого нужно получить закрытый ключ
* @return
* @throws UnrecoverableKeyException
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
*/
public Key getKey(String alias) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException {
return tstore.getKey(alias, null);
}
@Override
public void start(BundleContext context) throws Exception {
char[] password = "ХХХХХХ".toCharArray();
try {
List<String> tokenListName = getTokenList();
load(tokenListName.get(0), password);
Map<String, X509Certificate> rsaCerts = getCertificates("RSA");
String alias = rsaCerts.keySet().iterator().next();
logService.log(LogService.LOG_DEBUG, "Extracting certificate from token...");
userCertificate = rsaCerts.get(alias);
logService.log(LogService.LOG_DEBUG, "Certificate extracted");
logService.log(LogService.LOG_DEBUG, "Extracting private key from token...");
userPrivateKey = (PrivateKey) getKey(alias);
logService.log(LogService.LOG_DEBUG, "Private key extracted");
} catch (Exception e) {
logService.log(LogService.LOG_DEBUG, "exception", e);
}
}
P.S Проблему решил. Странно, если запускать локально, то в AKKaztokenStore.engineGetKey(String alias, char password[]), в качестве пароля можно передать null и отработает удачно (ключ приватный достанется). А если это же делать в подгруженном модуле, то уже нет. Странно именно то, почему локально так можно делать.