📜 ⬆️ ⬇️

Web services with electronic signature support based on GOST cryptography

Starting with version 2008.2, support for WS-Security has been built into Caché and Ensemble, including mechanisms for verifying and generating electronic signatures of SOAP messages. Currently, there is an “out of the box” support for EDS based on crypto algorithms of the RSA family.

The systems created for Russian customers are often subject to the requirement of using certified SKZI using GOST crypto algorithms. The following describes one of the approaches to the development of Caché web services, protected by EDS based on GOST-based cryptography.

As a certified SKPI, we will use the CryptoPro JCP product, which is a set of Java libraries that implement the signature algorithm - GOST R 34.10-2001 , as well as the hash algorithm GOST R 34.11-94 .

Installing CryptoPro JCP on Windows


First of all, install Java Runtime Environment (JRE) version 1.6 or higher on the server system.
')
Download the CryptoPro JCP distribution from the manufacturer’s website, unpack it into a folder on the server and run the install.bat installation script. The script is located in the lib folder of the distribution. When you run it, you must specify the path to the JRE:

install.bat "C: \ Program Files \ Java \ jdk1.6.0_20 \ jre"

If there is a license, when starting the script, the serial number and company name are also indicated:

install.bat "C: \ Program Files \ Java \ jdk1.6.0_20 \ jre" XXXXX-XXXXX-XXXXX-XXXXX-XXXXX "Your Company"

Under Windows 7, the installation script must be run as administrator. After the script completes, make sure that the following libraries appear in the jre \ lib \ ext folder:
asn1rt.jarJCP.jarJCPRevCheck.jarJCP_ASN.jar
AsnLite.jarJCPinst.jarJCPRevTools.jarJCryptoP.jar
forms_rt.jarJCPRequest.jarJCPxml.jar

Additional Java Libraries


We will need the iscjcp.jar library (source code here ), which contains a number of auxiliary classes for working with JCP from Caché. In addition, three open source libraries will be required - Commons Logging , Santuario (aka XML Security) and WSS4J . Their use is governed by the Apache Software License 2.0 .

Download the jars.zip archive with the four libraries listed and unpack it into the jre \ lib \ ext folder.

If you are using Windows 7, you must grant permissions to the Everyone group to read and execute all the libraries in the jre \ lib \ ext folder.

Setting up and launching Java Gateway, creating class projections


To make it possible to call Java classes from Caché / Ensemble, you must configure and run Java Gateway, as well as create projections of the Java classes used.

Add a new entry to the Java Gateway settings table in the% SYS area:

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 ')

Here in the Name field, the value “JCPGate” is the name of the new Java Gateway. In the JavaHome field, you must specify the path to the JRE for which the JCP was installed. The Port field indicates the TCP port used to communicate with this Java Gateway from Caché.

Now you can launch the new Java Gateway by running the following command in a Caché terminal:

write ## class (% Net.Remote.Service) .StartGateway ("JCPGate")

To stop it, call the StopGateway method:

write ## class (% Net.Remote.Service). StopGateway ("JCPGate")

You can start / stop Java Gateway from any area.

Let's go to the area where web services are being developed and create a projection for the isc.jcp.JcpFacade Java class by running the following command in the Caché terminal:

do ## class (% Net.Remote.Java.JavaGateway).% ExpressImport ("isc.jcp.JcpFacade", "55555")

Here, 55555 is the TCP port number used to communicate with the Java Gateway. We specified this port earlier when adding an entry to the% Net_Remote.ObjectGateway table.

Verification of digital signature in incoming SOAP-messages


Download and unzip the iscjcp-cos-sources2012.zip archive with the source code of smev.JcpUtils and smev.JcpSignature classes. Import the smev.JcpUtils class into Caché using Studio, first moving to the area where web services are being developed. Open the imported class in Studio and edit the values ​​of the JAVAGATEWAYPORT and JAVAGATEWAYSERVER parameters, specifying the TCP port and the IP address of the Java Gateway used, respectively. Compile the class.

Now, to add a digital signature verification to an existing web service, it suffices to add the following method to the web service class:

 Method OnPreSOAP (mode As% String, action As% String, request)
 {
   do ## super (mode, action, request)

   #dim stream As% Stream.Object = request

   if '$ isObject (stream)
   {
     // in case of 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
   }
 }

It works on Caché / Ensemble versions starting from 2009.1. Below is an example of a web service that checks the signatures of all incoming SOAP messages.

 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)
   {
     do ## super (mode, action, request)

     #dim stream As% Stream.Object = request

     if '$ isObject (stream)
     {
       // in case of 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
     }
   }
 }

Formation of EDS for outgoing SOAP messages of a web service


