powered by simpleCommunicator - 2.0.37     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Подписать SOAP-сообщение для СМЭВ
24 сообщений из 24, страница 1 из 1
Подписать SOAP-сообщение для СМЭВ
    #39225267
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте! Уже неделю бьюсь с этой задачей. Использовал https://habrahabr.ru/company/intersystems/blog/137145/, но хранилище типа "FloppyStore" на linux не подходит. Пробовал пересобрать библиотеку iscjcp.jar для "HDImagesStore" - вроде стало получаться (Хранилище видит), но вылетает
Код: plaintext
1.
2.
3.
4.
........... java.security.ProviderException
at ru.CryptoPro.JCP.KeyStore.u.g(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.u.b(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.engineGetKey(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.JCPKeyStore.engineGetKey(Unknown Source)
То ли КриптоПро неправильно настроена, то ли в коде ошибка.
Кто-нибудь реализовывал на Cache?
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39225309
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuctКто-нибудь реализовывал на Cache?
Да
KaIIIuctхранилище типа "FloppyStore" на linux не подходит. Пробовал пересобрать библиотеку iscjcp.jar для "HDImagesStore" - вроде стало получаться (Хранилище видит)

Тоже пересобирал iscjcp.jar (чтобы понимало не только FloppyStore). У нас всё работало. Ближе к вечеру, как будет свободное время, посмотрю подробнее чего и как. А может и раньше кто ответит.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39225329
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,
Заранее спасибо
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39226219
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuct,
По-моему менялись только два класса:
JcpFacade
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
package isc.jcp;

import java.util.*;

import java.io.IOException;

import org.w3c.dom.Element;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.xpath.XPathFactory;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.ws.security.WSSecurityException;

import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import com.objsys.asn1j.runtime.Asn1Exception;
//import javax.swing.JFrame;
//import javax.swing.JOptionPane;

/**
 * Фасад для работы с JCP из веб-сервисов Cache.
 */
public class JcpFacade
{
  private static final String ENVELOPE_NS_URI = "http://schemas.xmlsoap.org/soap/envelope/";
  private static final String WSSE_NS_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  private static final String DS_NS_URI = "http://www.w3.org/2000/09/xmldsig#";
  
  private static XPathFactory xpathFactory = XPathFactory.newInstance();

  /**
   * Формирует ЭЦП в формате XML Signature (ds:Signature).
   *
   * @param xmlFragmentBytes XML-документ, элемент которого подписывается; передается в виде массива байт в кодировке UTF-8
   * @param wsuId значение атрибута wsu:Id подписываемаего элемента
   * @param certFilename имя файла сертификата в формате X.509, соответствующего секретному ключу
   * @param keyPassword пароль для доступа к секретному ключу
   * @return Строка, содержащая XML-элемент ds:Signature.
   * @throws XMLSecurityException
   * @throws IOException
   * @throws CertificateException
   * @throws KeyStoreException
   * @throws NoSuchAlgorithmException
   * @throws UnrecoverableKeyException
   */
   public static String createSignature(byte[] xmlFragmentBytes, String wsuId, String certFilename, String keyPassword, String StoreName)
    throws XMLSecurityException, IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException
  {
    String xmlFragment = new String(xmlFragmentBytes, "UTF-8");
    
    
    JcpUtils.initJcp();
    if (StoreName == null)
    {
      throw new RuntimeException("Не задано имя хранилища");
    }
    //String storename = JcpUtils.getStoreName("c:\\store.cfg"); 
 
    //JcpUtils.ShowMessage(storename);
    
    KeyStore keyStore = JcpUtils.getFloppyStore(StoreName,keyPassword);
    if (keyStore == null)
    {
      throw new RuntimeException("Не удалось получить доступ к хранилищу ключей " + StoreName);
    }
    
    //Test(keyStore);
    
    //JcpUtils.ShowMessage("Получение сертификата");  
    X509Certificate certificate = JcpUtils.getCertificate(certFilename);
    if (certificate == null)
    {
    //    JcpUtils.ShowMessage("Не смогли получить");  
        throw new RuntimeException("Не найден сертификат");
    }
    //JcpUtils.ShowMessage("Получение закрытого ключа");  
    PrivateKey privateKey = getPrivateKey(keyStore, certificate, keyPassword, certFilename);
    if (privateKey == null)
    {
      throw new RuntimeException("Не найден закрытый ключ");
    }
    //JcpUtils.ShowMessage("Работа с xml");  
    Document document = XmlUtils.deserialize(xmlFragment);
    
    IdAttrResourceResolver resolver;
    synchronized(xpathFactory)
    {
      resolver = new IdAttrResourceResolver(xpathFactory);
    }
    
    Element signature = JcpUtils.signDocuments(
        document,
        new String[] {"#" + wsuId},
        resolver,
        certificate,
        privateKey);
   
    return XmlUtils.serializeNode(signature);
  }
   
  /**
   * Проверяет валидность ЭЦП для SOAP-сообщения.
   *
   * @param soapEnvelopeBytes подписанное SOAP-сообщение; передается в виде массива байт в кодировке UTF-8
   * @return Boolean
   * @throws XMLSecurityException
   * @throws IOException
   * @throws WSSecurityException
   * @throws CertificateException
   */
  public static Boolean verifySignature(byte[] soapEnvelopeBytes)
    throws XMLSecurityException, IOException, WSSecurityException, CertificateException
  {
    String soapEnvelope = new String(soapEnvelopeBytes, "UTF-8");
    
    //FileOutputStream f = new FileOutputStream("C://Temp//verifySignature.xml");
    //f.write(soapEnvelopeBytes);
    //f.flush();
  
    Document envelopeDocument = XmlUtils.deserialize(soapEnvelope);

    Element header = findSoapHeader(envelopeDocument);
    if (header == null)
      throw new RuntimeException("Не найден элемент SOAP Header");
    
    NodeList securityNL = header.getElementsByTagNameNS(WSSE_NS_URI, "Security");
    if (securityNL == null || securityNL.getLength() == 0)
    {
      throw new RuntimeException("Не найден элемент WS-Security");
    }
    
    IdAttrResourceResolver resolver;
    synchronized(xpathFactory)
    {
      resolver = new IdAttrResourceResolver(xpathFactory);
    }
    
    JcpUtils.initJcp();
    
    int signaturesVerified = 0;
    for (int i = 0; i < securityNL.getLength(); i++)
    {
      Element signature = getSignatureElement((Element)securityNL.item(i));
      if (signature == null) continue;
      
      if (!JcpUtils.verifySignature(signature, resolver))
      {
        signaturesVerified = -1;
        break;
      }
      
      signaturesVerified++;
    }
    
    if (signaturesVerified == 0)
    {
      throw new RuntimeException("Не найден элемент WS-Security, содержащий элемент Signature");
    }
    
    return Boolean.valueOf(signaturesVerified > -1);
  }
  
  private static Element findSoapHeader(Document envelopeDocument)
  {
    Element header = null;
    Element envelope = envelopeDocument.getDocumentElement();
    
    if (!"Envelope".equals(envelope.getLocalName()) || !ENVELOPE_NS_URI.equals(envelope.getNamespaceURI()))
      throw new RuntimeException("Не найден элемент SOAP Envelope");
    
    Element body = XmlUtils.getFirstChildElement(envelope);
    if (body == null || !ENVELOPE_NS_URI.equals(body.getNamespaceURI()))
      throw new RuntimeException("Не найдены элементы SOAP Header / SOAP Body");
    
    if ("Header".equals(body.getLocalName()))
    {
      header = body;
      body = XmlUtils.getNextChildElement(envelope, header);
      if (body == null || !ENVELOPE_NS_URI.equals(body.getNamespaceURI()))
        throw new RuntimeException("Не найден элемент SOAP Body");
    }

    if (!"Body".equals(body.getLocalName()))
      throw new RuntimeException("Не найден элемент SOAP Body");
    
    return header;
  }
  
  private static Element getSignatureElement(Element security)
  {
    NodeList sigNL = security.getElementsByTagNameNS(DS_NS_URI, "Signature");
    if (sigNL == null || sigNL.getLength() == 0)
    {
      return null;
    }
    else if (sigNL.getLength() > 1)
    {
      throw new RuntimeException("Найдено несколько элементов Signature в рамках одного элемента Security");
    }
    else
    {
      return (Element)sigNL.item(0);
    }
  }
  
  private static PrivateKey getPrivateKey(KeyStore keyStore, X509Certificate certificate, String password, String certFilename)
    throws KeyStoreException, CertificateEncodingException, NoSuchAlgorithmException, UnrecoverableKeyException
  {
    PrivateKey result = null;
    
    Enumeration aliases = keyStore.aliases();
    String alias = JcpUtils.getAlias(certFilename);
    if (alias == null) {
        while (aliases.hasMoreElements())
        {
          alias = (String)aliases.nextElement();

          if (keyStore.isKeyEntry(alias))
          {
            Key key = getKey(keyStore, alias, password);
            if (key instanceof PrivateKey)
            {
              result = (PrivateKey)key;
              X509Certificate floppyCertificate = (X509Certificate)keyStore.getCertificate(alias);

              if (floppyCertificate != null)
              {
                if (Arrays.equals(certificate.getEncoded(), floppyCertificate.getEncoded()))
                  return result;
                else
                  result = null;
              }
            }
          }
        }
    }
    else 
    {
      if (keyStore.isKeyEntry(alias))
      {
        Key key = getKey(keyStore, alias, password);
        if (key instanceof PrivateKey)
        {
          result = (PrivateKey)key;
          X509Certificate floppyCertificate = (X509Certificate)keyStore.getCertificate(alias);

          if (floppyCertificate != null)
          {
            if (Arrays.equals(certificate.getEncoded(), floppyCertificate.getEncoded()))
              return result;
            else
              result = null;
          }
        }
      }
    }
    
    if ((keyStore.size() == 1) && (result != null))
      return result;
    else   
      return null;
  }
  
private static Key getKey(KeyStore keyStore, String Alias, String Password) 
        throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException
{
    Key key;
    
    if (Password != null)
    {
      key = keyStore.getKey(Alias, Password.toCharArray());
    }
    else
    {
      key = keyStore.getKey(Alias, null);
    }
    return key;
}
/**
   * Формирует ЭЦП для произвольного массива байт.
   *
   * @param data подписываемый массив байт
   * @param certFilename имя файла сертификата в формате X.509, соответствующего секретному ключу
   * @param keyPassword пароль для доступа к секретному ключу
   * @return ЭЦП
   * @throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, SignatureException, Asn1Exception, CertificateEncodingException, InvalidKeyException
   */
  public static byte[] createCMSSignature(byte[] data, String certFilename, String keyPassword, String StoreName)
    throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, SignatureException, Asn1Exception, CertificateEncodingException, InvalidKeyException
  {
    JcpUtils.initJcp();
    
    if (StoreName == null)
    {
      throw new RuntimeException("Не задано имя хранилища");
    }
    //String StoreName = JcpUtils.getStoreName("c:\\store.cfg"); 
    KeyStore keyStore = JcpUtils.getFloppyStore(StoreName, keyPassword);
    if (keyStore == null) throw new RuntimeException("Не удалось получить доступ к хранилищу ключей "+StoreName);
    
    X509Certificate certificate = JcpUtils.getCertificate(certFilename);
    if (certificate == null) throw new RuntimeException("Не найден сертификат");
    
    PrivateKey privateKey = getPrivateKey(keyStore, certificate, keyPassword, certFilename);
    if (privateKey == null) throw new RuntimeException("Не найден закрытый ключ");
    
    return JcpUtils.createCMS(data, new PrivateKey[] { privateKey }, new Certificate[] { certificate }, true);
  }
  
  /**
   * Проверка CMS подписи массива байт.
   *
   * @param cmsBytes CMS подпись
   * @param data подписанные данные; null = поверяются подписанные данные, содержащиеся внутри CMS; если имеются вложенные в CMS подписанные данные, то data игнорируется
   * @param certFilename имя файла сертификата в формате X.509; null = использовать сертификат, содержащийся в CMS; если имеются вложенные в CMS сертификаты, то certFilename игнорируется
   * @return верна ли подпись
   * @throws IOException, SignatureException, Asn1Exception, NoSuchAlgorithmException, InvalidKeyException, CertificateException, KeyStoreException
   */
  public static Boolean verifyCMSSignature(byte[] cmsBytes, byte[] data, String certFilename)
    throws IOException, SignatureException, Asn1Exception, NoSuchAlgorithmException, InvalidKeyException, CertificateException, KeyStoreException
  {
    X509Certificate certificate = null;
    if (certFilename != null)
    {
      certificate = JcpUtils.getCertificate(certFilename);
      if (certificate == null) {
            throw new RuntimeException("Не найден сертификат");
        }
    }
    
    JcpUtils.initJcp();
    
    return Boolean.valueOf(JcpUtils.verifyCMS(cmsBytes, certificate == null ? null : new Certificate[] { certificate }, data));
  }  
  /**

   */
  public static byte[] getDigest(byte[] data) 
          throws IOException, NoSuchAlgorithmException
  {  
    JcpUtils.initJcp(); 
    return JcpUtils.getDigest(data);
  }
}


и
JcpUtils
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
package isc.jcp;

import java.util.*;
import java.io.*;

import org.w3c.dom.Element;
import org.w3c.dom.Document;

import java.security.DigestInputStream;
import java.security.Security;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.MessageDigest;
import java.security.Signature;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;

import org.apache.xml.security.Init;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.transforms.Transforms;

import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.message.token.X509Security;
import org.apache.ws.security.WSSecurityException;

import ru.CryptoPro.JCP.JCP;
import ru.CryptoPro.JCP.params.OID;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.CMSVersion;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.CertificateChoices;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.CertificateSet;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.ContentInfo;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.DigestAlgorithmIdentifier;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.DigestAlgorithmIdentifiers;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.EncapsulatedContentInfo;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.IssuerAndSerialNumber;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.SignatureAlgorithmIdentifier;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.SignatureValue;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.SignedData;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.SignerIdentifier;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.SignerInfo;
import ru.CryptoPro.JCP.ASN.CryptographicMessageSyntax.SignerInfos;
import ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Attribute;
import ru.CryptoPro.JCP.ASN.PKIX1Explicit88.CertificateSerialNumber;
import ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Name;
import ru.CryptoPro.JCP.tools.Array;

import com.objsys.asn1j.runtime.Asn1Type;
import com.objsys.asn1j.runtime.Asn1BerDecodeBuffer;
import com.objsys.asn1j.runtime.Asn1BerEncodeBuffer;
import com.objsys.asn1j.runtime.Asn1Null;
import com.objsys.asn1j.runtime.Asn1ObjectIdentifier;
import com.objsys.asn1j.runtime.Asn1OctetString;
import com.objsys.asn1j.runtime.Asn1Exception;
import java.security.UnrecoverableKeyException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

/**
 * Контейнер для полезных методов работы с КриптоПро JCP.
 */
public class JcpUtils
{
  /** Алгоритм подписи (ГОСТ Р 34.10-2001) **/
  public static final String signMethod = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411";

  /** Алгоритм хеширования, используемый при подписи (ГОСТ Р 34.11-94) **/
  public static final String digestMethod = "http://www.w3.org/2001/04/xmldsig-more#gostr3411"; 

  private static final String STR_CMS_OID_SIGNED = "1.2.840.113549.1.7.2";
  private static final String DIGEST_OID = JCP.GOST_DIGEST_OID;
  private static final String STR_CMS_OID_DATA = "1.2.840.113549.1.7.1";
  private static final String SIGN_OID = JCP.GOST_EL_KEY_OID;
  private static final String STR_CMS_OID_CONT_TYP_ATTR = "1.2.840.113549.1.9.3";
  private static final String STR_CMS_OID_DIGEST_ATTR = "1.2.840.113549.1.9.4";
  private static final String DIGEST_ALG_NAME = JCP.GOST_DIGEST_NAME;
  
  /** Хранилище ключей типа FloppyStore **/
  private static KeyStore floppyStore;
  
  /** Кэш сертификатов **/
  private static Map certificates = new HashMap();
  
  /** Фабрика сертификатов **/
  private static CertificateFactory certificateFactory;

  /**
   * Инициализирует JCP и XML Security.
   */
  public synchronized static void initJcp()
  {
    ru.CryptoPro.JCP.JCP jcp = new ru.CryptoPro.JCP.JCP();
    if (Security.getProvider(jcp.getName()) == null)
    {
      Security.addProvider(jcp);
    }
    
    if (!ru.CryptoPro.JCPxml.xmldsig.JCPXMLDSigInit.isInitialized())
    {
      ru.CryptoPro.JCPxml.xmldsig.JCPXMLDSigInit.init();
    }
    
    if (!Init.isInitialized())
    {
      Init.init();
    }
  }
  /*
   * Вернет имя хранилищиа
   */
  public static String getStoreName(String file)
    throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException
  {
      String str = "";
      try {
        BufferedReader in = new BufferedReader(new FileReader(file));
        while ((str = in.readLine()) != null) {            
            //JOptionPane.showMessageDialog(frame, str);
            if (!"".equals(str)) {
                break;
            }
        }
        in.close();
    } catch (IOException e) {}
    if ("".equals(str)) {
            str = "FloppyStore";
    } 
    //JOptionPane.showMessageDialog(frame, str);
    return str;
  }
  /**
   * Возвращает ссылку на хранилище ключей FloppyStore.
   *
   * @return KeyStore
   * @throws IOException
   * @throws CertificateException
   * @throws KeyStoreException
   * @throws NoSuchAlgorithmException
   */
  public static KeyStore getFloppyStore(String StoreName, String keyPassword )
    throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException
  {
    if (floppyStore == null)
      initFloppyStore(StoreName, keyPassword);
    
    return floppyStore;
  }

  /**
   * Инициализирует хранилище ключей FloppyStore.
   *
   * @throws IOException
   * @throws CertificateException
   * @throws KeyStoreException
   * @throws NoSuchAlgorithmException
   */
  private synchronized static void initFloppyStore(String StoreName, String keyPassword )
    throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException
  {
    floppyStore = KeyStore.getInstance(StoreName);
    if (floppyStore != null)
    {
        if (keyPassword == null) {
            floppyStore.load(null, null);
        }
        else {
            floppyStore.load(null, keyPassword.toCharArray());            
        }
        
    }
    
   /*   
      */
  }
  
  /**
   * Загружает сертификат в формате X.509 из потока.
   *
   * @param is поток, содержащий сертификат в формате X.509
   * @return X509Certificate
   * @throws CertificateException
   */
  public synchronized static X509Certificate getCertificate(InputStream is)
    throws CertificateException
  {
    if (certificateFactory == null)
      certificateFactory = CertificateFactory.getInstance("X.509");
      
    X509Certificate cert = null;
    try
    {
      cert = (X509Certificate)certificateFactory.generateCertificate(new BufferedInputStream(is));
    }
    finally
    {
      try
      {
        is.close();
      }
      catch (IOException ignore)
      {}
    }
    return cert;
  }

  /**
   * Загружает сертификат в формате X.509 из файла. Использует кэш сертификатов.
   *
   * @param file имя файла, содержащего сертификат в формате X.509
   * @return X509Certificate
   * @throws FileNotFoundException
   * @throws CertificateException
   */
  public synchronized static X509Certificate getCertificate(String file)
    throws CertificateException, KeyStoreException, UnsupportedEncodingException
  {
      X509Certificate cert = null;
      if (file != null) {
          String alias = getAlias(file);
          if (alias == null) { 
            try {
              FileInputStream ifStream = new FileInputStream(file);
              if (certificates.containsKey(file)) {
                    return (X509Certificate)certificates.get(file);
                }
              cert = getCertificate(ifStream);
            }
            catch(FileNotFoundException ignore)
            { }
            if (cert != null) {
                certificates.put(file, cert);
                return cert;
            }
          }
          else {
              cert = (X509Certificate) floppyStore.getCertificate(alias); 
          }
      }
    return cert;
  }

  // Получить алиас
public static String getAlias(String fileoralias) 
        throws KeyStoreException
{
    if (fileoralias == null) return null;
    Enumeration aliasesEnum = floppyStore.aliases();
    String result = null;
    while (aliasesEnum.hasMoreElements()) {        
          String alias = aliasesEnum.nextElement().toString();                          
          if (alias.indexOf(fileoralias)!= -1) {
              result = alias;
              break;
        }
    }
    return result;
}
 // Просто функция ShowMessage
 public static void ShowMessage(String Message)
 {
    JFrame frame=new JFrame();
    JOptionPane.showMessageDialog(frame, Message);  
 }
  /**
   * Проверяет валидность ЭЦП.
   *
   * @param signatureElement XML-элемент ds:Signature
   * @param resourceResolver реализация <code>org.apache.xml.security.utils.resolver.ResourceResolverSpi</code>, используемая при проверке подписи
   * @return boolean
   * @throws XMLSecurityException
   * @throws WSSecurityException
   * @throws CertificateException
   */
  public static boolean verifySignature(Element signatureElement, ResourceResolverSpi resourceResolver)
    throws XMLSecurityException, WSSecurityException, CertificateException
  {
    XMLSignature signature = new XMLSignature(signatureElement, "");
    if (signature.getSignedInfo().getLength() == 0)
      throw new RuntimeException("No signed resources");
    
    signature.addResourceResolver(resourceResolver);

    KeyInfo ki = signature.getKeyInfo();
    if (ki == null) 
      throw new RuntimeException("KeyInfo element not found");
    else if (ki.isEmpty()) 
      throw new RuntimeException("Empty KeyInfo element");
    else if (ki.containsX509Data())
      return signature.checkSignatureValue(ki.getX509Certificate());
    else if (ki.getPublicKey() != null)
      return signature.checkSignatureValue(ki.getPublicKey());
    
    // далее - сложный случай
    Element kiChild = XmlUtils.getFirstChildElement(ki.getElement());
    if (kiChild == null) throw new RuntimeException("Empty KeyInfo element");
    
    SecurityTokenReference tref = new SecurityTokenReference(kiChild);
    if (!tref.containsReference() || (tref.getReference() == null))
      throw new RuntimeException("SecurityTokenReference does not contain a direct reference (i.e. <wsse:Reference> element)");
    else if (!X509Security.X509_V3_TYPE.equals(tref.getReference().getValueType()))
      throw new RuntimeException("Reference value type \"" + tref.getReference().getValueType() + "\" is not supported");
      
    Element tokenEl = tref.getTokenElement(signatureElement.getOwnerDocument(), new WSDocInfo(signatureElement.getOwnerDocument()), null);
    X509Security token = new X509Security(tokenEl);
    X509Certificate cert = getCertificate(new ByteArrayInputStream(token.getToken()));
    
    return signature.checkSignatureValue(cert);
  }
  
  /**
   * Формирует ЭЦП в формате XML Signature (ds:Signature).
   *
   * @param targetDoc XML-документ (DOM), элементы которого подписываются
   * @param uris массив ссылок (URI) на подписываемые элементы
   * @param resourceResolver реализация <code>org.apache.xml.security.utils.resolver.ResourceResolverSpi</code>, используемая при формировании подписи
   * @param certificate сертификат в формате X.509, соответствующий секретному ключу, используемому при формировании подписи
   * @param privateKey секретный ключ, используемый при формировании подписи
   * @return XML-элемент ds:Signature
   * @throws XMLSecurityException
   */
  public static Element signDocuments(Document targetDoc, String[] uris, ResourceResolverSpi resourceResolver, X509Certificate certificate, PrivateKey privateKey)
    throws XMLSecurityException
  {
    XMLSignature sig = new XMLSignature(targetDoc, "", signMethod, Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

    Transforms transforms = new Transforms(targetDoc);
    transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
    
    for (int i = 0; i < uris.length; i++)
      sig.addDocument(uris[i], transforms, digestMethod);

    sig.getSignedInfo().addResourceResolver(resourceResolver);

    sig.addKeyInfo(certificate);
    sig.sign(privateKey);
    
    return sig.getElement();
  }
  
  /**
   * Формирует ЭЦП для произвольного массива байт.
   *
   * @param data подписываемый массив байт
   * @param keys массив секретных ключей, используемый при формировании подписи
   * @param certs массив сертификатов в формате X.509, соответствующий массиву секретных ключей
   * @param detached признак необходимости создания detached ЭЦП - см. http://notary.cryptopro.ru/Notary_Help.htm
   * @return ЭЦП
   * @throws IOException, SignatureException, Asn1Exception, CertificateEncodingException, NoSuchAlgorithmException, InvalidKeyException
   */
   public static byte[] createCMS(byte[] data, PrivateKey[] keys, Certificate[] certs, boolean detached)
    throws IOException, SignatureException, Asn1Exception, CertificateEncodingException, NoSuchAlgorithmException, InvalidKeyException
  {
    //create CMS
    final SignedData cms = new SignedData();
    cms.version = new CMSVersion(1);

    final ContentInfo all = new ContentInfo();
    all.contentType = new Asn1ObjectIdentifier(new OID(STR_CMS_OID_SIGNED).value);
    all.content = cms;
    
    // digest
    final DigestAlgorithmIdentifier a = new DigestAlgorithmIdentifier(new OID(DIGEST_OID).value);
    a.parameters = new Asn1Null();
    cms.digestAlgorithms = new DigestAlgorithmIdentifiers(1);
    cms.digestAlgorithms.elements[0] = a;
    
    if (detached)
      cms.encapContentInfo = new EncapsulatedContentInfo(new Asn1ObjectIdentifier(new OID(STR_CMS_OID_DATA).value), null);
    else
      cms.encapContentInfo = new EncapsulatedContentInfo(new Asn1ObjectIdentifier(new OID(STR_CMS_OID_DATA).value), new Asn1OctetString(data));

    // certificates
    final int ncerts = certs.length;
    cms.certificates = new CertificateSet(ncerts);
    cms.certificates.elements = new CertificateChoices[ncerts];
    for (int i = 0; i < cms.certificates.elements.length; i++)
    {
      final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate = new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
      final Asn1BerDecodeBuffer decodeBuffer = new Asn1BerDecodeBuffer(certs[i].getEncoded());
      certificate.decode(decodeBuffer);
      cms.certificates.elements[i] = new CertificateChoices();
      cms.certificates.elements[i].set_certificate(certificate);
    }
    
    // Signature.getInstance
    final Signature signature = Signature.getInstance(JCP.GOST_EL_SIGN_NAME);
    byte[] sign;
    
    // signer infos
    final int nsign = keys.length;
    cms.signerInfos = new SignerInfos(nsign);
    for (int i = 0; i < cms.signerInfos.elements.length; i++)
    {
      signature.initSign(keys[i]);
      signature.update(data);
      sign = signature.sign();

      final CertificateSerialNumber num = new CertificateSerialNumber(((X509Certificate)certs[i]).getSerialNumber());
      final byte[] encodedName = ((X509Certificate)certs[i]).getIssuerX500Principal().getEncoded();
      final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
      final Name name = new Name();
      name.decode(nameBuf);

      cms.signerInfos.elements[i] = new SignerInfo();
      cms.signerInfos.elements[i].version = new CMSVersion(1);
      cms.signerInfos.elements[i].sid = new SignerIdentifier();
      cms.signerInfos.elements[i].sid.set_issuerAndSerialNumber(new IssuerAndSerialNumber(name, num));
      cms.signerInfos.elements[i].digestAlgorithm = new DigestAlgorithmIdentifier(new OID(DIGEST_OID).value);
      cms.signerInfos.elements[i].digestAlgorithm.parameters = new Asn1Null();
      cms.signerInfos.elements[i].signatureAlgorithm = new SignatureAlgorithmIdentifier(new OID(SIGN_OID).value);
      cms.signerInfos.elements[i].signatureAlgorithm.parameters = new Asn1Null();
      cms.signerInfos.elements[i].signature = new SignatureValue(sign);
    }
    
    // encode
    final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();
    all.encode(asnBuf, true);
    
    return asnBuf.getMsgCopy();
  }
  
  /**
   * Проверка CMS подписи массива байт.
   *
   * @param cmsBytes CMS подпись
   * @param certs массив сертификатов в формате X.509; null = использовать сертификат, содержащийся в CMS; если имеются вложенные в CMS сертификаты, то certs игнорируется
   * @param data подписанные данные; null = поверяются подписанные данные, содержащиеся внутри CMS; если имеются вложенные в CMS подписанные данные, то data игнорируется
   * @return верна ли подпись
   * @throws IOException, SignatureException, Asn1Exception, NoSuchAlgorithmException, InvalidKeyException, CertificateException
   */
  public static boolean verifyCMS(byte[] cmsBytes, Certificate[] certs, byte[] data)
    throws IOException, SignatureException, Asn1Exception, NoSuchAlgorithmException, InvalidKeyException, CertificateException
  {
    int validsign = 0;
    
    final Asn1BerDecodeBuffer asnBuf = new Asn1BerDecodeBuffer(cmsBytes);
    final ContentInfo all = new ContentInfo();
    all.decode(asnBuf);
    if (!new OID(STR_CMS_OID_SIGNED).eq(all.contentType.value)) throw new RuntimeException("Формат подписи не поддерживается");
    
    final SignedData cms = (SignedData)all.content;
    
    final byte[] text;
    if (cms.encapContentInfo.eContent != null)
      text = cms.encapContentInfo.eContent.value;
    else if (data != null)
      text = data;
    else
      throw new RuntimeException("Нет данных для проверки подписи");
      
    OID digestOid = null;
    final DigestAlgorithmIdentifier digestAlgorithmIdentifier = new DigestAlgorithmIdentifier(new OID(DIGEST_OID).value);
    for (int i = 0; i < cms.digestAlgorithms.elements.length; i++)
    {
      if (cms.digestAlgorithms.elements[i].algorithm.equals(digestAlgorithmIdentifier.algorithm))
      {
        digestOid = new OID(cms.digestAlgorithms.elements[i].algorithm.value);
        break;
      }
    }
    if (digestOid == null) throw new RuntimeException("Неизвестный дайджест");
    
    final OID eContTypeOID = new OID(cms.encapContentInfo.eContentType.value);
    if (cms.certificates != null)
    {
      //Проверка на вложенных сертификатах
      for (int i = 0; i < cms.certificates.elements.length; i++)
      {
        final Asn1BerEncodeBuffer encBuf = new Asn1BerEncodeBuffer();
        cms.certificates.elements[i].encode(encBuf);

        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final X509Certificate cert = (X509Certificate)cf.generateCertificate(encBuf.getInputStream());

        for (int j = 0; j < cms.signerInfos.elements.length; j++)
        {
          final SignerInfo info = cms.signerInfos.elements[j];
          if (!digestOid.equals(new OID(info.digestAlgorithm.algorithm.value))) throw new RuntimeException("Подпись не соответствует сертификату");
          final boolean checkResult = verifyOnCert(cert, cms.signerInfos.elements[j], text, eContTypeOID);
          if (checkResult) validsign += 1;
        }
      }
    }
    else if (certs != null)
    {
      //Проверка на указанных сертификатах
      for (int i = 0; i < certs.length; i++)
      {
        final X509Certificate cert = (X509Certificate)certs[i];
        for (int j = 0; j < cms.signerInfos.elements.length; j++)
        {
          final SignerInfo info = cms.signerInfos.elements[j];
          if (!digestOid.equals(new OID(info.digestAlgorithm.algorithm.value))) throw new RuntimeException("Подпись не соответствует сертификату");
          final boolean checkResult = verifyOnCert(cert, cms.signerInfos.elements[j], text, eContTypeOID);
          if (checkResult) validsign += 1;
        }
      }
    }
    else
    {
       // Certificates for validation not found
    }
    
    return (cms.signerInfos.elements.length == validsign);
  }
  
  /**
   * Попытка проверки подписи на указанном сертификате
   *
   * @param cert сертификат для проверки
   * @param text текст для проверки
   * @param info подпись
   * @param eContentTypeOID
   * @return верна ли подпись
   * @throws IOException, SignatureException, Asn1Exception, NoSuchAlgorithmException, InvalidKeyException
   */
  private static boolean verifyOnCert(X509Certificate cert, SignerInfo info, byte[] text, OID eContentTypeOID)
    throws IOException, SignatureException, Asn1Exception, NoSuchAlgorithmException, InvalidKeyException
  {
    //подпись
    final byte[] sign = info.signature.value;
    
    //данные для проверки подписи
    final byte[] data;
    if (info.signedAttrs == null)
    {
      //аттрибуты подписи отсутствуют
      data = text;
    }
    else
    {
      //присутствуют аттрибуты подписи (SignedAttr)
      final Attribute[] signAttrElem = info.signedAttrs.elements;

      //проверка аттрибута content-type
      final Asn1ObjectIdentifier contentTypeOid = new Asn1ObjectIdentifier((new OID(STR_CMS_OID_CONT_TYP_ATTR)).value);
      Attribute contentTypeAttr = null;
      for (int r = 0; r < signAttrElem.length; r++)
      {
        final Asn1ObjectIdentifier oid = signAttrElem[r].type;
        if (oid.equals(contentTypeOid)) contentTypeAttr = signAttrElem[r];
      }

      if (contentTypeAttr == null)
        throw new RuntimeException("Отсутствует атрибут, отвечающий за структуру подписи");

      if (!contentTypeAttr.values.elements[0].equals(new Asn1ObjectIdentifier(eContentTypeOID.value)))
        throw new RuntimeException("Недопустимая структура подписи");

      //проверка аттрибута message-digest
      final Asn1ObjectIdentifier messageDigestOid = new Asn1ObjectIdentifier((new OID(STR_CMS_OID_DIGEST_ATTR)).value);
      Attribute messageDigestAttr = null;
      for (int r = 0; r < signAttrElem.length; r++)
      {
        final Asn1ObjectIdentifier oid = signAttrElem[r].type;
        if (oid.equals(messageDigestOid)) messageDigestAttr = signAttrElem[r];
      }
      if (messageDigestAttr == null)
        throw new RuntimeException("Не найдено значение дайджеста");

      //вычисление messageDigest
      final ByteArrayInputStream stream = new ByteArrayInputStream(text);
      final MessageDigest digest = MessageDigest.getInstance(DIGEST_ALG_NAME);
      final DigestInputStream digestStream = new DigestInputStream(stream, digest);
      while (digestStream.available() != 0)
        digestStream.read();
        
      final Asn1Type open = messageDigestAttr.values.elements[0];
      final Asn1OctetString hash = (Asn1OctetString)open;
      if (!Array.toHexString(digest.digest()).equals(Array.toHexString(hash.value)))
        throw new RuntimeException("Недопустимое значение дайджеста");

      //данные для проверки подписи
      final Asn1BerEncodeBuffer encBufSignedAttr = new Asn1BerEncodeBuffer();
      info.signedAttrs.encode(encBufSignedAttr);
      data = encBufSignedAttr.getMsgCopy();
    }

    // проверка подписи
    final Signature signature = Signature.getInstance(JCP.GOST_EL_SIGN_NAME);
    signature.initVerify(cert);
    signature.update(data);
    
    return signature.verify(sign);
  }
  
public static byte[] getBytesFromFile(File file) throws IOException {
    InputStream is = new FileInputStream(file);
    long length = file.length();
    if (length > Integer.MAX_VALUE) {
        return null;
    }
 
    byte[] bytes = new byte[(int)length];
 
    // Read in the bytes
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
        offset += numRead;
    }
 
    // Ensure all the bytes have been read in
    if (offset < bytes.length) {
        throw new IOException("Could not completely read file "+file.getName());
    }
 
    // Close the input stream and return bytes
    is.close();
    return bytes;
}

    /**
     * Метод печатает список алиасов
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws UnrecoverableKeyException
     */
    public static void prnListAlias(String StoreName, String keyPassword) 
           throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, IOException, CertificateException
  {
      initJcp();
      getFloppyStore(StoreName,keyPassword);
      try {
      Enumeration aliases = floppyStore.aliases();
        while (aliases.hasMoreElements())
        {
          String alias = (String)aliases.nextElement();
          System.out.print("alias: " + alias);
          System.out.println("");
        }
      } 
      catch (Exception ex) {} 
      floppyStore = null;
  }
    /**
     * Метод возвращает значение хеш для строки text
     * @param text принимает входную строку, для которой необходимо вычислить хеш
     * @return возвращает хеш
     */
    public static byte[] getDigest(byte[] text) 
            throws IOException, NoSuchAlgorithmException
    {
        //вычисление messageDigest
      final ByteArrayInputStream stream = new ByteArrayInputStream(text);
      final MessageDigest digest;
        digest = MessageDigest.getInstance(DIGEST_ALG_NAME);
      final DigestInputStream digestStream;
        digestStream = new DigestInputStream(stream, digest);
      while (digestStream.available() != 0) {
            digestStream.read();
        }
        
      //final Asn1Type open = messageDigestAttr.values.elements[0];
      //final Asn1OctetString hash = (Asn1OctetString)open;
      //if (!Array.toHexString(digest.digest()).equals(Array.toHexString(hash.value)))
       // throw new RuntimeException("Недопустимое значение дайджеста");
      return digest.digest();
      //return Array.toHexString(digest.digest());
    }
}



Соответственно потом проекции классов незабыть перегенерить.
Основное изменение:
String createSignature(byte[] xmlFragmentBytes, String wsuId, String certFilename, String keyPassword, String StoreName)
Может принимать имя хранилища (StoreName, не только FloppyStore) и путь к файлу сертификата или имя алиаса (certFilename).
Как то так...
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39226279
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Спасибо большое,будем пробовать
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39226351
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: java
1.
2.
3.
4.
5.
6.
7.
	... java.security.ProviderException
	at ru.CryptoPro.JCP.KeyStore.u.g(Unknown Source)
	at ru.CryptoPro.JCP.KeyStore.u.b(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:804)
	at isc.jcp.JcpFacade.getKey(JcpFacade.java:287)



Тоже самое вываливается. Все делали также как описано на хабре?
Ощущение что криптопро неправильно настроена.
Не может получить ключ - сертификат,хранилище,алиас все видит.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39226432
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuct,
Я бы с этой ошибкой пошел спрашивать туда Форум КриптоПро . Больше шансов получить полезный ответ :)
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39226609
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Да и там тоже тему завел. Спасибо
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39226735
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Напишите пожалуйста какую версию Java и КриптоПро использовали
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234248
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuct,

Да по-моему, как в статье была jdk1.6.0_20, такую и использовали. А JCP, то ли 1.0.52, то ли 1.0.53.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234377
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Ошибка при подписании выходит:
Код: java
1.
2.
3.
4.
ОШИБКА #5023: Ошибка Java-шлюза: java.lang.NullPointerException
	at isc.jcp.XmlUtils.serializeNode(XmlUtils.java:51)
	at isc.jcp.XmlUtils.serializeNode(XmlUtils.java:38)
	at isc.jcp.JcpFacade.createSignature(JcpFacade.java:111)



Верификация успешно отрабатывает.Ключи,хранилище,сертификат - все видит
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234381
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
этот метод возвращает null
Код: java
1.
2.
3.
4.
5.
JcpUtils.signDocuments
...
    Transforms transforms = new Transforms(targetDoc);
    transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
...



Используется xmlsec-1.4.3 может и в этом дело - сейчас попробую xmlsec-1.4.6
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234390
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нет, дело не в xmlsec
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234488
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дело в этом:
Код: java
1.
XmlUtils.deserialize(xmlFragment);

Возвращает null (пустой документ). Борюсь

Помогите ребята пожалуйста, неужели никто со СМЭВ не работал?
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234494
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KaIIIuct,
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
  public static Document deserialize(String paramString)
  {
    return deserialize(new StringReader(paramString));
  }
  
  public static Document deserialize(Reader paramReader)
  {
    DocumentBuilder localDocumentBuilder;
    try
    {
      synchronized (documentBuilderFactory)
      {
        localDocumentBuilder = documentBuilderFactory.newDocumentBuilder();
      }
    }
    catch (ParserConfigurationException localParserConfigurationException)
    {
      throw new RuntimeException(localParserConfigurationException);
    }
    return deserialize(localDocumentBuilder, paramReader);
  }
  
  public static Document deserialize(DocumentBuilder paramDocumentBuilder, Reader paramReader)
  {
    Document localDocument = null;
    try
    {
      localDocument = paramDocumentBuilder.parse(new InputSource(paramReader));
    }
    catch (SAXException localSAXException)
    {
      throw new RuntimeException(localSAXException);
    }
    catch (IOException localIOException)
    {
      throw new RuntimeException(localIOException);
    }
    return localDocument;
  }

...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234797
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, потратил немного времени и настроил всё с нуля.

- Нашел у себя виртуалку с убунту на которой стояла Cache:
Код: powershell
1.
2.
cat /proc/version
Linux version 3.13.0-32-generic (buildd@roseapple) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #57-Ubuntu SMP Tue Jul 15 03:51:12 UTC 2014

Код: plaintext
1.
w $zv
Cache for UNIX (SUSE Linux Enterprise Server for x86-32) 2014.1.2 (Build 753U) Tue Jul 22 2014 10:58:32 EDT
- Сходил на Oracle Java Archive и скачал jre1.6.0_20 (jre-6u20-linux-i586.bin в моём случае).
Яву поставил в /opt/java/jre1.6.0_20

- Взял имевшийся у меня дистрибутив CryptoPRO JCP (jcp.1.0.52).
Криптопро распаковал в /opt/JCP

- запустил инсталлятор криптопро:
Код: powershell
1.
sh ./install.sh /opt/java/jre1.6.0_20 00000-00000-00000-00000-00000

(соответственно вместо нулей реальный ключ).

- скопировал в папку /opt/java/jre1.6.0_2/lib/ext дополнительные файлы:
commons-logging-1.1.1.jar, wss4j-1.6.3.jar, xmlsec-1.4.6.jar ну и модернизированный iscjcp.jar

- Добавил новую запись в таблицу %Net_Remote.ObjectGateway в области %SYS:
Код: plaintext
1.
insert into %Net_Remote.ObjectGateway(Name, Type, Server, Port, JavaHome) 
values ('JCPGate', '1', '127.0.0.1', '55555', '/opt/java/jre1.6.0_20')
- Запускаем шлюз:
Код: plaintext
1.
>w ##class(%Net.Remote.Service).StartGateway("JCPGate")
1
- и сгенерим проекцию для ява класса:
Код: plaintext
>d ##class(%Net.Remote.Java.JavaGateway).%ExpressImport("isc.jcp.JcpFacade", "55555")
- Далее, в классе smev.JcpUtils прописываем параметры, у меня так (есть доп. параметры PASSWORD и STORENAME):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
/// Контейнер для методов, используемых при работе с КриптоПро JCP
Class smev.JcpUtils
{

/// Порт, на котором запущен Java-gateway
Parameter JAVAGATEWAYPORT = 55555;

/// Адрес сервера, на котором запущен Java-gateway
Parameter JAVAGATEWAYSERVER = "127.0.0.1";

/// Имя файла сертификата или название контейнера (можно посмотреть в панеле управления CryptoPro JCP)
Parameter CERTFILENAME = "название_контейнера";

/// Пароль к хранилищу
Parameter PASSWORD = "пароль";

/// OCFStore - eToken
/// RutokenStore - ruToken
/// FloppyStore - floppy drive disc
Parameter STORENAME = "FloppyStore";

...
- Затем, функция createSignature в классе smev.JcpUtils, она немного модернизирована (добавлено использование STORENAME и PASSWORD):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
/// Вызов Java-метода создания ЭЦП.
/// Предполагается, что в рамках XML-документа (аргумент xml) имеется элемент с атрибутом wsu:Id="<значение аргумента wsuId>". Именно для этого элемента будет создана подпись.
/// certFilename - имя файла сертификата. Если не указано, то берется значение параметра CERTFILENAME.
/// keyStorePassword - пароль хранилища секретных ключей, по умолчанию пустой.
ClassMethod createSignature(xml As %Stream.Object, wsuId As %String, Output signature As %String, certFilename As %String = "", keyStorePassword As %String = "", StoreName As %String = "") As %Status
{
  #dim sc As %Status = $$$OK
  
  if (certFilename = "") set certFilename = ..#CERTFILENAME
  if (keyStorePassword = "") set keyStorePassword = ..#PASSWORD
  if (StoreName = "") set StoreName = ..#STORENAME
  
  #dim jgw As %Net.Remote.Gateway = ##class(%Net.Remote.Gateway).%New()
  
  // третий аргумент - для совместимости со старыми версиями 
  set sc = jgw.%Connect(..#JAVAGATEWAYSERVER, ..#JAVAGATEWAYPORT, $ZU(5))
  if $$$ISERR(sc) quit sc
  
  try
  {
    set signature = ##class(isc.jcp.JcpFacade).createSignature(jgw, xml, wsuId, certFilename, keyStorePassword, StoreName)
  }
  catch
  {
    set sc = %objlasterror
  }
  
  do jgw.%Disconnect()
  
  quit sc
}
- Для проверки работы подписи возьмём кусок кода из метода InitializeForService класса smev.JcpSignature и запустим в терминале:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
>S dummyBody=##class(%GlobalBinaryStream).%New()
 
>S SOAPWSUns=" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 

>do dummyBody.Write("<dummy wsu:Id=""tst_id"" xmlns:wsu="""_SOAPWSUns_"""/>")

>w ##class(smev.JcpUtils).createSignature(dummyBody, "tst_id", .dummySignature)
1
zw dummySignature>zw dummySignature
dummySignature="<ds:Signature xmlns:ds="" http://www.w3.org/2000/09/xmldsig#"">" _$c(10)_"<ds:SignedInfo>"_$c(10)_"<ds:CanonicalizationMethod Algorithm="" http://www.w3.org/2001/10/xml-exc-c14n#""/>" _$c(10)_"<ds:SignatureMethod Algorithm="" http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411""/>" _$c(10)_"<ds:Reference URI=""#tst_id"">"_$c(10)_"<ds:Transforms>"_$c(10)_"<ds:Transform Algorithm="" http://www.w3.org/2001/10/xml-exc-c14n#""/>" _$c(10)_"</ds:Transforms>"_$c(10)_"<ds:DigestMethod Algorithm="" http://www.w3.org/2001/04/xmldsig-more#gostr3411""/>" _$c(10)_"<ds:DigestValue>jBjUqmWW5HxPJCXw/c2t4yiREwO7b6fQAkE51nVnraA=</ds:DigestValue>"_$c(10)_"</ds:Reference>"_$c(10)_"</ds:SignedInfo>"_$c(10)_"<ds:SignatureValue>"_$c(10)_"ZyGjMlWPfdYVLGUJYb7qCRgkCAELl0fYSvLAWzBHL4DeIMZuITzKkTwFoUXhUeLW/Ra73Cm4Pymp"_$c(10)_"TXBytVGdiw=="_$c(10)_"</ds:SignatureValue>"_$c(10)_"<ds:KeyInfo>"_$c(10)_"<ds:X509Data>"_$c(10)_"</ds:X509Data>"_$c(10)_"</ds:KeyInfo>"_$c(10)_"</ds:Signature>"_$c(10)
Как видим, всё работает.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234830
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Спасибо за инструкцию, буду пробовать с нуля.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234843
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuctДело в этом:
Код: java
1.
XmlUtils.deserialize(xmlFragment);

Возвращает null (пустой документ)Да, и будьте внимательны с кодировкой. Как правило, русский текст в файле и неправильная работа с кодировкой приводя к таким вот нулпоинтэксепшен.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39234877
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Пробовал тоже выполнить ваш код в терминале - та же ошибка. Устанавливаю с "0" на виртуалку.
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39235124
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Попробовал на виртуалке правда под windows - jre6+jcp1.0.54
все остальное тоже самое - ничего лишнего

Таже ошибка при

Код: java
1.
2.
3.
4.
5.
6.
7.
	S dummyBody=##class(%GlobalBinaryStream).%New()
 
	S SOAPWSUns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"

	do dummyBody.Write("<dummy wsu:Id=""tst_id"" xmlns:wsu="""_SOAPWSUns_"""/>")

	w ##class(smev.JcpUtils).createSignature(dummyBody, "tst_id", .dummySignature)



Код: java
1.
2.
3.
4.
ОШИБКА #5023: Ошибка Java-шлюза: java.lang.NullPointerException
	at isc.jcp.XmlUtils.serializeNode(XmlUtils.java:51)
	at isc.jcp.XmlUtils.serializeNode(XmlUtils.java:38)
	at isc.jcp.JcpFacade.createSignature(JcpFacade.java:110)



Не меняли класс XMLUtils?
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39235158
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuctНе меняли класс XMLUtils?
Вроде нет, но точно сказать пока не могу. Вечером еще раз посмотрю.

А если вы возьмёте первоначальный iscjcp.jar? С ним тоже ошибка???


ЗЫ.
Также, не помешает отладочный вывод в iscjcp.jar сделать )))
И после каждой изменения в iscjcp.jar не забывать перезапускать шлюз
w ##class(%Net.Remote.Service).StopGateway("JCPGate")
w ##class(%Net.Remote.Service).StartGateway("JCPGate")
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39235184
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Огромное человеческое СПАСИБО Вам за помощь - удалось мне победить на виртуалке, думаю и на остальном тоже удастся!
Дело было в классе XmlUtils - слава google :)

Было так
Код: java
1.
2.
3.
4.
5.
6.
public class XmlUtils
{
  private static TransformerFactory transformerFactory ;
  private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  
  static



На просторах интернета заметил, что перед перед определением
Код: java
1.
localTransformer = transformerFactory.newTransformer();


Вызывается
Код: java
1.
... = TransformerFactory.newInstance();



И в нашем классе XmlUtils я тоже решил поменять определение свойства на:
Код: java
1.
private static TransformerFactory transformerFactory = TransformerFactory.newInstance();
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39235185
KaIIIuct
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
П.С.М.,

Еще раз спасибо!!!
...
Рейтинг: 0 / 0
Подписать SOAP-сообщение для СМЭВ
    #39235875
Фотография П.С.М.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KaIIIuctП.С.М.,

Еще раз спасибо!!!
Пожалуйста, чем смог, т.с. :)

Посмотрел XmlUtils и у меня и в исходниках в статье он одинаков. Вот он:

XmlUtils
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
package isc.jcp;

import java.util.*;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Контейнер для полезных методов работы с XML.
 */
public class XmlUtils
{
  private static TransformerFactory transformerFactory = TransformerFactory.newInstance();
  private static DocumentBuilderFactory documentBuilderFactory;
  static
  {
    documentBuilderFactory = DocumentBuilderFactory.newInstance();
    documentBuilderFactory.setNamespaceAware(true);
  }
  
  /**
   * Сериализует XML DOM в строку.
   *
   * @param node вершина DOM
   * @return Cтрока с XML
   */
  public static String serializeNode(Node node)
  {
    return serializeNode(node, true, true);
  }
  
  /**
   * Сериализует XML DOM в строку.
   *
   * @param node вершина DOM
   * @param omitXmlDeclaration признак того, что в результат не нужно включить XML declaration (по умолчанию true)
   * @return Cтрока с XML
   */
  public static String serializeNode(Node node, boolean omitXmlDeclaration)
  {
    return serializeNode(node, omitXmlDeclaration, true);
  }

  /**
   * Сериализует XML DOM в строку.
   *
   * @param node вершина DOM
   * @param omitXmlDeclaration признак того, что в результат не нужно включить XML declaration (по умолчанию true)
   * @param indent признак необходимости добавлять отступы (по умолчанию true)
   * @return Cтрока с XML
   */  
  public static String serializeNode(Node node, boolean omitXmlDeclaration, boolean indent)
  {
    Transformer serializer;
    try
    {
      serializer = transformerFactory.newTransformer();
    }
    catch (TransformerConfigurationException e)
    {
      throw new RuntimeException(e);
    }

    serializer.setOutputProperty(OutputKeys.METHOD, "xml");
    serializer.setOutputProperty(OutputKeys.INDENT, (indent ? "yes" : "no"));
    serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, (omitXmlDeclaration ? "yes" : "no"));

    StringWriter writer = new StringWriter();
    try
    {
      serializer.transform(new DOMSource(node), new StreamResult(writer));
    }
    catch (TransformerException e)
    {
      throw new RuntimeException(e);
    }

    return writer.toString();
  }
  
  /**
   * Десериализует XML из строки в DOM.
   *
   * @param s строка, содержащая XML
   * @return XML-документ (DOM)
   */
  public static Document deserialize(String s)
  {
    return deserialize(new StringReader(s));
  }
  
  /**
   * Десериализует XML из <code>java.io.Reader</code> в DOM.
   *
   * @param reader экземпляр <code>java.io.Reader</code>, содержащий XML
   * @return XML-документ (DOM)
   */
  public static Document deserialize(Reader reader)
  {
    DocumentBuilder documentBuilder;
    try
    {
      synchronized (documentBuilderFactory)
      {
        documentBuilder = documentBuilderFactory.newDocumentBuilder();
      }
    }
    catch (ParserConfigurationException e)
    {
      throw new RuntimeException(e);
    }
    
    return deserialize(documentBuilder, reader);
  }

  /**
   * Десериализует XML из <code>java.io.Reader</code> в DOM, используя указанный <code>javax.xml.parsers.DocumentBuilder</code>.
   *
   * @param documentBuilder объект-реализация <code>javax.xml.parsers.DocumentBuilder</code>, который будет использован при десериализации XML
   * @param reader экземпляр <code>java.io.Reader</code>, содержащий XML
   * @return XML-документ (DOM)
   */
  public static Document deserialize(DocumentBuilder documentBuilder, Reader reader)
  {
    Document doc = null;  
    try
    {
      doc = documentBuilder.parse(new InputSource(reader));
    }
    catch (SAXException e)
    {
      throw new RuntimeException(e);
    }
    catch (IOException ioe)
    {
      throw new RuntimeException(ioe);
    }
    
    return doc;
  }

  /**
   * Вычисляет XPath-выражение.
   *
   * @param xpath подготовленный объект <code>javax.xml.xpath.XPath</code>
   * @param doc XML-документ (DOM)
   * @param xpathExpression XPath-выражение
   * @return Результирующий массив вершин DOM
   */
  public static Node[] evalXPath(XPath xpath, Document doc, String xpathExpression)
  {
    NodeList nodelist;
    try
    {
      nodelist = (NodeList)xpath.evaluate(xpathExpression, doc, XPathConstants.NODESET);
    }
    catch (XPathExpressionException e)
    {
      throw new RuntimeException("Error evaluating XPath expression " + xpathExpression + ": " + e.getMessage(), e);
    }

    Node[] result = new Node[nodelist.getLength()];
    for (int i = 0; i < nodelist.getLength(); i++)
      result[i] = nodelist.item(i);

    return result;
  }
  
  /**
   * Возвращает первый дочерний XML-элемент.
   *
   * @param elem родительский XML-элемент
   * @return Первый дочерний XML-элемент
   */
  public static Element getFirstChildElement(Element elem)
  {
    for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling())
    {
      if (n.getNodeType() == Node.ELEMENT_NODE)
      {
        return (Element)n;
      }
    }
    return null;
  }

  /**
   * Возвращает следующий после указанного дочерний XML-элемент.
   *
   * @param parentElem родительский XML-элемент
   * @param currentElem текущий дочерний XML-элемент
   * @return Следующий после указанного дочерний XML-элемент
   */
  public static Element getNextChildElement(Element parentElem, Element currentElem)
  {
    boolean currElemFound = false;
    
    for (Node n = parentElem.getFirstChild(); n != null; n = n.getNextSibling())
    {
      if (n.getNodeType() == Node.ELEMENT_NODE)
      {
        if (currElemFound)
          return (Element)n;
        else
          currElemFound = (currentElem == (Element)n);
      }
    }
    return null;
  }
}



И да, и там и там:
Код: java
1.
2.
3.
4.
public class XmlUtils
{
  private static TransformerFactory transformerFactory = TransformerFactory.newInstance();
 ...


Т.ч., похоже, что у Вас кто-то уже приложил руку к XmlUtils )))
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Подписать SOAP-сообщение для СМЭВ
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]