📜 ⬆️ ⬇️

SMEV 3. Electronic signature of messages in Java and CryptoPro



The system of interdepartmental electronic interaction (SMEV) was conceived as a digital environment for the provision of services and the execution of state and municipal functions in electronic form.

Currently, SMEV continues to expand its capabilities and involve an increasing number of participants in the interaction.
')
What turned out to be an opportune way, including for commercial organizations, in particular banks, which are increasingly seeking to translate their services into digital and serialize processes.

In this article we will talk about how to sign requests with our own forces and check the electronic signatures of the responses of the SMEV version 3.0, and about a couple of interesting nuances that we had to face.

Hello!

There may be a question. Why on their own? When for SMEV 3 there is a whole Technology portal , where


That's right, the portal is certainly extremely useful, and all its tips and tools can and should be used, but here we write our Java code.

For the simple reason that there is already a proprietary information system that works with the XMLDSig electronic signature formats, XAdES, which uses Apache Santuario project libraries that implement basic security standards for XML. As well as the libraries that make up CryptoPro JCSP , in addition to working with XML, provide the cryptographic functions API of the CryptoPro CSPI .

Writing our own methods for working with electronic signatures of SMEV 3 in this case looks more appropriate than deploying the full client of the supplied:
FSBI SRI "Sunrise" (until March 21, 2016 FSUE SRI "Sunrise") or the integration of its individual classes and packages.

At the same time, looking into the open source code of a client is always useful, and its presence in itself speaks of the maturity of the system and a high level of support.

Source Data Analysis


Download from the portal SMEV 3:


If we are already able to form an ordinary XMLDSig or sign, for example, the envelopes of the SMEV 2 messages, then it becomes most interesting to know what distinguishes the envelope with the signature of the SMEV 3 from the SMEV 2.

Open the envelope example SMEV 3 SendRequestRequestNoAttach.xml

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1"> <S:Body> <ns2:SendRequestRequest xmlns:ns3="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/faults/1.1" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"> <ns:SenderProvidedRequestData Id="SIGNED_BY_CONSUMER" xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"> <ns:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns:MessageID><ns2:MessagePrimaryContent><ns1:BreachRequest xmlns:ns1="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" xmlns:ns2="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0" xmlns:ns3="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1" Id="PERSONAL_SIGNATURE"> <ns1:RequestedInformation> <ns2:RegPointNum>78557</ns2:RegPointNum> </ns1:RequestedInformation> <ns1:Governance> <ns2:Name> </ns2:Name> <ns2:Code>GIBDD</ns2:Code> <ns2:OfficialPerson> <ns3:FamilyName></ns3:FamilyName> <ns3:FirstName></ns3:FirstName> <ns3:Patronymic></ns3:Patronymic> </ns2:OfficialPerson></ns1:Governance> </ns1:BreachRequest> </ns2:MessagePrimaryContent> <ns:TestMessage/></ns:SenderProvidedRequestData> <ns2:CallerInformationSystemSignature><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="#SIGNED_BY_CONSUMER"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/><ds:DigestValue>/jXl70XwnttJB5sSokwh8SaVHwo2gjgILSu0qBaLUAo=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>J3746ks34pOcPGQpKzc0sz3n9+gjPtzZbSEEs4c3sTwbtfdaY7N/hxXzEIvXc+3ad9bc35Y8yBhZ/BYbloGt+Q==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIBcDCCAR2gAwIBAgIEHVmVKDAKBgYqhQMCAgMFADAtMRAwDgYDVQQLEwdTWVNURU0xMQwwCgYDVQQKEwNJUzIxCzAJBgNVBAYTAlJVMB4XDTE1MDUwNzEyMTUzMFoXDTE4MDUwNjEyMTUzMFowLTEQMA4GA1UECxMHU1lTVEVNMTEMMAoGA1UEChMDSVMyMQswCQYDVQQGEwJSVTBjMBwGBiqFAwICEzASBgcqhQMCAiMBBgcqhQMCAh4BA0MABEDoWGZlTUWD43G1N7TEm14+QyXrJWProrzoDoCJRem169q4bezFOUODcNooQJNg3PtAizkWeFcX4b93u8fpVy7RoyEwHzAdBgNVHQ4EFgQUaRG++MAcPZvK/E2vR1BBl5G7s5EwCgYGKoUDAgIDBQADQQCg25vA3RJL3kgcJhVOHA86vnkMAtZYr6HBPa7LpEo0HJrbBF0ygKk50app1lzPdZ5TtK2itfmNgTYiuQHX3+nE</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></ns2:CallerInformationSystemSignature> </ns2:SendRequestRequest> </S:Body> </S:Envelope> 


