我按照本指南签署和验证 XML 消息https://www.oracle.com/technical-resources/articles/java/dig-signature-api.html。验证使用生成的文档。这种方法工作正常。
然而,在我们的用例中,我们将在我们的端点接收到一个签名的 XML 消息,因此我们将这个对象转换成一个文档:
public boolean validate(SignXml<?> xml) throws MarshalException, XMLSignatureException {
boolean status;
try {
status = validate(convertToDocument(xml));
} catch (ParserConfigurationException | JAXBException | IOException | SAXException ex) {
throw new XMLSignatureException(ex);
}
return status;
}
protected Document convertToDocument(SignXml<?> xml) throws ParserConfigurationException, JAXBException, IOException, SAXException {
DocumentBuilderFactory dbf = getDocumentBuilderFactory();
dbf.setNamespaceAware(true);
return dbf.newDocumentBuilder().parse(getStreamSource(xml));
}
private StreamSource getStreamSource(Document node) throws TransformerException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Result outputTarget = new StreamResult(outputStream);
Transformer t = getTransformer();
t.transform(new DOMSource(node), outputTarget);
return new StreamSource(new InputStreamReader(new ByteArrayInputStream(outputStream.toByteArray()), StandardCharsets.UTF_8));
}
public boolean validate(Document doc) throws MarshalException, XMLSignatureException, IOException {
try {
System.out.println("validate: " + getStringFromDocument(doc));
} catch (TransformerException e) {
throw new RuntimeException(e);
}
// Find Signature element
NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) {
throw new SignatureNotFoundException("Signature element not found");
}
// Create a DOMValidateContext and specify a KeySelector and document context
DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(), nl.item(0));
valContext.setProperty("org.jcp.xml.dsig.secureValidation", Boolean.TRUE);
valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
// Unmarshal the signature
XMLSignature signature = signatureFactory.unmarshalXMLSignature(valContext);
// Validate the signature
boolean coreValidity = signature.validate(valContext);
if (!coreValidity) {
LOGGER.error("Signature failed core validation");
boolean sv = signature.getSignatureValue().validate(valContext);
LOGGER.error("Signature validation status: {}", sv);
if (!sv) {
// Check the validation status of each Reference.
for (Reference ref : signature.getSignedInfo().getReferences()) {
boolean isRefValid = ref.validate(valContext);
LOGGER.debug("Reference '{}' {}", ref.getURI(), isRefValid ? "valid" : "invalid");
}
} else {
LOGGER.debug("Signature passed core validation");
}
}
return coreValidity;
}
但是失败了。在调试模式下,我发现生成的摘要与解码值不同:
似乎是 JAXB 解组的问题。是什么导致了这个问题?