Я создаю следующий XML-документ, используя JAXB данного XSD, который предоставляется третьей стороной. Третий сторонний запрос подписать документ и добавить к нему дополнительный элемент, который содержит подпись. Использование JDK 1.7.
Ниже приведен пример кода для сортировки:
JAXBContext jaxbContext = JAXBContext.newInstance(DataPDU.class);
DataPDU myDataPDU = new DataPDU();
myDataPDU.setRevision("2.0.6");
// marshall the file
Marshaller marshaller = jaxbContext.createMarshaller();
DOMResult domResult = new DOMResult();
marshaller.marshal(myDataPDU, domResult);
// get the document list
Document document = (Document) domResult.getNode();
Затем я создаю элемент (LAU), как показано ниже, и подписываю документ с использованием алгоритма HMAC-SHA256
и JAVA API JSR105 (я не собираюсь включать весь код подписи для уменьшения детализации, я использую стандартное поведение класс XMLSignature
, а затем преобразование документа в выходной поток файла из DOMSource с использованием XML-трансформаторов):
Element LAUElement = document.createElementNS("urn:swift:saa:xsd:saa.2.0", "Saa:LAU");
Element rootElement = document.getDocumentElement();
rootElement.appendChild(LAUElement);
// sign the document
XMLSignatureUtil.sign(document, secret, LAUElement, "ds");
// create the output file
TransformerUtil.transformDocumentToFile(document, "resultingFile.xml");
XML правильно подписывается, но при проверке вычисляемое значение дайджест отличается от значения дайджеста.
Я заметил, что при изменении значения пространства имен при создании элемента LAU дайджест никогда не меняется, как если бы документ подписывался и пренебрегал пространством имен элемента LAU, и я думаю, что это причина его неудачи, Любые другие изменения в документе в целом или изменение префикса элемента LAU напрямую влияют на вычисленный дайджест полезной нагрузки.
Если я добавляю подпись к корневому элементу напрямую, а не создавая элемент LAU, проверка корректно работает.
Элемент LAU существует в XSD и может быть создан с использованием JAXB, но проблема в том, что я не могу найти способ назначить префикс (только для него в документе) того же пространства имен, что и корневой элемент.
Вопросы:
Является ли пространство имен фактически опущено из дайджест полезной нагрузки вычисление при добавлении элемента в документ с помощью
createElementNS
иappendChild
?Есть ли способ предоставить через JAXB префикс для того же корня пространство имен только для одного элемента?
Как я могу найти фактическую строку XML, подписанную API, я попробовал прочитать исходный поток ввода после включения
javax.xml.crypto.dsig.cacheReference
, но это не сработало при подписании, оно работало только при проверке?
Ниже приведен пример XML:
<DataPDU xmlns="urn:swift:saa:xsd:saa.2.0">
<Revision>2.0.6</Revision>
<Saa:LAU xmlns:Saa="urn:swift:saa:xsd:saa.2.0"> Signature lies here </Saa:LAU>
</DataPDU>
Обновление - полный процесс подписи XML
JAXBContext jaxbContext = JAXBContext.newInstance(DataPDU.class);
DataPDU myDataPDU = new DataPDU();
myDataPDU.setRevision("2.0.6");
// marshall the file
Marshaller marshaller = jaxbContext.createMarshaller();
DOMResult domResult = new DOMResult();
marshaller.marshal(myDataPDU, domResult);
// get the document list
Document document = (Document) domResult.getNode();
// signing process
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
SignatureMethod signatureMethod =
factory.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", null);
CanonicalizationMethod canonicalizationMethod =
factory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (XMLStructure) null);
List<Transform> transforms = new ArrayList<Transform>();
transforms.add(factory.newTransform(Transform.ENVELOPED, (XMLStructure) null));
transforms.add(factory.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#", (XMLStructure) null));
DigestMethod digestMethod = factory.newDigestMethod("http://www.w3.org/2001/04/xmlenc#sha256", null);
Reference reference = factory.newReference("", digestMethod, transforms, null, null);
SignedInfo signedInfo =
factory.newSignedInfo(canonicalizationMethod, signatureMethod, Collections.singletonList(reference));
String secretKey = "Abcd1234abcd1234Abcd1234abcd1234";
SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
Element LAUElement = document.createElementNS("urn:swift:saa:xsd:saa.2.0", "Saa:LAU");
Element rootElement = document.getDocumentElement();
rootElement.appendChild(LAUElement);
DOMSignContext domSignContext = new DOMSignContext(secret_key, LAUElement);
domSignContext.setDefaultNamespacePrefix("ds");
XMLSignature signature = factory.newXMLSignature(signedInfo, null);
signature.sign(domSignContext);