By the deductive method it turns out that:

Through this transformation, own rules of canonicalization of SMEV 3 are disseminated.

Canonicalization is the process of converting data, having several possible forms of presentation, to one normalized standard form.

Before calculating the hash of the attribute being signed in the XML envelope and signing it, it is necessary to convert it to the 3 form specified by the rules of SMEV.

In search of a description of the transformation urn: // smev-gov-ru / xmldsig / transform open Methodical recommendations 3.4.0.3

We are acquainted with clause 4.4.2.1 of the Rules for generating electronic signature of messages.

XMLDSig detached signature format (https://www.w3.org/TR/xmldsig-core/)

Transformation, in addition to canonization urn: // smev-gov-ru / xmldsig / transform

Formatting Requirements The XML structure of the signature between elements does not allow text nodes, including line breaks.

Paragraph Guidelines 12.4. APPENDIX 4: EXEMPLARY IMPLEMENTATION OF TRANSFORMATION URN: // SMEV-GOV-RU / XMLDSIG / TRANSFORM
contains the Java class SmevTransformSpi.java , which implements the transformation algorithm "urn: // smev-gov-ru / xmldsig / transform", inherited from org.apache.xml.security.transforms.TransformSpi from the Apache Santuario library.

Thus, in order to ensure the canonicalization of the signed envelope SMEV 3, this transformation class can be used in your code.

The only condition and limitation in this case is that to process the XML document when generating a signature or verifying it, you need to use org.apache.xml.security.signature.XMLSignature from the Apache Santuario project.

Using tools from the javax.xml.crypto.dsig or ru.CryptoPro.JCPxml.xmldsig packages just won't work anymore.

Preparation for the signature according to the rules of SMEV 3


Apache Santuario initially does not know anything about GOST cryptographic algorithms and CryptoPro SKZI.

The xmlsec-1.5.0.jar library in the \ org \ apache \ xml \ security \ resource \ config.xml file contains settings for working with foreign cryptographic algorithms only.

In order for it to begin to recognize and apply GOST, you need to initialize it.

In the old way it was done like this:

 //APACHE-SANTUARIO INIT WITH CryptoPro JCP System.setProperty("org.apache.xml.security.resource.config", "resource/jcp.xml"); org.apache.xml.security.Init.init(); String cfile1 = System.getProperty("org.apache.xml.security.resource.config"); LOGGER.log(Level.INFO, "Init class URL: " + org.apache.xml.security.Init.class.getProtectionDomain().getCodeSource().getLocation()); LOGGER.log(Level.INFO, cfile1); 

In new versions of CryptoPro JCP (JCSP), one line will perform initialization:

 ru.CryptoPro.JCPxml.xmldsig.JCPXMLDSigInit.init(); 

Now we need Apache Santuario to teach the new transformation rules dictated by SMEV 3. To do this, we register the transformation class:

  try { Transform.register(SmevTransformSpi.ALGORITHM_URN, SmevTransformSpi.class.getName()); santuarioIgnoreLineBreaks(true); LOGGER.log(Level.INFO, "SmevTransformSpi has been initialized"); } catch (AlgorithmAlreadyRegisteredException e) { LOGGER.log(Level.INFO, "SmevTransformSpi Algorithm already registered: " + e.getMessage()); } 

At the same time, we immediately fulfill the requirement of the Methodical Instructions:

Formatting Requirements The XML structure of the signature between elements does not allow text nodes, including line breaks.

 santuarioIgnoreLineBreaks(true); private static final String IGNORE_LINE_BREAKS_FIELD = "ignoreLineBreaks"; /** * Apache Santuario privileged switch IgnoreLineBreaks property * * @param mode */ private void santuarioIgnoreLineBreaks(Boolean mode) { try { Boolean currMode = mode; AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() { public Boolean run() throws Exception { Field f = XMLUtils.class.getDeclaredField(IGNORE_LINE_BREAKS_FIELD); f.setAccessible(true); f.set(null, currMode); return false; } }); } catch (Exception e) { LOGGER.warning("santuarioIgnoreLineBreaks " + ExceptionUtils.getFullStackTrace(e)); } } 

This is done in the privileged block AccessController.doPrivileged
and through reflection, due to the peculiarity of the implementation of the ignoreLineBreaks property in Santuario.

