Форум КриптоПро
»
Средства криптографической защиты информации
»
КриптоПро JCP, JavaTLS
»
верификация enveloped xml signature не проходит без TRANSFORM_ENVELOPED_SIGNATURE
Статус: Участник
Группы: Участники
Зарегистрирован: 24.11.2017(UTC) Сообщений: 12 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 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)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,003 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 714 раз в 674 постах
|
Здравствуйте. Попробуйте такой вариант (из того же примера, метод 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)
| Причина: Не указана |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 24.11.2017(UTC) Сообщений: 12 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 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));
...
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 24.11.2017(UTC) Сообщений: 12 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 2 раз
|
извините, но неужели у службы технической поддержки нет никаких идей относительно возможного решения проблемы? если в моём коде что-то сделано явно некорректно, укажите пожалуйста.
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,003 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 714 раз в 674 постах
|
Попробуйте так: Код:
// Подпись (без 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>
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 24.11.2017(UTC) Сообщений: 12 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 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)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,003 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 714 раз в 674 постах
|
Это проверка из примера. Вы узел подписи добавляете после подписи и удаляете его перед проверкой, как я в примере выше добавил? Приведенный пример у меня отработал. |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 24.11.2017(UTC) Сообщений: 12 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 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, ""); здесь и далее по коду никаких ссылок на исходный документ вообще нет
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,003 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 714 раз в 674 постах
|
Автор: Вячеслав Александрович ![Перейти к цитате Перейти к цитате](/forum2/Themes/soclean/icon_latest_reply.gif) sig.addDocument("", transforms, XML_SIGN_HASH_ALGORITHM_URI); Вы подписываете весь документ, потому наличие узла подписи при проверке может влиять. |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 24.11.2017(UTC) Сообщений: 12 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png) Откуда: Санкт-Петербург Сказал(а) «Спасибо»: 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);
}
всё равно удалит узел из документа, а следовательно родитель уже будет недоступен. полагаю, что в моей картине мироздания не хватает важной детали, но всё же рассуждения, приведённые выше, не лишены логики )
|
|
|
|
Форум КриптоПро
»
Средства криптографической защиты информации
»
КриптоПро JCP, JavaTLS
»
верификация enveloped xml signature не проходит без TRANSFORM_ENVELOPED_SIGNATURE
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close