Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline Вячеслав Александрович  
#1 Оставлено : 24 ноября 2017 г. 18:21:13(UTC)
Вячеслав Александрович

Статус: Участник

Группы: Участники
Зарегистрирован: 24.11.2017(UTC)
Сообщений: 12
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 2 раз
здравствуйте!

уже второй день не могу решить проблему верификации XML-документа, подписанного в формате enveloped.
используется версия CryptoPro jcp-2.0.39014, в реализации опирался на пример xmlSign/XMLSignDoc.java

опытным путём обнаружил, что верификация проходит успешно при наличии трансформации TRANSFORM_ENVELOPED_SIGNATURE:
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);

если данная трансформация присутствует, верификация проходит успешно, независимо от метода канонизации XML и наличия других трансформаций.

в нашем случае допустимо использование трансформаций TRANSFORM_C14N_EXCL_OMIT_COMMENTS и алгоритма нормализации СМЭВ 3.4
про TRANSFORM_ENVELOPED_SIGNATURE в ТЗ ничего нет, и добавление данной трансформации вызывает вопросы со стороны потребителя услуг.

причём, даже если я не буду использовать СМЭВ, а только стандартные трансформации, объявленные в org.apache.xml.security.transforms.Transforms,
то верификация также не сработает без включения TRANSFORM_ENVELOPED_SIGNATURE в цепочку преобразований.

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

Отредактировано пользователем 1 декабря 2017 г. 20:18:27(UTC)  | Причина: Не указана

Online Евгений Афанасьев  
#2 Оставлено : 27 ноября 2017 г. 17:10:54(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,916
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 688 раз в 649 постах
Здравствуйте.
Попробуйте такой вариант (из того же примера, метод signObj):
Код:

...
// создание нового (пустого) XML-документа
final DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
final Document doc = documentBuilder.newDocument();

final Element root = doc.createElement("Root");
doc.appendChild(root);

final Element anElement = doc.createElement("InsideObject");
anElement.appendChild(doc.createTextNode("A text in a box"));
anElement.setAttribute("Id", "signed");
anElement.setIdAttribute("Id", true);
root.appendChild(anElement);

final XMLSignature sig = new XMLSignature(doc, "", signMethod);
root.appendChild(sig.getElement());

final Transforms transforms = new Transforms(doc);
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);

sig.addDocument("#signed", transforms, digestMethod);
sig.addKeyInfo(cert);
sig.sign(privateKey);
...

Код:

<?xml version="1.0" encoding="UTF-8"?><Root><InsideObject Id="signed">A text in a box</InsideObject><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
<ds:Reference URI="#signed">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
<ds:DigestValue>fp7gOtOW5oXBJr/dkStrVhxMr5SvS25bAy1bUkX9a+c=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
mIE6ZWBb8zEdLWQFnirHSMW7f3KWNrTcL5Lg8+uJsfl2H7awonASx3gcG4Wx4NNPtTypVX7Dg5dy
7EPah6+/ug==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIBfjCCAS2gAwIBAgIFAIjNRC0wCAYGKoUDAgIDMDMxCzAJBgNVBAYTAlJVMRIwEAYDVQQKDAlD
cnlwdG9Qcm8xEDAOBgNVBAMMB25ld0NlcnQwHhcNMTcxMTI3MTQwMzEwWhcNMTgxMTI3MTQwMzEw
WjAzMQswCQYDVQQGEwJSVTESMBAGA1UECgwJQ3J5cHRvUHJvMRAwDgYDVQQDDAduZXdDZXJ0MGMw
HAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEDQwAEQDImpcfgEqlFvA0crJ7/TTHhbxHylYfh
gSFpQQBGxatikyY6/PWcCmhh5GPrlQB2pEt2Kt0J4A+WW2QfZvfURoajJjAkMA4GA1UdDwEB/wQE
AwIGwDASBgNVHRMBAf8ECDAGAQH/AgEFMAgGBiqFAwICAwNBAJZrHBZX/iRjMkLus/E0FTy1egVo
WudwZpElR0vNA1Y0VvS2quc/sIrjIRMqWiwm0mD9U+Q1UjpeP+BGuikbZFM=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature></Root>

Отредактировано пользователем 27 ноября 2017 г. 17:11:39(UTC)  | Причина: Не указана

