Эта статья посвящена тому, как перестать использовать Крипто Про и перейти на Bouncy Castle в девелоперском/тестовом окружении.
В начале статьи будет больше про СМЭВ и его клиент, в конце — больше про конвертирование ключей с готовой копипастой, чтобы можно было начать прямо сейчас.


Картинка для привлечения внимания:


image

И сразу же ответ:


image

Disclamer


Конечно, сбежать с Крипто Про невозможно, потому что это оплот российской криптографии. Он удовлетовряет требованиям компетентных органов, он прописан в договоры и контраты, ему доверяет вся страна, и так далее. Поэтому все нижеописанное относится девелоперскому или тестовому окружению, где мы сами себе хозяева.


Недавно мне нужно было разобраться, как написать сервис, работающий с Системой Межведомственного Электронного Взаимодействия.
Все написанное представляет собой просто результат небольшого исследования, максимально абстрагированный от выполненной работы. И даже приблизительно угадать что-то о реально принятых решениях невозможно, я проверял.


Обоснование нужности готового клиента


На технологическом портале СМЭВ3 лежат исходники клиента, но вот незадача — они гвоздями прибиты к КриптоПро. Вордовский файл с инструкцией, приложенный к исходникам, утверждает это самым прямым образом. Да и все равно, исходные ключи у нас тоже в формате КриптоПро. Исходя из production это нормально, а вот для тестового окружения жутко неудобно. Хотелось бы от этого избавиться.


На сайте есть две версии — "актуальная" и "рекомендуемая". Почему они так, и почему актуальная версия не рекомендуется, а рекомендуемая не актуальна — какая-то дилемма копирайтера :) Дальше речь о том клиенте который "актуальный".


Строго говоря, использовать его нельзя, потому что в архиве исходников нету текста лицензии, и поэтому непонятно, под какой лицензией должна распространяться производная работа. Я позвонил по телефону поддержки, написанному на портале, написал на почту, пару недель наблюдал как моя заявка летает между уровнями техподдержки и исполняющими организациями, и в результате воз и ныне там:


image


Задача не выполнена, но выполнена и закрыта, изумительно. Ладно, черт с ними...


Несмотря на невозможность использовать его у себя непосредственно в коде, это отличный тестовый пример. Дело в том, что в методических рекомендациях СМЭВа без поллитры не разобраться, и готовый живой код дает отличный буст к пониманию.


Основная претензия к документации — это канцеляризмы и скудное описание в интернете.
Помните мем про копирайтера, который из абзаца сделал одно предложение в несколько слов? Для документации СМЭВа это имеет место быть, например вот цепочка рефакторинов для одной произовльно взятой фразы:


"2. ИС потребителя направляет в СМЭВ межведомственный запрос;"
"2. ИС потребителя направляет в СМЭВ запрос;"
"2. ИС потребителя направляет запрос;"
"2. потребитель направляет запрос;"
"2. запрос потребителя;"


Короче, наличие готовой реализации — это добро.


Почему Крипто Про JCP добро


  • Он есть и работает
  • Судя по исходникам BoncyCastle, товарищи из КриптоПро поучаствовали в его развитии, добавив алгоритмы по ГОСТ

Почему Крипто Про JCP зло


  • Если у вас много разработчиков и виртуальных машин, покупать лицензию не очень хочется
  • Проприетарщина, поэтому все описанные ниже баги исправить нельзя. Точнее можно (дизассемблер стреляет без промаха), но незаконно и с потерей всех гарантий — не вариант
  • На Java 8 под OSX завести не удалось (никакую версию КП JCP). Скорей всего это исправят довольно скоро, т.к. представители отреагировали на мой пост в Фейсбуке
  • Вообще, на OSX завести не удалось. Гуй админки — полурабочий, сыпет ошибками, куски гуя не работают.
  • На линуксе тоже есть баги в интерфейсе
  • Когда-то давно установщик на Windows писал в консоли крокозябры (не проверял на новых версиях — может, пофиксили)
  • Установка патчингом дистрибутива джавы. Ящетаю, что установка софта методом патчинга джавы — это зло в последней инстанции, за это суд по правам человека должен назначать шестикратный расстрел с повешанием
  • Не каждую джаву можно пропатчить, для выяснения магической комбинации нужно серьезно упороться. Тут важно, что мы стараемся разрабатывать на самых новых версиях джавы, с пылу-с жару, и тестируем на новых версия (на момент написания статьи — JDK9), так что ограничения на версию джавы — это безумие как оно есть
  • Способы инсталляции и запуска админки — лютый треш (это надо видеть)

В качестве альтернативы в тестовом окружении я предалагю использовать Bouncy Castle с контейнером PKCS12 или JKS. Это открытое, свободное и бесплатное ПО.
К чести разработчиков Крипто Про, похоже, они принимали участие в его разработке.


Что нужно допилить в готовом клиенте, чтобы сбежать с Крипто Про


