I have a problem where I sign xml document and validate signature after that and the validation passes, but when I serialize document to byte array and then deserialize it back to document, signature validation fails.
Here are methods used for validation and serialization/deserialization:
public class DocumentSigner { @Override public byte[] transformToByteArray(Document doc) throws Exception { TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory.newTransformer(); ByteArrayOutputStream os = new ByteArrayOutputStream(); transformer.transform(new DOMSource(doc), new StreamResult(os)); return os.toByteArray(); } private Document byteArrayToXmlDoc(byte[] documentoXml) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setIgnoringElementContentWhitespace(true); DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(new ByteArrayInputStream(documentoXml), "UTF-8"); } @Override public Boolean validate(byte[] byteArrayDoc, Integer certificatePropertiesId) throws Exception { Document doc = byteArrayToXmlDoc(byteArrayDoc); return validate(doc, certificatePropertiesId); } public Boolean validate(Document doc, Integer certificatePropertiesId) throws Exception { NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); if (nl.getLength() == 0) { throw new Exception("No signature element."); } KeyStore ks = KeyStore.getInstance("JKS"); CertificatePropertiesDTO certProp = databaseLogic.getCertificateProperties(certificatePropertiesId); if (certProp == null || certProp.getCertificatePassword().isEmpty() || certProp.getCertificate() == null){ throw new RuntimeException("No certificate."); } ks.load(new ByteArrayInputStream(certProp.getCertificate()), certProp.getCertificatePassword().toCharArray()); KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(ks.aliases().nextElement(), new KeyStore.PasswordProtection(certProp.getCertificatePassword().toCharArray())); X509Certificate[] certs = (X509Certificate[]) keyEntry.getCertificateChain(); if (certs == null || certs.length == 0) { throw new RuntimeException("No certificate found."); } XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); DOMValidateContext valContext = new DOMValidateContext(keyEntry.getCertificate().getPublicKey(), nl.item(0)); NodeList els = doc.getElementsByTagNameNS("*", "SignatureProperties"); Element el = (Element) els.item(0); valContext.setIdAttributeNS(el, null, "Id"); valContext.setDefaultNamespacePrefix("dsig"); valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); try { XMLSignature signature2 = fac .unmarshalXMLSignature(new DOMStructure(nl.item(0))); boolean coreValidity = signature2.validate(valContext); // Check core validation status. if (coreValidity == false) { log.info("Signature failed core validation"); boolean sv = signature2.getSignatureValue() .validate(valContext); log.info("signature validation status: " + sv); Iterator<?> i = signature2.getSignedInfo().getReferences() .iterator(); for (int j = 0; i.hasNext(); j++) { Reference ref = (Reference) i.next(); boolean refValid = ref.validate(valContext); log.info("ref[" + j + "] validity status: " + refValid); } return false; } else { log.info("Signature passed core validation"); return true; } } catch (Exception ex) { log.info("EXCEPTION during validation: " + ex.getMessage()); return false; } } public void signDocument(Document doc) { .... } }
Here is where it passes/fails:
public void SignAndValidate() { ... Document doc = createDocument(); documentSigner.signDocument(doc); validate(doc, 1); // OUTPUT: // Signature passed core validation byte[] docArr = documentSigner.transformToByteArray(doc); validate(docArr, 1); // OUTPUT: // Signature failed core validation // signature validation status: false // ref[0] validity status: false // ref[1] validity status: true }
If necessary I will post methods for creating/signing document but it's big.
No comments:
Post a Comment