хабраиндекс
93,99

Веб-сервисы с поддержкой ЭЦП на базе криптографии ГОСТ

Начиная с версии 2008.2, в Caché и в Ensemble встроена поддержка WS-Security, включающая механизмы проверки и формирования электронной подписи SOAP-сообщений. На текущий момент имеется «out of the box» поддержка ЭЦП на базе крипто алгоритмов семейства RSA.
К системам, создаваемым для российских заказчиков, зачастую предъявляется требование применения сертифицированных СКЗИ, использующих крипто алгоритмы ГОСТ.

Под хабракатом рассказывается, как делать веб-сервисы Caché, защищенные ЭЦП на базе ГОСТ’овской криптографии.


В качестве сертифицированного СКЗИ, будем использовать продукт КриптоПро JCP, представляющий собой набор Java библиотек, в которых реализован алгоритм подписи — ГОСТ Р 34.10-2001, а также алгоритм хэширования ГОСТ Р 34.11-94.

Установка КриптоПро JCP на Windows


Прежде всего, на сервер системы установите Java Runtime Environment (JRE) версии не ниже 1.6.
Загрузите дистрибутив КриптоПро JCP с сайта производителя, распакуйте его в папку на сервере и запустите скрипт установки install.bat. Скрипт находится в папке lib дистрибутива. При его запуске необходимо указать путь к JRE:
install.bat «C:\Program Files\Java\jdk1.6.0_20\jre»
В случае если имеется лицензия, при запуске скрипта также указывается серийный номер и название компании:
install.bat «C:\Program Files\Java\jdk1.6.0_20\jre» XXXXX-XXXXX-XXXXX-XXXXX-XXXXX «Your Company»
Под Windows 7 скрипт установки необходимо запускать с правами администратора. После завершения работы скрипта, убедитесь в том, что в папке jre\lib\ext появились следующие библиотеки:
asn1rt.jar JCP.jar JCPRevCheck.jar JCP_ASN.jar
AsnLite.jar JCPinst.jar JCPRevTools.jar JCryptoP.jar
forms_rt.jar JCPRequest.jar JCPxml.jar

Дополнительные библиотеки Java


Нам понадобится библиотека iscjcp.jar (исходники здесь), в которой содержится ряд вспомогательных классов для работы с JCP из Caché. Кроме этого, потребуются три open source библиотеки — Commons Logging, Santuario (aka XML Security) и WSS4J. Их использование регулируется лицензией Apache Software License 2.0.
Загрузите архив jars.zip с четырьмя перечисленными библиотеками и распакуйте его в папку jre\lib\ext.
В случае использования Windows 7, необходимо выдать полномочия группе «Все» на чтение и выполнение всех библиотек в папке jre\lib\ext.

Настройка и запуск Java Gateway, создание проекций классов


Чтобы стало возможным вызывать Java-классы из Caché/Ensemble, необходимо настроить и запустить Java Gateway, а также создать проекции используемых Java-классов.
Добавим новую запись в таблицу настроек Java Gateway в области %SYS:
insert into %Net_Remote.ObjectGateway(Name, Type, Server, Port, JavaHome) values ('JCPGate', '1', '127.0.0.1', '55555', 'C:\Program Files\Java\jdk1.6.0_20\jre')
Здесь в поле Name указано значение “JCPGate” – это имя нового Java Gateway. В поле JavaHome необходимо указать путь к JRE, для которой была произведена установка JCP. В поле Port указывается TCP-порт, используемый для общения с этим Java Gateway из Caché.
Теперь можно запустить новый Java Gateway, выполнив в терминале Caché следующую команду:
write ##class(%Net.Remote.Service).StartGateway(«JCPGate»)
Чтобы остановить его, вызовите метод StopGateway:
write ##class(%Net.Remote.Service).StopGateway(«JCPGate»)
Запускать/останавливать Java Gateway можно из любой области.
Перейдем в область, где ведется разработка веб-сервисов, и создадим проекцию для Java-класса isc.jcp.JcpFacade, выполнив в терминале Caché следующую команду:
do ##class(%Net.Remote.Java.JavaGateway).%ExpressImport(«isc.jcp.JcpFacade», «55555»)
Здесь 55555 – это номер TCP-порта, который используется для общения с Java Gateway. Этот порт был указан нами ранее при добавлении записи в таблицу %Net_Remote.ObjectGateway.