Offline Вячеслав Александрович  
#3 Оставлено : 27 ноября 2017 г. 18:59:22(UTC)
Вячеслав Александрович

Статус: Участник

Группы: Участники
Зарегистрирован: 24.11.2017(UTC)
Сообщений: 12
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 2 раз
мой код приведён ниже.

как написал в первом сообщении, используемые трансформации определены в ТЗ, и тут я ничего менять не могу.


Код:

final XMLSignature sig = new XMLSignature(
		xmlDocument,
		"",
		XML_SIGN_ENCRYPT_ALGORITHM_URI,
		Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS
);

final Element rootElement = xmlDocument.getDocumentElement();
rootElement.appendChild(sig.getElement());

final Transforms transforms = new Transforms(xmlDocument);

transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
transforms.addTransform(SmevTransformSpi.ALGORITHM_URN);

sig.addDocument("", transforms, XML_SIGN_HASH_ALGORITHM_URI);

// добавляем информацию о сертификатах для используемого ключа
for (final Certificate certificate: certificates) {
	sig.addKeyInfo((X509Certificate) certificate);
}

sig.sign(privateKey);

// копирование содержимого XML-документа в поток
final ByteArrayOutputStream output = new ByteArrayOutputStream(source.length);

final TransformerFactory tf = TransformerFactory.newInstance();

final Transformer trans = tf.newTransformer();

trans.transform(new DOMSource(xmlDocument), new StreamResult(output));
...


Offline Вячеслав Александрович  
#4 Оставлено : 28 ноября 2017 г. 19:16:26(UTC)
Вячеслав Александрович

Статус: Участник

Группы: Участники
Зарегистрирован: 24.11.2017(UTC)
Сообщений: 12
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 2 раз
извините, но неужели у службы технической поддержки нет никаких идей относительно возможного решения проблемы? Think
если в моём коде что-то сделано явно некорректно, укажите пожалуйста.
Online Евгений Афанасьев  
#5 Оставлено : 29 ноября 2017 г. 16:23:09(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,916
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 688 раз в 649 постах
Попробуйте так:
Код:


// Подпись (без SmevTransformSpi.ALGORITHM_URN)

// создание нового (пустого) XML-документа
final DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
final Document doc = documentBuilder.newDocument();

// корень (подписывается)
Element root = doc.createElement("Root");
doc.appendChild(root);

final Element anElement = doc.createElement("InsideObject");
anElement.appendChild(doc.createTextNode("A text in a box"));
root.appendChild(anElement);

final XMLSignature sig = new XMLSignature(doc, "", signMethod);

final Transforms transforms = new Transforms(doc);
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);

sig.addDocument("", transforms, digestMethod); // "" - весь документ (Root)
sig.addKeyInfo(cert);
sig.sign(privateKey);

root.appendChild(sig.getElement()); // добавляем узел подписи

...

// Проверка. При проверке удаляем узел подписи, т.к. он включен в Root

final DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
doc = documentBuilder.parse(new FileInputStream(<файл>));

final Element nscontext = doc.createElementNS(null, "namespaceContext");
nscontext.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" + "ds".trim(), Constants.SignatureSpecNS);