Next, we consider the case when all the responses of the web service must be signed by the organization’s EDS. In such a situation, the server of the system hosts the storage containing the secret key that is used when generating the signature. In addition, a certificate must be available that corresponds to this key. The iscjcp.jar library implements work with a “FloppyStore” storage. Therefore, for the formation of EDS, we need a virtual diskette with a keystore.

Placement of the private key and certificate on a virtual diskette on the system server


To create such a floppy disk, follow these steps:
  1. Install a driver that simulates a FDD drive, for example, ImDisk .
  2. From the Windows Control Panel, launch the “ImDisk Virtual Disk Driver” setup program and configure the disk with the following parameters:
    • Drive letter: A,
    • Size of virtual disk: 1 Megabyte,
    • Device type: Floppy.
  3. Format the virtual diskette by specifying the FAT file system.
  4. Unzip the contents of the archive FDD.zip to disk A: \.

As a result of the described manipulations on the A: \ server disk, we have the keystore containing the test secret key. File A: \ SelfSigned.cer is a test certificate corresponding to the private key.

You can independently generate keys and certificates using CryptoPro JCP. These procedures are described in the product documentation.

Formation of EDS


The previously downloaded iscjcp-cos-sources2012.zip archive with the Caché Object Script source code contained the smev.JcpSignature class. Import this class into Caché using Studio.

Open the smev.JcpUtils class in Studio and edit the value of the CERTFILENAME parameter specifying the full path to the certificate file - “A: \ SelfSigned.cer”. This certificate corresponds to the secret key that will be used when generating the EDS. Compile the class.

Now, to add to the web service method the functionality for generating EDS for returned messages, you need to insert the following line into the code of this method:

do ..SecurityOut.AddElement (## class (smev.JcpSignature).% New ())

This works on Caché / Ensemble versions from 2009.1 through 2012.1 inclusive. Below is an example of a web service where the signing of the response is added to the echo () method.

 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)
   {
     do ## super (mode, action, request)

     #dim stream As% Stream.Object = request

     if '$ isObject (stream)
     {
       // in case of 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
     }
   }
 }

Web service testing


To test the verification / generation of EDS by the web service test.TestService, the source code of which is given above, we will perform the following steps.

  1. Using Studio, create a test.TestService class in the same area where the smev. * Classes were imported. The source code of the new class is copied from the above listing.

  2. Using Notepad, create the file C: \ Temp \ input.xml, containing the body of the incoming SOAP message for the test.TestService service:

     <SOAP-ENV: Body wsu: Id = "id1"
             xmlns: SOAP-ENV = "http://schemas.xmlsoap.org/soap/envelope/"
             xmlns: wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
       <s0: echo xmlns: s0 = "http: // test / wsdl">
         <s0: request> Hello world! </ s0: request>
       </ s0: echo>
     </ SOAP-ENV: Body>
    

    The file must be saved in UTF-8 encoding. Notice the wsu: Id attribute of the root Body element.

    The finished input.xml file is available in the xmls.zip archive.

  3. Run the signFile () method in the Caché terminal of the smev.JcpUtils class:
    write ## class (smev.JcpUtils) .signFile ("id1", "C: \ Temp \ input.xml", "C: \ Temp \ output.xml")

    Make sure that the result of the work of the method was the creation of the file C: \ Temp \ output.xml, which contains the signed SOAP message (Envelope): in the header (Header) there is an EDS in the format WS-Security, and the body (Body) is An XML document taken from the input.xml file.

    The finished output.xml file is available in the xmls.zip archive.

  4. We will send the received SOAP message from the EDS to the input of the test.TestService service. To do this, execute the following commands in the Caché terminal (if necessary, replace the web server port - “57772” with the correct one, as well as the “user” area in the penultimate command):

      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 ()
    

    If the verification of the digital signature of the incoming message has successfully passed, and then the formation of the outgoing digital signature, then a web service response of the following type will appear in the terminal window:

    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, Oct 29, 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>
    <Security xmlns = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <ds: Signature xmlns: ds = "http: / /www.w3.org/2000/09/xmldsig # ">
    <ds: SignedInfo>
    <ds: CanonicalizationMethod Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#" />
    <ds: SignatureMethod Algorithm = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411" />
    <ds: Reference URI = "# Body-B290AFEC-9812-49E4-9177-6D617D30622C">
    <ds: Transforms>
    <ds: Transform Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#" />
    </ ds: Transforms>
    <ds: DigestMethod Algorithm = "http://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>
    </ Security> </ SOAP-ENV: Header>
    <SOAP-ENV: Body wsu: Id = "Body-B290AFEC-9812-49E4-9177-6D617D30622C"> <echoResponse xmlns = "http: // test / wsdl"> <echoResult> Hello world! </ EchoResult> < / echoResponse> </ SOAP-ENV: Body>
    </ SOAP-ENV: Envelope>



All actions described in the article can be seen in the following video:

Source: https://habr.com/ru/post/137145/


All Articles