Проверка ЭЦП во входящих SOAP-сообщениях


Загрузите и распакуйте архив iscjcp-cos-sources.zip с исходным кодом классов smev.JcpUtils и smev.JcpSignature. Импортируйте класс smev.JcpUtils в Caché с помощью Studio, предварительно перейдя в область, где ведется разработка веб-сервисов. Откройте импортированный класс в Studio и отредактируйте значения параметров JAVAGATEWAYPORT и JAVAGATEWAYSERVER, указав соответственно TCP-порт и IP-адрес используемого Java Gateway. Скомпилируйте класс.
Теперь, чтобы добавить в существующий веб-сервис проверку ЭЦП, достаточно внести в класс веб-сервиса следующий метод:
Method OnPreSOAP(mode As %String, action As %String, request)
{
  #dim stream As %Stream.Object = request
  if '$isObject(stream)
  {
    // на случай MIME attachments
    #dim index As %Integer = %request.NextMimeData("")
    set stream = $select(index="":"", 1:%request.GetMimeData(index))
  }
  if $isObject(stream)
  {
  #dim fault As %SOAP.Fault = ##class(smev.JcpUtils).verifySignatureOnPreSoap(stream)
    if $isObject(fault) set ..SoapFault = fault
  }
}
Это работает на версиях Caché/Ensemble, начиная с 2009.1. Ниже приведен пример веб-сервиса, который осуществляет проверку подписи всех входящих SOAP-сообщений.
Class test.TestService Extends %SOAP.WebService
{
  Parameter SERVICENAME = "TestService";

  Parameter NAMESPACE = "http://test/wsdl";

  Method echo(request As %String) As %String [ ProcedureBlock = 1, SoapAction = "urn:echo", SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
  {
     quit request
  }

  Method OnPreSOAP(mode As %String, action As %String, request)
  {
    #dim stream As %Stream.Object = request

    if '$isObject(stream)
    {
      // на случай MIME attachments
      #dim index As %Integer = %request.NextMimeData("")
      set stream = $select(index="":"", 1:%request.GetMimeData(index))
    }

    if $isObject(stream)
    {
      #dim fault As %SOAP.Fault = ##class(smev.JcpUtils).verifySignatureOnPreSoap(stream)
      if $isObject(fault) set ..SoapFault = fault
    }
  }
}


Формирование ЭЦП для исходящих SOAP-сообщений веб-сервиса


Далее рассмотрим случай, когда все ответы веб-сервиса должны быть подписаны ЭЦП организации. В такой ситуации на сервере системы размещается хранилище, содержащее секретный ключ, который используется при формировании подписи. Кроме того, должен быть доступен сертификат, соответствующий этому ключу. В библиотеке iscjcp.jar реализована работа с хранилищем типа “FloppyStore”. Поэтому, для формирования ЭЦП нам потребуется виртуальная дискета с хранилищем ключей.

Размещение секретного ключа и сертификата на виртуальной дискете на сервере системы


Чтобы создать такую дискету, выполните следующие действия:
  1. Установите драйвер, имитирующий FDD привод, например, ImDisk.
  2. Из панели управления Windows запустите программу настройки «ImDisk Virtual Disk Driver» и настройте диск с параметрами:
    • Drive letter: A,
    • Size of virtual disk: 1 Megabyte,
    • Device type: Floppy.

  3. Отформатируйте виртуальную дискету, задав файловую систему FAT.
  4. Распакуйте содержимое архива FDD.zip на диск A:\.

В результате описанных манипуляций на диске A:\ сервера имеем хранилище ключей, содержащее тестовый секретный ключ. Файл A:\SelfSigned.cer представляет собой тестовый сертификат, соответствующий секретному ключу.
Вы можете самостоятельно генерировать ключи и сертификаты с помощью КриптоПро JCP. Эти процедуры описаны в документации продукта.

Формирование ЭЦП


Загруженный ранее архив iscjcp-cos-sources.zip с исходным кодом Caché Object Script содержал класс smev.JcpSignature. Импортируйте этот класс в Caché с помощью Studio.
Откройте класс smev.JcpUtils в Studio и отредактируйте значение параметра CERTFILENAME, указав полный путь к файлу сертификата – “A:\SelfSigned.cer”. Этот сертификат соответствует секретному ключу, который будет использоваться при формировании ЭЦП. Скомпилируйте класс.
Теперь, чтобы добавить в метод веб-сервиса функционал по формированию ЭЦП для возвращаемых сообщений, необходимо вставить следующую строку в код этого метода:
do ..SecurityOut.AddElement(##class(smev.JcpSignature).%New())
Это работает на версиях Caché/Ensemble, начиная с 2009.1, по 2011.1 включительно. Ниже приведен пример веб-сервиса, где в метод echo() добавлено подписывание ответа.
Class test.TestService Extends %SOAP.WebService
{
  Parameter SERVICENAME = "TestService";

  Parameter NAMESPACE = "http://test/wsdl";

  Method echo(request As %String) As %String [ ProcedureBlock = 1, SoapAction = "urn:echo", SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
  {
     do ..SecurityOut.AddElement(##class(smev.JcpSignature).%New())
     quit request
  }

  Method OnPreSOAP(mode As %String, action As %String, request)
  {
    #dim stream As %Stream.Object = request

    if '$isObject(stream)
    {
      // на случай MIME attachments
      #dim index As %Integer = %request.NextMimeData("")
      set stream = $select(index="":"", 1:%request.GetMimeData(index))
    }

    if $isObject(stream)
    {
      #dim fault As %SOAP.Fault = ##class(smev.JcpUtils).verifySignatureOnPreSoap(stream)
      if $isObject(fault) set ..SoapFault = fault
    }
  }
}


Тестирование веб-сервиса


Чтобы протестировать проверку/формирование ЭЦП веб-сервисом test.TestService, исходный код которого приведен выше, выполним следующие действия.
  1. При помощи Studio создадим класс test.TestService в той же области, куда были импортированы классы smev.*. Исходный код нового класса скопируем из вышеприведенного листинга.
  2. С помощью Блокнота создадим файл C:\Temp\input.xml, содержащий тело входящего SOAP-сообщения для сервиса test.TestService:
     
    <SOAP-ENV:Body wsu:Id=«id1»
            xmlns:SOAP-ENV=«schemas.xmlsoap.org/soap/envelope/»
            xmlns:wsu=«docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd»>
      <s0:echo xmlns:s0=«test/wsdl»>
        <s0:request>Здравствуй, мир!</s0:request>
      </s0:echo>
    </SOAP-ENV:Body>
  3. Запустим в терминале Caché метод signFile() класса smev.JcpUtils:
     
    write ##class(smev.JcpUtils).signFile(«id1», «C:\Temp\input.xml», «C:\Temp\output.xml»)
    Убедимся в том, что в результате работы метода был создан файл C:\Temp\output.xml, содержащий подписанное SOAP-сообщение (Envelope): в заголовке (Header) находится ЭЦП в формате WS-Security, а тело (Body) представляет собой XML-документ, взятый из файла input.xml.
    Готовый файл output.xml имеется в архиве xmls.zip.

    Направим полученное SOAP-сообщение с ЭЦП на вход сервиса test.TestService. Для этого выполним в терминале Caché следующие команды (при необходимости, замените порт веб-сервера – “57772” на правильный, а также область “user” в предпоследней команде):
     
    set httprequest = ##class(%Net.HttpRequest).%New()
    set httprequest.Server = «localhost»
    set httprequest.Port = «57772»
    set httprequest.WriteRawMode = 1
    set httprequest.ContentType = «text/xml»
    do httprequest.SetHeader(«SOAPAction»,«urn:echo»)
    set fileStream = ##class(%Library.FileBinaryStream).%New()
    set fileStream.Filename = «C:\Temp\output.xml»
    do httprequest.EntityBody.CopyFrom(fileStream)
    do httprequest.Post("/csp/user/test.TestService.cls")
    do httprequest.HttpResponse.OutputToDevice()
     
    Если успешно прошла проверка ЭЦП входящего сообщения, а затем и формирование ЭЦП исходящего, то в окне терминала появится ответ веб-сервиса примерно такого вида:
     
    HTTP/1.1 200 OK
    CACHE-CONTROL: no-cache
    CONNECTION: close
    CONTENT-LENGTH: 2352
    CONTENT-TYPE: text/xml; charset=UTF-8
    DATE: Thu, 01 Dec 2011 20:08:40 GMT
    EXPIRES: Thu, 29 Oct 1998 17:04:19 GMT
    PRAGMA: no-cache
    SERVER: Apache
    SET-COOKIE: CSPSESSIONID-SP-57774-UP-csp-user-=0000000100001odLLhtp000000igxIuSVnd12z6BtrSIFFJA—; path=/csp/user/;
     
    <?xml version=«1.0» encoding=«UTF-8» ?>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV=’http://schemas.xmlsoap.org/soap/envelope/’ xmlns:xsi=’http://www.w3.org/2001/XMLSchema-instance’ xmlns:s=’http://www.w3.org/2001/XMLSchema’ xmlns:wsse=’http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd’ xmlns:wsu=’http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd’>
    <SOAP-ENV:Header>
    <ds:Signature xmlns:ds=«www.w3.org/2000/09/xmldsig#»>
    <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm=«www.w3.org/2001/10/xml-exc-c14n#»/>
    <ds:SignatureMethod Algorithm=«www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411»/>
    <ds:Reference URI="#Body-B290AFEC-9812-49E4-9177-6D617D30622C">
    <ds:Transforms>
    <ds:Transform Algorithm=«www.w3.org/2001/10/xml-exc-c14n#»/>
    </ds:Transforms>
    <ds:DigestMethod Algorithm=«www.w3.org/2001/04/xmldsig-more#gostr3411»/>
    <ds:DigestValue>vs42sfoxCX8naSV2NnBSoIoCvUb1ydvvyNnp5XC7nKQ=</ds:DigestValue>
    </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>
    ES4aVXFSkHr1cnXUcdZYJTPTa+e5//ASQRYhrRMy46pWSwRW93VxgrW+GhATD2xwK3l+8T1Dfsi2
    beVfrkQS0g==
    </ds:SignatureValue>
    <ds:KeyInfo>
    <ds:X509Data>
    <ds:X509Certificate>
    MIIB9TCCAaSgAwIBAgIIRdAY3dqebKUwCAYGKoUDAgIEMCkxJzAlBgNVBAMeHgB0AC4AZQAuAG0A
    LgBwAEAAbQBhAGkAbAAuAHIAdTAeFw0xMTExMjkxMzQwMTFaFw0xMjExMjkxMzQwMTFaMCkxJzAl
    BgNVBAMeHgB0AC4AZQAuAG0ALgBwAEAAbQBhAGkAbAAuAHIAdTBjMBwGBiqFAwICEzASBgcqhQMC
    AiMBBgcqhQMCAh4BA0MABECebxtl5EDpwaWKy2MeJQ7v+NCiIRHiXBeqaqJnNi5AS4aW+14FKKHH
    Llu7jjggB06d+/4U29OtDbjfIkPqRUcio4GtMIGqMB0GA1UdDgQWBBTz0qujqn+CC0O9L1aSv39a
    ga3EhDALBgNVHQ8EBAMCAcYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDwYDVR0TBAgwBgEB/wIBATBW
    BgNVHQEETzBNgBTz0qujqn+CC0O9L1aSv39aga3EhKErMCkxJzAlBgNVBAMeHgB0AC4AZQAuAG0A
    LgBwAEAAbQBhAGkAbAAuAHIAdYIIRdAY3dqebKUwCAYGKoUDAgIEA0EANUalM3ag0xYJ7MqzmCzh
    w8ejPqUds37UXKadbyqogZ2yJBMbhWUCsQFyZZZzfc6gXQbRThBTAftfdXxjW8Yusg==
    </ds:X509Certificate>
    </ds:X509Data>
    </ds:KeyInfo>
    </ds:Signature>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body wsu:Id=«Body-B290AFEC-9812-49E4-9177-6D617D30622C»>Здравствуй, мир!</SOAP-ENV:Body>
    </SOAP-ENV:Envelope>


Все действия, описанные в статье, можно посмотреть в следующем видеоролике:
0
27 января 2012, 16:52
4

комментарии (1)

0
intersystems #
Добавлено видео-прохождение статьи с комментариями.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.