Код написан довольно дружелюбно для расширения, поэтому можно просто взять за основу класс KeyStoreWrapperJCP, и аналогично написать KeyStoreWrapperBouncyCastlePKCS12, KeyStoreWrapperBouncyCastleJKS.


Переписать DigitalSignatureFactory, так, чтобы он на вход начал принимать путь до криптоконтейнера на файловой системе и пароль от него (для КриптоПро это просто не нужно). Там есть свич, который проверяет тип криптопровайдера, в него надо дописать дополнительно два кейса, для имен типа BOUNCY_JKS и BOUNCY_PKCS12 и навешать использование соответсвующих KeyWrapper и вызов initXmlSec.


В initXmlSec нужно дописать
1) возможность принимать вообще любой провайдер, а не только криптопро (это просто удобно)
2) Security.addProvider(new BouncyCastleProvider());
3) для XMLDSIG_SIGN_METHOD сделать свич: если КриптоПро, то алгоритм называется "GOST3411withGOST3410EL", а если BouncyCastle алгоритм называется "GOST3411WITHECGOST3410".


Ну вроде как и все. Если бы была известна лицензия на этот смэв-клиент, я бы приложил конкретный код под Apache License 2, а так это просто список идей.


Инициализация XML-подписи в Santuario


Ах да, тут есть один интересный момент. В сети множество советов, касающихся СМЭВа, заключающихся в ручном парсинге кусков XMLек, и прочим закатом солнца вручную, но это не наш метод (и не метод, который использовали создатели клиента)


Замес в том, что сгенерить самоподписанные ключи по госту легко (копипаста на SO ищется за секунды). А вот подписать — нет, ибо по мнению интернет-школьников якобы Bouncycastle не поддерживает xml-подпись. Конкретней, при работе с Apache Santuario, XMLSignature из santuario-xmlsec не понимает что использовать для обработки метода "xmldsig-more#gostr34102001-gostr3411" при вызове xmlSignature.sign(privateKey).


Отдельная хохма в том, что IntelliJ IDEA Community глючит при попытке отдебажить xmlsec, бросая step in отладчика в неверное место верных исходников. Я попробовал все разумные версии Идеи, поэтому понимать как это работает надо вслепую, написуя тактические письма в Спортлото. Это не в укор Идее, не существует идеальных инструментов, просто фактор повлиявший на скорость понимания вопроса.


Чтобы это заработало, нужно:


1) Заимплементить реализацию SignatureAlgorithmSpi из Apache Santuario. В GetEngineUri вернуть строку: "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411" (или что там у вас). Это ключевая магия. Совершенно ничего умного этот класс делать не должен.


Инициализация раз за всю жизнь приложения (н-р в синглтон-бине спринга):


2) Загрузить провайдер, чтобы не патчить JDK:


Security.addProvider(new BouncyCastleProvider());

3) Впердолить в рантайм только что написанный класс:


String algorithmClassName = "fully qualified name класса реализующего SignatureAlgorithmSpi";
Class.forName(algorithmClassName);
SignatureAlgorithm.providerInit();
SignatureAlgorithm.register("http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411", algorithmClassName);

4) Достучаться до маппингов алгоритмов JCE:


String ns = "http://www.xmlsecurity.org/NS/#configuration";
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rootElement = document.createElementNS(ns, "JCEAlgorithmMappings");
Element algorithms = document.createElementNS(ns, "Algorithms");

5) Замапить метод на алгоритм:


Element aElem = document.createElementNS(NameSpace, "Algorithm");
aElem.setAttribute("URI", "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411");
aElem.setAttribute("Description", "GOST R 34102001 Digital Signature Algorithm with GOST R 3411 Digest");
aElem.setAttribute("AlgorithmClass", "Signature");
aElem.setAttribute("RequirementLevel", "OPTIONAL");
aElem.setAttribute("JCEName", "GOST3411WITHECGOST3410");
algorithms.appendChild(aElem);

6) Применить маппинги:


org.apache.xml.security.Init.init();
JCEMapper.init(rootElement);

6) PROFIT!
После этого XMLSignature резко начинает понимать этот метод, и начнет делать xmlSignature.sign.


Подготовка OpenSSL для работы с ГОСТ


Если у вас в начале статьи на стене висит OpenSSL, когда-нибудь он точно выстрелит.
Так что да, это важный момент, необходимый для осуществления дальнейшего текста.


  • Так как у нас Крипто Про, и на Маке оно не взлетает, нам понадобится виртуальная машина с Windows (можно даже Windows XP), и установленной Криптой
  • Установить как можно более актуальную версию OpenSSL (так, чтобы в ней уже была поддержка ГОСТ):
    https://wiki.openssl.org/index.php/Binaries
    https://slproweb.com/products/Win32OpenSSL.html
  • Проверить, что в установленной версии есть файл gost.dll
  • В установленном OpenSSL найти файл openssl.cfg
  • В самое начало файла добавить строчку:
    openssl_conf = openssl_def
  • В самый конец файла добавить строчки:


    [openssl_def]
    engines = engine_section
    
    [engine_section]
    gost = gost_section
    
    [gost_section]
    engine_id = gost
    dynamic_path = ./gost.dll
    default_algorithms = ALL
    CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet

  • PROFIT

