barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)
Показаны сообщения с ярлыком Java Security. Показать все сообщения
Показаны сообщения с ярлыком Java Security. Показать все сообщения

вторник, 4 декабря 2018 г.

КриптоПро JCP 2: ошибка ru.CryptoPro.JCP.tools.SelfTester.run SelfTester's test №16 failed

Проблема

Есть приложение, использующее КриптоПро JCP 2 для подписания XML. После развертывания на новом сервере при попытке подписания падает ошибка:
04-Dec-2018 18:21:54.093 WARNING [SelfTester] ru.CryptoPro.JCP.tools.SelfTester.run SelfTester's test №16 failed
 ru.CryptoPro.JCP.tools.SelfTesterException: Error during store working
at ru.CryptoPro.JCP.tools.SelfTests$TestDigestStore.run(Unknown Source)
at ru.CryptoPro.JCP.tools.SelfTester.b(Unknown Source)
at ru.CryptoPro.JCP.tools.SelfTester.a(Unknown Source)
at ru.CryptoPro.JCP.tools.SelfTester.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: ru.CryptoPro.JCP.tools.SelfTesterException: Error during store working
at ru.CryptoPro.JCP.tools.SelfTests.testDigestStore(Unknown Source)
... 5 more
Caused by: ru.CryptoPro.JCP.tools.CPVerify.CPVerifyException: Error during store working
at ru.CryptoPro.JCP.tools.CPVerify.DigestStoreDefault.<init>(Unknown Source)
... 6 more  
При последующих попытках падает:
SelfTester Error: some test crashed twice in a row, usage of JCP is no longer available
ru.CryptoPro.JCP.tools.SelfTesterException: SelfTester Error: some test crashed twice in a row, usage of JCP is no longer available
Причина

У пользователя, от имени которого работает приложение, не было прав на запись в директорию /var/opt/cprocsp/tmp. После выдачи прав стала падать ошибка "Permission denied" при попытке работы с какими-то файлами в этой папке, имена файлов начинаются с ".". У этих файлов владельцем был root, поэтому ошибка закономерна. После удаления этих файлов все заработало.

пятница, 25 ноября 2016 г.

Бесследное удаление КриптоПРО JCP 2.x

Под Windows:
  • Сносим JDK
  • Удаляем из реестра HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs\ru\/Crypto/Pro
Под Linux:
  • Сносим JDK
  • Удаляем /root/.java/
  • Удаляем /var/opt/cprocsp/
  • Если /usr/java/default не совпадает с только что снесенной JDK, то нужно удалить из нее .java/.systemPrefs/.ru (т.к. эта папка создается JCP почему-то именно в этой JDK, а не в той, куда ставится JCP)

среда, 9 сентября 2015 г.

JCP + ruToken: ошибка "java.io.IOException: Can't connect to Aktiv Co. ruToken 0"

Проблема