Just by setting the system property:

 System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true"); 

does not work.

By setting the JVM option:

 -Dcom.sun.org.apache.xml.internal.security.ignoreLineBreaks=true 

works.

If you look at the code of the org.apache.xml.security.utils.XMLUtils class, you can see that the ignoreLineBreaks static field is initialized in a privileged block from the system property "org.apache.xml.security.ignoreLineBreaks" .

 private static boolean ignoreLineBreaks = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { return Boolean.valueOf(Boolean.getBoolean ("org.apache.xml.security.ignoreLineBreaks")); } }).booleanValue(); public static boolean ignoreLineBreaks() { return ignoreLineBreaks; } 

Such an implementation makes it impossible to configure flexibly in one Java process for part of the methods to ignore line feeds, and for the other part not to ignore.

That is, if one application executes the XMLDsig, SMEV 2 and SMEV 3 signatures, all XML documents processed by Santuario should lose the translation of the output at the output.

With this property, of course, the question arises for Apache Santuario:



Signature of messages SMEV 3


For the signing of documents SMEV 3 everything is ready.

The signing code looks like this:

 private static final String XMLDSIG_MORE_GOSTR34102001_GOSTR3411 = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"; private static final String XMLDSIG_MORE_GOSTR3411 = "http://www.w3.org/2001/04/xmldsig-more#gostr3411"; private static final String CANONICALIZATION_METHOD = "http://www.w3.org/2001/10/xml-exc-c14n#"; private static final String DS_SIGNATURE = "//ds:Signature"; private static final String SIG_ID = "sigID"; private static final String COULD_NOT_FIND_XML_ELEMENT_NAME = "ERROR! Could not find xmlElementName = "; private static final String GRID = "#"; private static final String XML_SIGNATURE_ERROR = "xmlDSignature ERROR: "; try { //    XML- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //  ,     //     XML- dbf.setIgnoringElementContentWhitespace(true); //  ,    CDATA  //     XML- dbf.setCoalescing(true); //  ,      //  XML- dbf.setNamespaceAware(true); //       //       data DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); Document doc = documentBuilder.parse(new ByteArrayInputStream(data)); /* *    <ds:Signature>   XML- */ //   (  34.10-2001) final String signMethod = XMLDSIG_MORE_GOSTR34102001_GOSTR3411; //  ,    (  34.11-94) final String digestMethod = XMLDSIG_MORE_GOSTR3411; final String canonicalizationMethod = CANONICALIZATION_METHOD; String[][] filters = {{XPath2FilterContainer.SUBTRACT, DS_SIGNATURE}}; String sigId = SIG_ID; //        //    34.10-2001 XMLSignature sig = new XMLSignature(doc, "", signMethod, canonicalizationMethod); //      sig.setId(sigId); //    XML- Element anElement = null; if (xmlElementName == null) { anElement = doc.getDocumentElement(); } else { NodeList nodeList = doc.getElementsByTagName(xmlElementName); anElement = (Element) nodeList.item(0); } // = doc.getElementById("#AppData"); //     XML-   if (anElement != null) { anElement.appendChild(sig.getElement()); } else { throw new SignatureProcessorException(COULD_NOT_FIND_XML_ELEMENT_NAME + xmlElementName); } /* *     XML-       *  */ //    <ds:Transforms>  // XML- Transforms transforms = new Transforms(doc); //         // transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE); transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); transforms.addTransform(SmevTransformSpi.ALGORITHM_URN); //      ( <ds:Reference>), //     // XML- (      //  <ds:Transforms>  //    ) sig.addDocument(xmlElementID == null ? "" : GRID + xmlElementID, transforms, digestMethod); /* *     XML-    , *     */ //      <ds:KeyInfo>   //     //  sig.addKeyInfo(x509Cert); //   XML- sig.sign(privateKey); //  ,      // XML- bais = new ByteArrayOutputStream(); //     XML-  //  TransformerFactory tf = TransformerFactory.newInstance(); //     XML-   Transformer trans = tf.newTransformer(); //   XML-   trans.transform(new DOMSource(doc), new StreamResult(bais)); bais.close(); } catch (TransformationException e) { throw new SignatureProcessorException("TransformationException " + XML_SIGNATURE_ERROR + e.getMessage()); } catch (XMLSignatureException e) { throw new SignatureProcessorException("XMLSignatureException " + XML_SIGNATURE_ERROR + e.getMessage()); } catch (TransformerException e) { throw new SignatureProcessorException("TransformerException " + XML_SIGNATURE_ERROR + e.getMessage()); } catch (IOException e) { throw new SignatureProcessorException("IOException " + XML_SIGNATURE_ERROR + e.getMessage()); } catch (XMLSecurityException e) { throw new SignatureProcessorException("XMLSecurityException " + XML_SIGNATURE_ERROR + e.getMessage()); } catch (SAXException e) { throw new SignatureProcessorException("SAXException " + XML_SIGNATURE_ERROR + e.getMessage()); } catch (ParserConfigurationException e) { throw new SignatureProcessorException( "ParserConfigurationException " + XML_SIGNATURE_ERROR + e.getMessage()); } return bais.toByteArray(); 