final Element sigElement = (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature[1]", nscontext);

NodeList nodes = doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
for (int i = 0; i < nodes.getLength(); i++) {

  Element item = (Element)nodes.item(i);
  item.getParentNode().removeChild(item);

}

final XMLSignature signature = new XMLSignature(sigElement, "");
final KeyInfo ki = signature.getKeyInfo();
final X509Certificate certKey = ki.getX509Certificate();

if (certKey != null) {
 Logger.getLogger("LOG").info("The XML signature  is " + (signature.checkSignatureValue(certKey) ? "valid (good)" : "invalid (bad)"));
}
else {

  final PublicKey pk = ki.getPublicKey();
  if (pk != null) {
    Logger.getLogger("LOG").info("The XML signature is " + (signature.checkSignatureValue(pk) ? "valid (good)" : "invalid (bad)"));
  } else {
    throw new Exception("There are no information about public key. Verification couldn't be implemented");
  }
}



Код:

<?xml version="1.0" encoding="UTF-8"?><Root><InsideObject>A text in a box</InsideObject><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
<ds:DigestValue>3PWU3QLRW9/y6hJlqbcmSR1NvNVF8NJ8PPKBwNanMW0=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
WQ27RtOrkCSc4y1fsxD4x1FzN3FgImxXdZi3QBbf6mWmVtnZy7wl1sLhbatxJ3jmoZck0BAyBosw
d6s0kKkoDw==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIBfTCCASygAwIBAgIEX5oxDTAIBgYqhQMCAgMwMzELMAkGA1UEBhMCUlUxEjAQBgNVBAoMCUNy
eXB0b1BybzEQMA4GA1UEAwwHbmV3Q2VydDAeFw0xNzExMjkxMzE2MDRaFw0xODExMjkxMzE2MDRa
MDMxCzAJBgNVBAYTAlJVMRIwEAYDVQQKDAlDcnlwdG9Qcm8xEDAOBgNVBAMMB25ld0NlcnQwYzAc
BgYqhQMCAhMwEgYHKoUDAgIjAQYHKoUDAgIeAQNDAARAVpvmoo92NI1fAHim8MXouagdznNPUiwg
0JWXQ/c9oIBIeOfAv2YXYSz0jTpGcbBSILpcOry1aOLdjnW+JibJcKMmMCQwDgYDVR0PAQH/BAQD
AgbAMBIGA1UdEwEB/wQIMAYBAf8CAQUwCAYGKoUDAgIDA0EAZcQoEW2InWMOfbfa4oD3g83PMAZm
HVmBjkz5/WC8eWoj74ak35IkDIbuQNsVhOvopvHdQbFWIA9KFTnCxd3Gcg==
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature></Root>
Offline Вячеслав Александрович  
#6 Оставлено : 30 ноября 2017 г. 16:01:05(UTC)
Вячеслав Александрович

Статус: Участник

Группы: Участники
Зарегистрирован: 24.11.2017(UTC)
Сообщений: 12
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 2 раз
спасибо за ответ.
попробовал, но с тем же результатом - ошибка валидации.

пожалуй, следует мне также скопировать код, который использую для валидации, он также сделан на основе примера xmlSign/XMLSignDoc.java

Код:
    
      public static boolean verifyXmlEnvelopedSignature(final byte[] source) throws Exception  {        
        final Document doc =
                DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(new ByteArrayInputStream(source));

        /* Чтение узла подписи <ds:Signature> из XML-документа */        
        final Element nscontext = doc.createElementNS(null, "namespaceContext");
        nscontext.setAttributeNS("http://www.w3.org/2000/xmlns/",
                "xmlns:" + "ds".trim(), Constants.SignatureSpecNS);

        // выбор из прочитанного содержимого пространства имени узла подписи <ds:Signature>
        final Element sigElement =
                (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature[1]", nscontext);

        /* Проверка подписи XML-документа на основе информации об открытом ключе, хранящейся в
        XML-документе */        
        final XMLSignature signature = new XMLSignature(sigElement, "");

        // чтение узла <ds:KeyInfo> информации об открытом ключе
        final KeyInfo ki = signature.getKeyInfo();

        // чтение сертификата из узла информации об открытом ключе
        final X509Certificate certKey = ki.getX509Certificate();

        // если сертификат найден, то осуществляется проверка
        // подписи на основе сертфиката
        if (certKey != null) {
            return signature.checkSignatureValue(certKey);
        } else { // в противном случае осуществляется проверка на открытом ключе
            // чтение открытого ключа из узла информации об открытом ключе
            final PublicKey pk = ki.getPublicKey();
            if (pk != null) {
                return signature.checkSignatureValue(pk);
            }
        }
        throw new ApplicationException("applicationException.noPubKeyInfoToVerifySignature");
    }


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

отсюда ещё один вопрос: правильный ли способ валидации я использую?

Отредактировано пользователем 1 декабря 2017 г. 20:18:08(UTC)  | Причина: Не указана

Online Евгений Афанасьев  
#7 Оставлено : 30 ноября 2017 г. 17:59:38(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,916
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 688 раз в 649 постах
Это проверка из примера. Вы узел подписи добавляете после подписи и удаляете его перед проверкой, как я в примере выше добавил?
Приведенный пример у меня отработал.
Offline Вячеслав Александрович  
#8 Оставлено : 30 ноября 2017 г. 18:52:02(UTC)
Вячеслав Александрович

Статус: Участник

Группы: Участники
Зарегистрирован: 24.11.2017(UTC)
Сообщений: 12
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 2 раз
если внимательно читаю, то поступаю аналогичным образом:
подписываю так: https://www.cryptopro.ru...ts&m=85945#post85945

проверять пробовал и так:

Код:
    
      public static boolean verifyXmlEnvelopedSignature(final byte[] source) throws Exception  {
        /* Загружаем подписанный XML-документ из файла */
        final Document doc =
                DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(new ByteArrayInputStream(source));

        /* Чтение узла подписи <ds:Signature> из XML-документа */
        // чтение из загруженного документа содержимого пространства имени Signature
        final Element nscontext = doc.createElementNS(null, "namespaceContext");
        nscontext.setAttributeNS("http://www.w3.org/2000/xmlns/",
                "xmlns:" + "ds".trim(), Constants.SignatureSpecNS);

        // выбор из прочитанного содержимого пространства имени узла подписи <ds:Signature>
        final Element sigElement =
                (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature[1]", nscontext);

        final NodeList nodes = doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
        for (int i = 0; i < nodes.getLength(); i++) {
            final Element item = (Element) nodes.item(i);
            item.getParentNode().removeChild(item);
        }

        /* Проверка подписи XML-документа на основе информации об открытом ключе, хранящейся в
        XML-документе */

        // инициализация объекта проверки подписи
        final XMLSignature signature = new XMLSignature(sigElement, "");

        // чтение узла <ds:KeyInfo> информации об открытом ключе
        final KeyInfo ki = signature.getKeyInfo();

        // чтение сертификата из узла информации об открытом ключе
        final X509Certificate certKey = ki.getX509Certificate();

        // если сертификат найден, то осуществляется проверка
        // подписи на основе сертфиката
        if (certKey != null) {
            return signature.checkSignatureValue(certKey);
        } else { // в противном случае осуществляется проверка на открытом ключе
            // чтение открытого ключа из узла информации об открытом ключе
            final PublicKey pk = ki.getPublicKey();
            if (pk != null) {
                return signature.checkSignatureValue(pk);
            }
        }
        throw new ApplicationException("applicationException.noPubKeyInfoToVerifySignature");
    }



но, извиняюсь за назойливость, я не понимаю, как удаление элемента из документа может влиять на проверку подписи.
ведь конструктор выглядит так: new XMLSignature(sigElement, "");
здесь и далее по коду никаких ссылок на исходный документ вообще нет Think
Online Евгений Афанасьев  
#9 Оставлено : 1 декабря 2017 г. 9:56:03(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,916
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 688 раз в 649 постах
Автор: Вячеслав Александрович Перейти к цитате
sig.addDocument("", transforms, XML_SIGN_HASH_ALGORITHM_URI);

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

Offline Вячеслав Александрович  
#10 Оставлено : 1 декабря 2017 г. 16:18:36(UTC)
Вячеслав Александрович

Статус: Участник

Группы: Участники
Зарегистрирован: 24.11.2017(UTC)
Сообщений: 12
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 2 раз
к сожалению, предложенное решение (с удалением эл-та подписи перед верификацией) не сработало.

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

но вот когда выполняется верификация - тут исходный документ никак уже не участвует.

мы извлекаем подпись:
Код:
final Element sigElement = (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature[1]", nscontext);


инициализируем объект верификатора:
Код:
final XMLSignature signature = new XMLSignature(sigElement, "");


и выполняем проверку:
Код:
signature.checkSignatureValue(certKey);


соответственно, никаких ссылок на родительский документ у нас нет, правильно?

и даже если предположить, что ссылку можно получить неявно, например так:
Код:
sigElement.getParentNode()


то тогда операция:
Код:
   final NodeList nodes = doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
   for (int i = 0; i < nodes.getLength(); i++) {
	   final Element item = (Element) nodes.item(i);
	   item.getParentNode().removeChild(item);
   } 


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

полагаю, что в моей картине мироздания не хватает важной детали,
но всё же рассуждения, приведённые выше, не лишены логики )
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.