Используется JCP + ruToken для вычисления ЭЦП. При попытке получить ключ с токена падает ошибка:
Caused by: java.security.UnrecoverableKeyException: Can't connect to Aktiv Co. ruToken 0
at ru.CryptoPro.JCP.KeyStore.s.e(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.engineGetKey(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.JCPKeyStore.engineGetKey(Unknown Source)
at java.security.KeyStore.getKey(KeyStore.java:792)
...
Caused by: java.io.IOException: Can't connect to Aktiv Co. ruToken 0
at rtjlib.JCP.RutokenReader.lock(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.j.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.a(Unknown Source)
Решение

Текст ошибки не особо содержателен, и по нему совершенно неочевидно, в чем именно проблема. Из того же JCP-шного ControlPane я великолепно вижу Aktiv Co. ruToken 0, включая ключ и сертификат на нем.
Декомпилируем rtjlib.JCP.RutokenReader (rtjlib.jar в jre/lib/ext того JDK, который используется для подписывания). Там IOException с таким текстом кидается в 2 местах, и если в одном он кидается просто в коде после неудачного коннекта, то вот во втором применен замечательный подход "проглатывания исключения":
try
    {
      arrayOfByte = nativeWinJavaReader.getAtr(str, "T=0|T=1");
    }
    catch (Exception localException1)
    {
      throw new IOException("Can't connect to " + str);
    }
Добавляем в бросаемое исключение исходный localException1:
    try
    {
      arrayOfByte = nativeWinJavaReader.getAtr(str, "T=0|T=1");
    }
    catch (Exception localException1)
    {
      throw new IOException("Can't connect to " + str, localException1);
    }
Перекомпилируем класс RutokenReader, подкладываем в целевой JDK. Получаем более развернутую ошибку:
Caused by: java.io.IOException: Can't connect to Aktiv Co. ruToken 0
at rtjlib.JCP.RutokenReader.lock(RutokenReader.java:38)
at ru.CryptoPro.JCP.KeyStore.j.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.a(Unknown Source)
... 25 more
Caused by: java.lang.Exception: Establish context failed with 0x8010001d
at rtjlib.nativeAPI.SCardEstablishContext(Native Method)
at rtjlib.readerImpl.nativeWinJavaReader.getAtr(Unknown Source)
at rtjlib.JCP.RutokenReader.lock(RutokenReader.java:34)
... 28 more
Гуглим код 0x8010001d, узнаем, что расшифровывается он как "SCARD_E_NO_SERVICE - "The Smart card resource manager is not running." (http://blogs.msdn.com/b/alejacma/archive/2011/05/19/scardestablishcontext-fails-with-scard-e-no-service-error.aspx). Гугл же подсказывает и возможную причину: ошибка может быть вызвана нехваткой прав к событию "Global\Microsoft Smart Card Resource Manager Started". На это событие есть права только у интерактивных пользователей, SYSTEM и LOCAL SERVICE. В моем же случае ошибка падала в службе, запускающейся из-под обычного пользователя (но т.к. вход не интерактивный - прав не хватало). Запустили целевую программу в интерактивном режиме (из командной строки) вместо запуска в качестве службы - ошибка ушла. Пока такое решение устроило.

КриптоПРО JCP XMLDSig: java.lang.ClassCastException: content[0] is not a valid X509Data type

При попытки подписывания XML-документа с помощью КриптоПРО JCP падает ошибка:
java.lang.ClassCastException: content[0] is not a valid X509Data type
at ru.CryptoPro.JCPxml.dsig.internal.dom.DOMX509Data.<init>(DOMX509Data.java:68)
at ru.CryptoPro.JCPxml.dsig.internal.dom.DOMKeyInfoFactory.newX509Data(DOMKeyInfoFactory.java:88)
...
Причина - в моем случае был неверно указан keyAlias.

понедельник, 7 сентября 2015 г.

пятница, 28 августа 2015 г.

КриптоПРО JCP 1.0.54 и JDK 1.7.0_71: java.util.MissingResourceException: Can't find ru.CryptoPro.JCP.tools.resources.logger bundle

Проблема

Пытаюсь установить КриптоПРО JCP 1.0.54 на JDK 1.7.0_71, получаю ошибку:
...
Executing commands:
java.lang.ExceptionInInitializerError
        at ru.CryptoPro.JCP.Digest.GostDigest.reset(Unknown Source)
        at ru.CryptoPro.JCP.Digest.GostDigest.a(Unknown Source)
        at ru.CryptoPro.JCP.Digest.GostDigest.<init>(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.a(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.a(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.b(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.c(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.<init>(Unknown Source)
        at ru.CryptoPro.JCP.tools.License.<init>(Unknown Source)
        at ru.CryptoPro.JCP.Install.JCPInstaller.a(Unknown Source)
        at ru.CryptoPro.JCP.Install.JCPInstaller.parseArgs(Unknown Source)
        at ru.CryptoPro.Install.f.a(Unknown Source)
        at ru.CryptoPro.Install.ShellInstaller.h(Unknown Source)
        at ru.CryptoPro.Install.ShellInstaller.makeAction(Unknown Source)
        at ru.CryptoPro.Install.ShellInstaller.makeActionNoEx(Unknown Source)
        at ru.CryptoPro.Install.VariantTwo.main(Unknown Source)
Caused by: java.util.MissingResourceException: Can't find ru.CryptoPro.JCP.tools.resources.logger bundle
        at java.util.logging.Logger.setupResourceInfo(Logger.java:1537)
        at java.util.logging.Logger.<init>(Logger.java:267)
        at java.util.logging.Logger.<init>(Logger.java:261)
        at ru.CryptoPro.JCP.tools.JCPLogger.<init>(Unknown Source)
        at ru.CryptoPro.JCP.tools.JCPLogger.<clinit>(Unknown Source)
        ... 16 more
Install failed
---- Script ERROR
Решение

Установка сертифицированных версий JCP (последняя на данный момент - 1.0.54) возможна на версии JDK до 1.7.0_25, о чем и сказано на странице продукта в разделе "Системные требования". Причем, судя по всему, не включительно, т.к. на 25-ой наблюдается та же проблема. Установить удалось только на 1.7.0_21.
Т.е. либо даунгрэйдим JDK, либо отказываемся от сертифицированной версии в пользу несертифицированной.

четверг, 25 сентября 2014 г.

GUI-браузер для JKS-файлов

http://www.clearfield.com/key_store_browser/key_store_browser.html - вполне рабочая вещь, единственное что - импорт сертификатов все равно пришлось делать через keytool, т.к. эта утилита выдавала какую-то невнятную ошибку.

среда, 9 апреля 2014 г.

Wavemaker 6.5.3: аутентификация по Active Directory с использованием sAMAccountName

Проблема

Реализовать аутентификацию по Active Directory в приложении, построенном на Wavemaker 6.5.3, c использованием в качестве логина sAMAccountName.

Решение 

Через UI настройек безопасности поиск по sAMAccountName не организовать, т.к. там единственный вариант поиска пользователя - это userDnPattern:


Нам же нужно задать не шаблон для DN, а поиск по атрибуту sAMAccountName. Выход - идем Source -> Resources, в Folder Shortcuts выбираем "Project", там открываем файл WEB-INF/project-security.xml. В нем добавляем бин:
<bean id="userSearch"
       class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
   <constructor-arg index="0">
     <value>OU=Users</value>
   </constructor-arg>
   <constructor-arg index="1">
     <value>(sAMAccountName={0})</value>
   </constructor-arg>
   <constructor-arg index="2">
     <ref local="initialDirContextFactory"/>
   </constructor-arg>
   <property name="searchSubtree">
     <value>true</value>
   </property>
 </bean>
Первый аргумент конструктора нужно поправить в соответствие с базовым узлом для поиска по sAMAccountName. Базовый узел указывается относительно указанного в URL-е LDAP (в моем случае - относительно DC=my,DC=domain).
Далее необходимо исправить первый аргумент конструктора бина ldapAuthProvider с:
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg>
<ref local="initialDirContextFactory"/>
</constructor-arg>
<property name="userDnPatterns">
<list>
<value>cn={0},ou=Users</value>
</list>
</property>
</bean>
</constructor-arg>
на 
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg>
<ref local="initialDirContextFactory"/>
</constructor-arg>
<property name="userSearch">
<ref bean="userSearch"/>
</property>
</bean>
</constructor-arg>
Все, можно заходить в приложение по  sAMAccountName и паролю из AD.

PS Спасибо http://dev.wavemaker.com/forums/?q=node/7096

вторник, 4 сентября 2012 г.

jTrust: OnlineCrlRepository и прокси с авторизацией

Онлайн-репозиторий CRL из библиотеки jTrust реализует загрузку CRL-файлов по указанным URL`ам точек распространения сертификатов (CRL Distribution Points). Поддержка прокси в нем есть, и реализуется она передачей объекта NetworkConfig в конструктор класса:
import be.fedict.trust.NetworkConfig;
import be.fedict.trust.crl.OnlineCrlRepository;
// ...
NetworkConfig nwcfg = new NetworkConfig(proxyHost, proxyPort);
OnlineCrlRepository onlineCrlRepo = new OnlineCrlRepository(nwcfg); 
Но такой вариант работает только с прокси-серверами без авторизации.
В тоже время Apache HttpClient, используемый классом OnlineCrlRepository для загрузки файла CRL, авторизацию на прокси поддерживает (не уверен, что все возможные варианты авторизации реализованы, но по крайней мере BASIC есть): http://hc.apache.org/httpclient-3.x/authentication.html#Proxy_Authentication. Но т.к. внутренние поля и методы OnlineCrlRepository являются закрытыми, наследовать его для добавления нового функционала нет особого смысла, приходится копировать исходники в свой класс, добавляя возможность установки авторизации на прокси. 
Для этого я, во-первых, создал специальный класс ProxyCredentials, унаследовав be.fedict.trust.Credentials, предназначенный для хранения данных http-авторизации. Класс  be.fedict.trust.Credentials содержит метод init(), который применяет авторизационные данные к объекту HttpState. Этот метод я и переопределил таким образом, чтобы он задавал не данные авторизации на конечном сайте, а данные авторизации на прокси, заменив вызов httpState.setCredentials() на httpState.setProxyCredentials():
public class ProxyCredentials extends be.fedict.trust.Credentials
{
  @Override
  public void init(HttpState httpState) {
      for (Credential credential : this.getCredentials()) {
        AuthScope authScope = new AuthScope(credential.getHost(),
            credential.getPort(), credential.getRealm(),
            credential.getScheme());
        UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(
            credential.getUsername(), credential.getPassword());
        httpState.setProxyCredentials(authScope, usernamePasswordCredentials);
      }
    }
}
Теперь достаточно в нашем варианте класса OnlineCrlRepository добавить поле для хранения объекта ProxyCredentials, setter-метод для этого поля, а также добавить в метод getCrl() применение этих авторизационных данных к объекту HttpState:
public class AdvancedOnlineCrlRepository implements CrlRepository {

  // ..
  protected ProxyCredentials proxyCredentials;
  /**
   * Sets the credentials for proxy authentication
   * @param proxyCredentials
   */
  public void setProxyCredentials(ProxyCredentials proxyCredentials) {
    this.proxyCredentials = proxyCredentials;
  }

  // ..

protected X509CRL getCrl(URI crlUri) throws IOException,
CertificateException, CRLException, NoSuchProviderException,
NoSuchParserException, StreamParsingException {
HttpClient httpClient = new HttpClient();
if (null != this.networkConfig) {
httpClient.getHostConfiguration().setProxy(
this.networkConfig.getProxyHost(),
this.networkConfig.getProxyPort());
}
if (null != this.credentials) {
HttpState httpState = httpClient.getState();
this.credentials.init(httpState);
}
 
if (null != this.proxyCredentials) {
HttpState httpState = httpClient.getState();
this.proxyCredentials.init(httpState);
}
 
String downloadUrl = crlUri.toURL().toString();
//...
return crl;
}
}
Теперь создание объект репозитория CRL для работы с прокси-сервером с авторизацией выглядит так:
NetworkConfig nwcfg = new NetworkConfig(proxyHost, proxyPort);
ProxyCredentials creds = new ProxyCredentials();
Credential cred = new Credential(proxyHost, proxyPort, proxyLogin, proxyPassword);
creds.addCredential(cred);
AdvancedOnlineCrlRepository onlineCrlRepo = new AdvancedOnlineCrlRepository(nwcfg);
onlineCrlRepo.setProxyCredentials(creds);

понедельник, 23 июля 2012 г.

Получение thumbprint`а для X509Certificate в Java

Класс java.security.cert.X509Certificate не предоставляет соответствующего метода, поэтому приходится делать это вручную. Можно непосредственно, используя MessageDigest (http://stackoverflow.com/questions/1270703/how-to-retrieve-compute-an-x509-certificates-thumbprint-in-java), а можно воспользоваться классом DigestUtils из библиотеки commons-codec:
public static String getHexThumbprint(X509Certificate cert) throws CertificateEncodingException
{
return DigestUtils.shaHex(cert.getEncoded());  
}
public static byte[] getThumbprint(X509Certificate cert) throws NoSuchAlgorithmException, CertificateEncodingException
{
return DigestUtils.sha(cert.getEncoded());
}


пятница, 29 июня 2012 г.

java.lang.NoSuchMethodError: org.apache.xml.security.transforms.Transform.init()

Проблема:

В веб-приложении, использующем Apache xml-security, валятся исключения:
java.lang.NoSuchMethodError: org.apache.xml.security.transforms.Transform.init()

Решение:

В CLASSPATH лежит слишком поздняя версия xml-security (к примеру, 1.5.1), в которой этого метода уже нет. Необходимо заменить jar-ник на версию 1.4.5.

четверг, 5 апреля 2012 г.

java.security.NoSuchProviderException No such provider: BC при использовании библиотеки BouncyCastle

Проблема:

При выполнии проекта, использующего крипто-библиотеку BouncyCastle вываливается исключение:
java.security.NoSuchProviderException No such provider: BC
хотя все необходимые jar-ники подключены.

Решение:

Перед использованием криптопровайдера его необходимо зарегистрировать в окружении безопасности программно:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
 или с помощью policy-файла:
security.provider.<n>=org.bouncycastle.jce.provider.BouncyCastleProvider