The main parameters here are:

 byte[] data, // XML      String xmlElementName, //    XML   ,     ,  -3    "ns2:CallerInformationSystemSignature" String xmlElementID // ID   XML ( )   ,     ,  -3    "SIGNED_BY_CONSUMER" X509Certificate certificate //      PrivateKey privateKey //    


Verification of the signature of the message SMEV 3


The signature verification code is as follows:

 private static final QName QNAME_SIGNATURE = new QName("http://www.w3.org/2000/09/xmldsig#", "Signature", "ds"); private static final String SIGNATURE_NOT_FOUND = "Signature not found!"; private static final String SIGNATURE_NOT_VALID = "Signature not valid"; private static final String SMEV_SIGNATURE_PASSED_CORE_VALIDATION = "SmevSignature passed core validation"; private static final String VERIFY_SIGNATURE_ON_XML_IO_EXCEPTION = "Verify signature on XML IOException: "; private static final String VERIFY_SIGNATURE_ON_XML_PARSER_CONFIGURATION_EXCEPTION = "Verify signature on XML ParserConfigurationException: "; private static final String VERIFY_SIGNATURE_ON_XML_SAX_EXCEPTION = "Verify signature on XML SAXException: "; private static final String VERIFY_SIGNATURE_ON_XML_XML_SIGNATURE_EXCEPTION = "Verify signature on XML XMLSignatureException: "; private static final String VERIFY_SIGNATURE_ON_XML_XML_SECURITY_EXCEPTION = "Verify signature on XML XMLSecurityException: "; private static final String ID = "Id"; boolean coreValidity = true; try { DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance(); bf.setNamespaceAware(true); DocumentBuilder b = bf.newDocumentBuilder(); Document doc = b.parse(new InputSource(new ByteArrayInputStream(signedXmlData))); NodeList sigs = doc.getElementsByTagNameNS(QNAME_SIGNATURE.getNamespaceURI(), QNAME_SIGNATURE.getLocalPart()); org.apache.xml.security.signature.XMLSignature sig = null; sigSearch: { for (int i = 0; i < sigs.getLength(); i++) { Element sigElement = (Element) sigs.item(i); String sigId = sigElement.getAttribute(ID); if (sigId != null) { sig = new org.apache.xml.security.signature.XMLSignature(sigElement, ""); break sigSearch; } } throw new XMLSignatureVerificationException(SIGNATURE_NOT_FOUND); } org.apache.xml.security.keys.KeyInfo ki = (org.apache.xml.security.keys.KeyInfo) sig.getKeyInfo(); X509Certificate certificate = ki.getX509Certificate(); if (!sig.checkSignatureValue(certificate.getPublicKey())) { coreValidity = false; LOGGER.log(Level.INFO, SIGNATURE_NOT_VALID); } else { LOGGER.log(Level.INFO, String.format(SMEV_SIGNATURE_PASSED_CORE_VALIDATION)); } } catch (IOException e) { throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_IO_EXCEPTION + ExceptionUtils.getStackTrace(e)); } catch (ParserConfigurationException e) { throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_PARSER_CONFIGURATION_EXCEPTION + ExceptionUtils.getStackTrace(e)); } catch (SAXException e) { throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_SAX_EXCEPTION + ExceptionUtils.getStackTrace(e)); } catch (org.apache.xml.security.signature.XMLSignatureException e) { throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_XML_SIGNATURE_EXCEPTION + ExceptionUtils.getStackTrace(e)); } catch (XMLSecurityException e) { throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_XML_SECURITY_EXCEPTION + ExceptionUtils.getStackTrace(e)); } return coreValidity; 


Problems. Hash does not match


Attention!



For debugging, we used the example of the envelope SMEV 3 SendRequestRequestNoAttach.xml
The ds: Signature element was deleted from it with the goal of re-signing the message and checking it with the original.

