我正在使用第三方提供的给定XSD的JAXB创建以下XML文档。 第三方请求签署文档并向其添加一个包含签名的额外元素。 使用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算法和JSR105 JAVA API签署文档(我不会包含整个签名代码以减少冗长,我使用的是XMLSignature类的标准行为然后使用XML转换器将文档转换为来自DOMSource的文件输出流:
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为同一根命名空间提供前缀到单个元素?
如何找到由API签名的实际XML字符串,我在启用javax.xml.crypto.dsig.cacheReference之后尝试读取引用输入流但是这在签名时不起作用,它只在验证时有效?
以下是XML示例:
2.0.6
Signature lies here
更新 - 完整的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 transforms = new ArrayList(); 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);
Java XML签名问题与解决方案
在使用Java进行XML文档加签时,遇到一个问题:当在文档中添加元素并签名后,验证时摘要值不匹配。问题可能在于创建的LAU元素的命名空间未被正确考虑。尝试将签名直接附加到根元素时,验证可以成功。寻求解决方法,包括为单个元素分配与根元素相同命名空间的前缀以及查看实际被签名的XML字符串。
792

被折叠的 条评论
为什么被折叠?