Как мы можем попросить Крипто Про отдать ключи (на самом деле, нет)


Если у нас уже есть настоящие (не самоподписанные) ключи, то совершенно некисло было бы проверить их в действии. Да, мы говорим о тестовых целях, но таки доверяй — но проверяй!


Если поставить винду в виртуальную машину, накатить туда Крипто Про, установить ключи и попробовать их экспортировать, то обнаруживаем удивительную вещь: в экспортере не работает экспорт в PKCS12, а все остальные направления в экспортере заблокированы (англ. "grayed out").


Гуглю ошибку, и что же мы видим на официальном форуме?
https://www.cryptopro.ru/forum2/default.aspx?g=posts&t=2425


"От Алексея Писинина был получен ответ:
Добрый день. PKCS12 не соответствует требованиям безопасности ФСБ в части хранения закрытых ключей. В теории, закрытые ключи должны храниться на так называемых "съемных" носителях. Собственно, по этой причине и не работает экспорт."


Я правильно это читаю как, что у них гуй для экспорта есть, но бизнес-логики к нему нету?!
Ппоэтому каких галочек ни нащелкай — всегда будет выпадать ошибка на последнем шаге гуевого мастера?!


Какой же стыд.


Dear God,
Please kill them all.
Love, Greg.


image


Как мы можем грубо заставить Крипто Про отдать ключи


Можно очень долго мучиться, пытаясь засучив C++ вычитать ключ из контейнера с помощью OpenSSL и такой-то матери. Я честно пытался, и разбился об задачу как корабль об скалы (по крайней мере, это задачка больше чем на 1 день для человека, который давно таким не занимался). На просторе интернетов мы не единственные, кто разбился об те же скалы: http://gigamir.net/techno/pub903517


Вот тут наступает момент "это радость со слезами на глазах". Некая контора под названием Лисси Софт, всего за 2 тыщи рублей отдает нам гениальную утилиту P12FromGostCSP. Ее создатели таки победили ту проблему, которую не осилило сообщество, и она выдирает ключи в PFX. Радость — потому что она работает.


Со слезами — потому что это проприетарщина, и она фиг знает как работает.
На картинке Ричард Столлман как бы удивляется и спрашивает: "неужели вы боретесь с проприетарщиной с помощью другой проприетарщины?"


image


Так что целиком инструкция по перегону ключей выглядит как-то так:


  • Все действия производить на Windows (подойдет виртуальная машина) с установленным Крипто Про CSP;
  • Подготовить OpenSSL с ГОСТом по инструкции (есть в этой статье).
  • Купить P12FromGostCSP. Поплакать.
  • Установить исходный ключ в КриптоПро (это заслуживает отдельной инструкции, но она гуглится).
  • Запустить P12FromGostCSP (перед этим спрятать икону Ричарда Столлмана под стол, чтобы он не проклял тебя за запуск проприетарщины)
  • Выбрать установленный сертификат, указать пароль сертификата КриптоПро
  • Указать произвольный новый пароль (парольную фразу) для ключевой пары PFX
  • Указать местоположение для сохранения файла. Файл лучше именовать в формате p12.pfx (это название по-умолчанию, лучше не трогать — говорят, есть баги, если переименовать)
  • Получить pem файл:
    openssl pkcs12 -in p12.pfx -out private.key.pem -name "alias"
  • (-name "alias" — эта опция поменяет имя ключа внутри контейнера. Это нужно потому, что P12FromGostCSP именует ключи как попало (на самом деле, по порядку, цифрами), без сохранения исходного алиаса.
  • Получить pkcs12 файл:
    openssl pkcs12 -export -out private.key.pkcs12 -in private.key.pem -name "alias"
  • Готово

Тестовые самоподписанные ключи


Так как мы деламем все это в тестовых целях, теперь мы подходим к кульминации и начинаем сами себе выдавать ключи.


Как выдать ключи в формате Крипто Про, я особо не заморачивался, потому что это просто не нужно в рамках текущей задачи. Но на всякий случай, существует сервис выдачи таких ключей: http://www.cryptopro.ru/certsrv/


  • Все действия производить на Windows (подойдет виртуальная машина) с установленным Крипто Про CSP;
  • Открыть сайт и перейти к выдаче ключа;
  • Нужно выбрать пункт "Сформировать ключи и отправить запрос на сертификат" и нажать кнопку "Дальше";
  • Щелкнуть по ссылке "Создать и выдать запрос к этому ЦС";
  • Заполнить необходимые поля;
  • Нажат кнопку "Выдать";
  • Установить сертификат.

Выдача контейнера JKS


Этот вопрос широко представлен в интернете, поэтому можно сразу смотреть Stackoverflow:
http://stackoverflow.com/questions/14580340/generate-gost-34-10-2001-keypair-and-save-it-to-some-keystore


Идея в том, что раз уж мы все равно используем Bouncy Castle, то им же можем и сгенерить ключ.
Этот код не самый идеальный, но дает реально работающую реализацию (на практике у меня в результате получилось несколько объемных классов, чтобы сделать удобный интерфейс)


Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider() );

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( "ECGOST3410", "BC" );
keyPairGenerator.initialize( new ECGenParameterSpec( "GostR3410-2001-CryptoPro-A" ) );
KeyPair keyPair = keyPairGenerator.generateKeyPair();