Despite the fact that the signature method and the SmevTransformSpi transformation, taken from the Methodical Instructions, were worked out, the output was a signed document, which was interpreted as an online signature on the SMEV 3 portal.

VC-OB is not confirmed: VC check error: VC integrity is violated

Why

 <ds:DigestValue>e76oVeYGapFDE+PV6glsj0XDjLHydLMd0cSkFPY8fWk=</ds:DigestValue> 

did not coincide with the original example:

 <ds:DigestValue>/jXl70XwnttJB5sSokwh8SaVHwo2gjgILSu0qBaLUAo==</ds:DigestValue> 

To diagnose the causes, your XMLEventWriter has been added to the SmevTransformSpi class in the process method.

 ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLEventWriter bdst = outputFactory.get().createXMLEventWriter(baos, ENCODING_UTF_8); 

for parallel analysis of all stages of transformation.

The normalized XML element to which you want to sign was as follows:

 <ns1:SenderProvidedRequestData xmlns:ns1="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" Id="SIGNED_BY_CONSUMER"><ns1:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns1:MessageID><ns2:MessagePrimaryContent xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"><ns3:BreachRequest xmlns:ns3="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" Id="PERSONAL_SIGNATURE"><ns3:RequestedInformation><ns4:RegPointNum xmlns:ns4="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">78557</ns4:RegPointNum></ns3:RequestedInformation><ns3:Governance><ns4:Name> </ns4:Name><ns4:Code>GIBDD</ns4:Code><ns4:OfficialPerson><ns5:FamilyName xmlns:ns5="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1"></ns5:FamilyName><ns5:FirstName></ns5:FirstName><ns5:Patronymic></ns5:Patronymic></ns4:OfficialPerson></ns3:Governance></ns3:BreachRequest></ns2:MessagePrimaryContent><ns1:TestMessage></ns1:TestMessage></ns1:SenderProvidedRequestData> 

The search for a solution showed that, in the first place, the CryptoPro forum , a normalized document may actually look different and, accordingly, its hash will be different and possibly correct.

Secondly, it resulted in GitHub , where the older version of SmevTransformSpi class was laid out.

The old version of the transformation class has issued the following normalized document:

 <ns1:SenderProvidedRequestData xmlns:ns1="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" Id="SIGNED_BY_CONSUMER"><ns1:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns1:MessageID><ns2:MessagePrimaryContent xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"><ns3:BreachRequest xmlns:ns3="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" Id="PERSONAL_SIGNATURE"><ns3:RequestedInformation><ns4:RegPointNum xmlns:ns4="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">78557</ns4:RegPointNum></ns3:RequestedInformation><ns3:Governance><ns5:Name xmlns:ns5="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0"> </ns5:Name><ns6:Code xmlns:ns6="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">GIBDD</ns6:Code><ns7:OfficialPerson xmlns:ns7="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0"><ns8:FamilyName xmlns:ns8="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1"></ns8:FamilyName><ns9:FirstName xmlns:ns9="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1"></ns9:FirstName><ns10:Patronymic xmlns:ns10="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1"></ns10:Patronymic></ns7:OfficialPerson></ns3:Governance></ns3:BreachRequest></ns2:MessagePrimaryContent><ns1:TestMessage></ns1:TestMessage></ns1:SenderProvidedRequestData> 

With it, the hash began to match, and the signature successfully passed the validation.

Comparing the versions of the SmevTransformSpi class showed that in addition to the additional logging and diagnostic functions added in the new implementation in debug mode:

 if (logger.isDebugEnabled()) { debugStream = new DebugOutputStream(argDst); dst = outputFactory.get().createXMLEventWriter(debugStream, ENCODING_UTF_8); } else { dst = outputFactory.get().createXMLEventWriter(argDst, ENCODING_UTF_8); } 

The class from the Methodical Instructions does not contain the necessary line, or contains a typo:



Missing line:

 prefixMappingStack.pop(); 

which removes the first object from the prefixed stack

  Stack<List<Namespace>> prefixMappingStack = new Stack<List<Namespace>>(); 

, which led to incorrect operation of SmevTransformSpi.

Adding this line to the new version of SmevTransformSpi.java solved the problem.

A working transformation class and an envelope with a signature can be viewed at github.com/VBurmistrov/Smev3

results


The signing of envelopes SMEV 3 is successful.

Messages are checked on the portal of e-government services



And in its own application:

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


All Articles