XML : Xml document signature not valid after deserialization from byte array

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