org.bouncycastle.asn1.x500.X500Name subject = new org.bouncycastle.asn1.x500.X500Name( "CN=Me" );
org.bouncycastle.asn1.x500.X500Name issuer = subject; // self-signed
BigInteger serial = BigInteger.ONE; // serial number for self-signed does not matter a lot
Date notBefore = new Date();
Date notAfter = new Date( notBefore.getTime() + TimeUnit.DAYS.toMillis( 365 ) );

org.bouncycastle.cert.X509v3CertificateBuilder certificateBuilder = new org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder(
        issuer, serial,
        notBefore, notAfter,
        subject, keyPair.getPublic()
);
org.bouncycastle.cert.X509CertificateHolder certificateHolder = certificateBuilder.build(
        new org.bouncycastle.operator.jcajce.JcaContentSignerBuilder( "GOST3411withECGOST3410" )
                .build( keyPair.getPrivate() )
);
org.bouncycastle.cert.jcajce.JcaX509CertificateConverter certificateConverter = new org.bouncycastle.cert.jcajce.JcaX509CertificateConverter();
X509Certificate certificate = certificateConverter.getCertificate( certificateHolder );

KeyStore keyStore = KeyStore.getInstance( "JKS" );
keyStore.load( null, null ); // initialize new keystore
keyStore.setEntry(
        "alias",
        new KeyStore.PrivateKeyEntry(
                keyPair.getPrivate(),
                new Certificate[] { certificate }
        ),
        new KeyStore.PasswordProtection( "entryPassword".toCharArray() )
);
keyStore.store( new FileOutputStream( "test.jks" ), "keystorePassword".toCharArray()

Выдача контейнера PKCS12


В принципе, это не особо нужно, потому что у нас уже есть простой и удобный способ выдавать JKS, а JKS для Java это самое что ни на есть родное решение. Но для полноты картины, пусть будет.


  • Подготовить OpenSSL с ГОСТом по инструкции (есть в этой статье).
  • Сделать Cerificate Signing Request + приватный ключ (вписать нужные данные о ключе!):
    openssl req -newkey gost2001 -pkeyopt paramset:A -passout pass:aofvlgzm -subj "/C=RU/ST=Moscow/L=Moscow/O=foo_bar/OU=foo_bar/CN=developer/emailAddress=olegchiruhin@gmail.com" -keyout private.key.pem -out csr.csr
  • Подписать приватным ключом (на Windows эту операцию нужно делать с правами Administrator, иначе свалится с ошибкой "unable to write 'random state'"):
    openssl x509 -req -days 365 -in csr.csr -signkey private.key.pem -out crt.crt
  • Получить публичный ключ:
    openssl x509 -inform pem -in crt.crt -pubkey -noout > public.key.pem
  • GOST2001-md_gost94 hex (если надо):
    openssl.exe dgst -hex -sign private.key.pem message.xml 
  • MIME application/x-pkcs7-signature (если надо):
    openssl smime -sign -inkey private.key.pem -signer crt.crt -in message.xml
  • Превратить pem в pkcs12:
    openssl pkcs12 -export -out private.key.pkcs12 -in private.key.pem -name "alias" 

Резюме


В результате всех вышеописанных действий мы получили относительно легий способ избавиться от тяжкой ноши Крипто Про.


В дальнейшем хотелось бы продолжить борьбу за выпил до финальной победы: оформить все утилиты, генераторы ключей, самописные смэв-клиенты итп в виде одного репозитория на Гитхабе. Еще, очень хотелось бы получить права на модификацию и распространение под пермиссивной лицензией официального клиента СМЭВ. Тогда половина этой статьи была бы просто не нужна, и проблема решалась бы скачиванием нужного кода с Гитхаба.

Комментарии (45)


  1. gotch
    22.04.2016 14:29
    +2

    А вот эта статья никак не поможет сэкономить 2000 на извлечении ключа?
    https://habrahabr.ru/post/276057/


    1. olegchir
      22.04.2016 14:42

      Вполне возможно. Отличный совет! Когда/если найду время, чтобы своими руками проверить статью — обновлю пост.


    1. fmb
      22.04.2016 15:35

      Разве Крипто-про не позволяет скопировать контейнер закрытого ключа?


      1. olegchir
        22.04.2016 15:36

        есть в тексте. Ctrl+F в браузере, «Как мы можем попросить Крипто Про отдать ключи (на самом деле, нет)»


        1. archimed7592
          23.04.2016 17:03

          Вы что-то делаете не так. Приведенная ссылка на форум — 6 летней давности. Сейчас ключи прекрасно экспортируются в PFX и импортируются обратно. Я сам очень давно (лет 5-6 назад) сталкивался с проблемой невозможности экспорта в PFX, однако, относительно недавно обнаружил, что это работает — изучая пример, идущий с КриптоПро.NET SDK (как раз про SMEV), обнаружил там в каталоге Certificates примеры ключей в PFX и в readme.txt написано что эти PFX устанавливаются штатными средствами системы. Проверил на своих сертификатах — действительно, всё работает.


          1. olegchir
            25.04.2016 10:15

            Тем не менее, закрытый ключ не экспортируется сейчас, в 2016 году. Это факт.

            Импорта не проверял — цель ведь сбежать с крипты, а не прибежать в неё.


            1. archimed7592
              25.04.2016 14:23

              Закрытый ключ прекрасно экспортируется. Это факт. Экспортировал в 2016 году. Специализированного софта для этого не устанавливал — только КриптоПро 3.9 КС1


              1. olegchir
                25.04.2016 15:19
                +1

                Ну то есть иногда экспортируется, иногда — нет. Какой-то баг, наверное. Как всегда :)

                Если уж на то пошло, то на Linux через админку КриптоПро JCP нету вообще никаких опций экспорта кроме одной — «Экспорт» без описания. Оно экспортит в неназванный формат без расширения имени файла, который содержит в себе только открытый ключ. А на OSX даже эта админка либо не запускается, либо сыпет багами. А если захочешь установить ключи, устанавливать их надо копированием в магическую директорию, путь который ищется на форуме, и из интефрейса админки JCP это не делается. Думаю, если тут «кто-то делает не так», искать надо начинать не с меня, а например, с самой Крипты.


  1. Visphord
    22.04.2016 14:49
    +2

    Простите за «глупость» но для экспорта всех ключей из системы разве нельзя использовать известный mimikatz? он еще и с открытыми исходниками.


    1. olegchir
      22.04.2016 15:12

      Мне он (mimikatz) неизвестен. Спасибо за подсказку.


  1. Lelik13a
    22.04.2016 15:03
    +2

    Да, избавиться от Крипто-Про и сотоварищей довольно насущная задача. Сейчас как раз с коллегой решаем задачу взаимодействия с http://dom.gosuslugi.ru, которые не навязчиво рекомендуют единственное решение.
    Половина уже решена средствами openssl + обёртка на питоне и есть надежда на полный успех. Сильно не хватает нормальных интерфейсов работы с openssl на питоне, с поддержкой дополнительных движков криптопровайдеров. Тот же pyopenssl не умеет пока. Но, надеюсь, в будущем ситуация улучшится, благо все возможности есть.


  1. imbasoft
    22.04.2016 15:45
    +2

    Избавиться от Крипто-Про в тестовых целях конечно можно, но на проде у вас могут следующие грабли:
    1. Поддержка ключевых носителей eToken, Соболь, и т.д.
    2. Поддержка параметров алгоритмов.
    3. Работа с аппаратными генераторами случайных чисел.
    4. Экзотические грабли, но тем не менее — переход на новые шифры «Кузнечик», «Стрибог» и т.д. не факт что в Bounty Castle оперативна появится их поддержка.

    Хотя если делать замену КП на BC как черного ящика, то есть нечто что шифрует, то такой способ имеет место быть.


  1. Alexins
    22.04.2016 15:47
    +2

    Не в качестве рекламы, а в качестве учебника по работе с надфилем XML-Security Java and MS CryptoIAPI for CXF WS-Security signature. Меня умиляют эти слова о Apache Santuario и код работы с DOM деревом. Apache Santuario — это для XML SAX разбора. Для DOM дерева используется JSR105.
    Да, проект опубликован давно, но отнюдь не означает, что он не работает. Там идут JUnit тесты и работаю. Заметьте, работают под Linux и под Windows.

    Зачем сражаться с контейнерами закрытых ключей? Покупка КриптоПро CSP по цене соизмерима со стоимостью некой утилиты. И не факт, что она сможет извлечь ключи с аналогов eToken.
    Посмотрите на недавно сертифицированную CSP 4.0. Там есть куча компонентов с полюбившимся OpenSSL.


    1. olegchir
      22.04.2016 15:59

      кстати, код работы с DOM-деревом по сути не мой — это расширение того, что уже написано в официальном СМЭВ-клиенте. Описанная в статье копипаста — малоинтрузивный патч. Меньше строчек поменяешь — проще будет поддерживать, патчить обновления клиента. В джавадоке по методу, о котром идет речь, есть комментарий на тему, что автор кода не разобрался, почему весь этот текст нужно писать, но без него не работает, поэтому он просто оставит это здесь :)


      1. Alexins
        22.04.2016 16:38

        Я предлагаю всё же разобраться в том, что написано другим человеком.

        На самом деле, я хочу вам показать пример реализации с Apache CXF. Здесь нет надобности вообще каким-то образом обрабатывать XML документ. JAXB и JaxWS делают много вещей для вас. Вы используете обычные классы. Далее, поднимаем SOAP клиента на основе WSDL и вкладываем в качестве параметра нужный Java класс.
        Вся работа с криптографией, прописывание подписей в XML, извлечение и проверка подписей, это удел Apache CXF. Ваш код должен быть «мягким и пушистым», а не вызывать сложные рефлексы.

        Самое основное понимание XML подписи — не надо стремится сохранить текстовое представление документа. В подписи указывается алгоритм нормализации. Он убирает все отступы и упорядочивает названия атрибутов в тегах. Полученная каша, в кодировке UTF-8 поступает в хеш функцию. Значение функции находится в разделе digest. Подпись собирает все эти дайджесты вместе и уже подписывает.

        Я извиняюсь, если не совсем доходчиво объясняю.


        1. olegchir
          25.04.2016 23:23

          Вы доходчиво объяснете, самые ценные комменты в теме


    1. olegchir
      22.04.2016 16:08

      Покупка КриптоПро CSP по цене соизмерима со стоимостью

      «Лицензия на право использования СКЗИ „
      КриптоПро JCP“ версии 2.0 на одном
      сервере с одним ядром процессора (или с 2 ядрами с отключенным Hyper
      Threading)»

      https://www.cryptopro.ru/sites/default/files/docs/price.pdf

      То есть, если я, в тестовых целях, энсиблом пачкой зафигачу свою софтину в сотню-другую докеров, на покупку лицензий мне придется продать на черном рынке машину, кваритру, собаку, жену, и все свои внутренние органы?

      > соизмерима со стоимостью некой утилиты

      если когда-нибудь у меня случится отпуск, таки напишу эту утилиту прямо на гитхаб, и это будет стоить вообще ничего никому


      1. Alexins
        22.04.2016 16:47

        Вы пишете клиента или вы пишете сервер?
        Обратите внимание на этот вопрос. Клиенты могут воспринимать вашу систему как сервер. Но ваша система может являться промежуточным звеном на этапе передачи данных во внешнюю систему. Другими словами, вы выступаете инициатором передачи сообщения — вы клиент. Это главное понимание.
        Если же ваша система является получателем, вы выступаете в качестве сервера — стоите и слушаете, когда кто-то к вам подключится.
        Точно так же в установке TLS соединения. Ваш browser выступает в роли клиента и ему не нужна серверная лицензия на КриптоПро CSP.
        То же самое происходит и с лицензированием КриптоПро JCP/JCSP и JTLS. Для Клиентского ПО, JTLS бесплатно — так утверждают сами сотрудники КриптоПро. JCP так же идет по лицензии клиента.


        1. olegchir
          22.04.2016 18:25

          Смэв — это шина. По шине бегают сообщения. Сервисы обрабатывают входящие сообщения и на основании этого забрасывают в шину собственные сообщения. Сообщения — это XMLки, подписанные по госту. Так что сервисы — это автономные полностью автоматические серверы, никаких браузеров и прочих веб-интерфейсов там нет.


          1. Alexins
            22.04.2016 20:52

            Вы считаете, что ваше ПО выступает в качестве автономных сервисов. Поймите, что слово сервис — это клиент шины. Сервер — это средство хранения и обмена в вашей шине. По аналогии, это SMTP/POP сервера электронной почты. У вас всего лишь почтовый клиент.
            То же самое в MQ или JMS. Есть один или несколько серверов, на которые поступают сообщения и они передают их клиентам. Клиент может публиковать сообщения, может забирать корреспонденцию. Но при этом, он остается для шины клиентом.
            С точки зрения, вы делаете клиента. Сервер у вас пассивный.

            В рамках Java программ, мы создаем сокеты. Для понимания, о чем я говорю, можно посмотреть статью Создаем клиент-сервер на сокетах.
            Если вы создаете ServerSocket, это сервер. Если создаете Socket, это клиент.

            Теперь представим такую ситуацию. У нас есть SOAP сообщение от клиента. Он подписывает сообщение и отправляет на сервер. Сервер отправляет ответ. Если ответ сервера должен быть подписан, ему нужна серверная лицензия.

            Еще раз повторю, что сервис в шине — это клиент.
            Он спрашивает у сервера наличие сообщений и получает сообщения в ответ. То что ваш сервис, это клиент, понятно?
            После получения ответа, ваше ПО отключается от сервера и может не спеша подготовить ответ на полученное сообщение. После этого, ваш сервис подключается к серверу обмена и передает туда свое сообщение для отправителя исходного сообщения. Получает ответ от сервера, что он получил сообщение. То что ваш сервис — это клиент, понятно?
            В чем же главное отличие сервера от клиента? Сервер не может самостоятельно установить соединение с клиентом. А вот, клиент может установить соединение с сервером.

            Вам хватит клиентской лицензии на средства криптографии.


            1. olegchir
              22.04.2016 22:12

              Ответы тоже должны быть подписаны


        1. archimed7592
          23.04.2016 17:13

          Про CSP вы совершенно правы. Про КП JCP — не уверен. Я Java не использую, но КП.NET совершенно точно лицензируется по используемой операционной системе и не важно, что использование КП.NET ограничивается клиентскими нуждами. Благо, для КП.NET лицензирование не по ядрам :).


  1. imbasoft
    22.04.2016 17:35
    +1

    Коллеги, разрешите вступлюсь за КриптоПРО.
    Клиентская лицензия для КП CSP (без возможности формирования ЭП + только клиентский TLS) — бесплатна.
    Кому надо можете запросить соответствующее письмо у них в офисе.


    1. olegchir
      22.04.2016 18:27

      задача вот такая. Мне поможет клиентская лицензия?


      1. imbasoft
        22.04.2016 20:09

        Если ваши сервисы только проверяют электронную подпись то да.


        1. Alexins
          22.04.2016 21:02

          Скажу крамольную истину. Если вам надо только проверять подписи и не заниматься подписыванием сообщений, вы можете использовать КриптоПро JCP и не платить. Да, это не честно, но работает.


        1. olegchir
          22.04.2016 22:13

          Сервисы в основном подписывают исходящие. Входящие можно проверить, но необязательно.


  1. dartraiden
    22.04.2016 19:01
    +1

    >> Некая контора под названием Лисси Софт
    >> Со слезами — потому что это проприетарщина, и она фиг знает как работает.

    Эти «Лисси» умудрились даже исходники Firefox и Thunderbird спиратить. Оправдываются тем, что «У микрософта исходники тоже закрыты».


    1. olegchir
      25.04.2016 23:16

      А зачем им тырить Firefox и Thunderbird? В чем профит? Вот же они, в инторнете лежат.


      1. dartraiden
        25.04.2016 23:49

        Под «стырили» я подразумевал то, что они взяли исходники, сделали на их основе версии с поддержкой российского крипто, но эти производные продукты внезапно стали проприетарные. Хотя, по лицензии, под которой они брали сорцы (Firefox и Thunderbird распространяются на условиях GNU GPL) — Лисси обязаны предоставлять исходный код своих изменений по первому же запросу пользователей.


        1. olegchir
          26.04.2016 15:30

          А что сказали в суде?


          1. dartraiden
            26.04.2016 15:35
            +1

            Понятия не имею, мне, к счастью, не так нужны эти бинарные блобы, чтобы за них судиться.
            Что, впрочем, не отменяет того факта, что «Лисси» поступает, мягко говоря, нехорошо. С linux.org.ru их за это уже шуганули после попыток пиарить там свои поделия.
            Вдобавок, возникает интересный каламбур — они предлагают довериться российской криптографии, но для этого, зачем-то, надо доверится сначала самой «Лисси».


            1. olegchir
              26.04.2016 16:38

              Да, я и репортил модераторам лора просьбу удалить их пиар, вспомнил теперь :)


              1. dartraiden
                26.04.2016 16:53
                +1

                Но вы подали мне идею с судом — сообщил в Mozilla о нарушении лицензии. У них на сайте есть для этого форма. В конце-концов, это их права нарушены, им и судиться, если оно им надо.


  1. Mingun
    22.04.2016 20:03
    +2

    И после этого еще кто-то смеет жаловаться на проблемы безопасности! Да если для того, чтобы вся эта криптография хоть как-то заработала, нужно гуглить днями и вставлять спагетти непонятно как и почему работающего кода — неудивительно, что статьи об уязвимостях просто прут пачками.


    Асимметричная криптография в основе своей проста, как два пальца, почему же ее использование сопряжено с такими трудностями? Где внятные мануалы? Примеры кода? Вот, например, у меня как раз стоит задача прочитать приходящий PKCS#7 сертификат (в виде массива байт) и проверить подписи в нем, так даже для такой элементарной задачи (если не пользоваться классом PCKS7 из пакета sun.*) нужно наворотить такую кучу кода, что волосы дыбом встают. Причем у всех кода разный и у меня впечатление, что никто не знает, как же это делать правильно. Во всяком случае, понимания того, что происходит, я ни в одном из ответов на stackoverflow не вижу. О генерации ответа в таком же формате (отдать свой подписанный публичный ключ) я пока даже боюсь думать, настолько все запутанно и неочевидно.


    1. Alexins
      22.04.2016 21:26

      PKCS#7 — это контейнер, используемый в криптографии. Сертификат, обычно, передается в контейнере PKCS#7, вместе с подписью.
      В контейнер можно положить несколько сертификатов. И будет у нас хранилище сертификатов.
      Можно положить CRL файлы. Можно положить подписываемое сообщение. Можно положить зашифрованное сообщение.
      Отсюда и идут все сложности в понимании.

      Да, в самом сертификате есть подпись издателя и сведения о сертификате издателя. Но сам сертификат не является контейнером формата PKCS#7.

      Для чтения и записи сертификата и контейнера используется стандарт ASN1.
      Отсюда и все сложности на этапе освоения всего этого нагромождения.


      1. crazyblu
        24.04.2016 09:49

        PKCS#7 это не контейнер для сертификата. Это запрос на сертификат, содержащий subject, публичный ключ и, возможно, дополнительные поля. Все это подписано приватным ключем, который никуда не передается.
        СА получает запрос, извлекает публичный ключ и используя его проверяет подпись всего запроса. Если да — добавить поля Issuer, поменять/заменить/добавить дополнительный полей и подписать все это своим приватным ключом CA. Так получается сертификат.
        Далее его можно отдать как есть (bin или base64), можно спрятать в контейнер PKCS#12 под пароль и отдать в нем.

        О криках про шифрование и ключи. Основная задача криптографии не в алгоритмах. Основные трудности (основной упор всех разработок) — создание ключей (надежный непредсказуемый ДСЧ, от чего и появляются аппаратные прибамбасы) и надежный/стойкий метод хранения ключей (приватных в том числе).

        О какой надежности системы можно говорить, если ПРИВАТНЫЕ ключи «ходят по рукам», перекладываются и «светятся» чуть ли не в открытом виде? Алгоритмы описаны на каждом втором вебсайте — приватность именно в хранении ключей. Любой СКЗИ работает по принципу «мы вам сделаем внутри ключ, вы можете использовать его для шифрования/подписи, но сам ключ (его содержимое) будет тайной за семью печатями и для вас тоже».

        Посмотрите как устроены токены? Посмотрите как сделана ваша СИМ-карта в телефоне наконец — она свой ключ Ki не светит нигде и никогда.
        Но использует вовсю.


        1. Alexins
          24.04.2016 19:30
          +1

          Вы бы заглянули на сайт wiki статью PKCS. Запрос на сертификат — это PKCS#10. Разные устройства, типа eToken, это стандарт PKCS#11.

          Что смотреть в этой карточке или USB token? Микроконтроллер. Разве, что, на специальном оборудовании снимать с него стружку. Эти устройства хороши, но очень медленные. Вот, вы, пишите ответ в данной статье. Обмен с сервером идет в зашифрованном протоколе TLS. Теперь, ваш поток мыслей должен пройти через эту карточку / USBToken. После этого, данные уйдут на сервер. Данных не много. А теперь представьте, что этот сервер так же, весь трафик, все HTML статьи, будет гонять через USB Token. Данная технология имеет право на жизнь в некоторых областях применения.


          1. crazyblu
            24.04.2016 20:09

            ОК, я был не совсем прав. Да, запрос это PKCS#10.
            Проблема в том, что PKCS#7 && PKCS#12 не могут выступать в роли хранилищ сертификатов и ключей. Эти протоколы разрабатывались только как транспортные.
            Для хранения — токены (и связанный с ними протокол обмена (!!) PKCS#11), или новый PKCS#15

            Основной вопрос был в попытке оправдать идеологию СКЗИ хранить свою приватную информацию в закрытом ото всех виде. В том числе и от владельца ключа. Обращаться к СКЗИ для использования этого ключа можно, экспортировать и унести ключ — должно быть запрещено.

            Токены я упомянул (равно как и SIM) — пример того, что ключ создан, но пользователь его не видит и не может получить. Он скрыт внутри микросхемы контроллера. Вы можете его использовать, выдавая запросы на операции с этим ключом, микроконтроллер будет отвечать.

            И… давайте не будем меряться скоростями? Есть много решений, почему вы думаете что все токены работают на USB? Но я вовсе не склоняю всех использовать токены как СКЗИ, это скорее пример реализации закрытых ключей. Закрытых «совсем».


  1. nvv
    23.04.2016 13:29

    olegchir, какой класс СКЗИ применяется (должна применяться — КС1, КС2, КС3, КВ1, КВ2, КА1) в Вашей системе в соответствии с требованиями?


    1. olegchir
      23.04.2016 15:56
      +1

      а почему ви спрашиваете?


      1. nvv
        23.04.2016 21:12
        +1

        чем выше класс СКЗИ, тем больше требований к окружению (аппаратный ДСЧ, контроль загрузки и т.д.), не придется потом сильно менять платформу (ОС, версии ПО и др.) для соответствия классу?


  1. BigW
    24.04.2016 09:48

    странный вопрос… требования то для всех едины (210 приказ минкомсвязи от 23 июня 2015) А так — какой в модели угроз написан ;) А там написано, что криптография нам вообще не нужна ;))


    1. olegchir
      24.04.2016 11:40

      наверное, это ответ не мне, а nvv


      1. BigW
        24.04.2016 23:14

        вы правы, промахнулся