title: Xades4j Verify signature Xades - EPES: Bad XML signature
body: <p>I am using Xades4J to develop a simple Java program that signs and verifies an XML with XADES-EPES. The sign process seems to be working properly and generates a valid signed XML (although we don't need the SignaturePolicyIdentifier section on it).</p>
  
  <p>*options arguments is from joptsimple library to parse arguments</p>
  
  <p>This is my sign function:</p>
  
  <pre><code>void signXML(OptionSet options) {
      KeyingDataProvider kp;
      try {
  
          SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
              public SignaturePolicyBase getSignaturePolicy() {
                  return new SignaturePolicyIdentifierProperty(
                          new ObjectIdentifier("oid:/1.2.4.0.9.4.5", IdentifierType.OIDAsURI, "Policy description"),
                          new ByteArrayInputStream("Test policy input stream".getBytes()))
                                  .withLocationUrl("http://www.example.com/policy");
              }
          };
  
          kp = new FileSystemKeyStoreKeyingDataProvider("pkcs12", options.valueOf("certificate").toString(),
                  new FirstCertificateSelector(), new DirectPasswordProvider(options.valueOf("password").toString()),
                  new DirectPasswordProvider(options.valueOf("password").toString()), false);
  
          // SignaturePolicyInfoProvider spi = new
          XadesSigningProfile p = new XadesEpesSigningProfile(kp, policyInfoProvider);
          p.withBasicSignatureOptionsProvider(new SignatureOptionsProvider());
          XadesSigner signer = p.newSigner();
  
          // open file
          DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
          factory.setNamespaceAware(true);
          DocumentBuilder builder = null;
          builder = factory.newDocumentBuilder();
          Document doc1 = builder.parse(new File(options.valueOf("input").toString()));
          Element elemToSign = doc1.getDocumentElement();
  
          // sign whole document
          new Enveloped(signer).sign(elemToSign);
  
          // save output file
          Transformer transformer = TransformerFactory.newInstance().newTransformer();
          Result output = new StreamResult(new File(options.valueOf("output").toString()));
          Source input = new DOMSource(doc1);
          transformer.transform(input, output);
  
      } catch (KeyStoreException | ParserConfigurationException | SAXException | IOException | XAdES4jException
              | TransformerException e) {
  
          e.printStackTrace();
      }
  }
  </code></pre>
  
  <p>This is a sample signature that it creates: (Is it normal to have &#13; at the end of each line of the base64 values?)</p>
  
  <pre><code>&lt;ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686"&gt;
  &lt;ds:SignedInfo&gt;
  &lt;ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/&gt;
  &lt;ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/&gt;
  &lt;ds:Reference Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686-ref0" URI=""&gt;
  &lt;ds:Transforms&gt;
  &lt;ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/&gt;
  &lt;/ds:Transforms&gt;
  &lt;ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/&gt;
  &lt;ds:DigestValue&gt;h20v8PSCwU5ymBKMj5o8scN3FyMfGCmN8OA2bnRHTnI=&lt;/ds:DigestValue&gt;
  &lt;/ds:Reference&gt;
  &lt;ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-f5700b65-334e-4905-96f6-ca6156139686-signedprops"&gt;
  &lt;ds:Transforms&gt;
  &lt;ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/&gt;
  &lt;/ds:Transforms&gt;
  &lt;ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/&gt;
  &lt;ds:DigestValue&gt;tEyMfk39qnevJRyLbxQJIGpEBJuCcYRSZNNjm7HfaaA=&lt;/ds:DigestValue&gt;
  &lt;/ds:Reference&gt;
  &lt;/ds:SignedInfo&gt;
  &lt;ds:SignatureValue Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686-sigvalue"&gt;
  ZhdQPEz7KwYoLTc72rxqUN2rlMfRGmqHd0MVSEeHRf/kmoqAGAqit5tw6k9k8oFCyuPDS/+DoXHJ&amp;#13;
  rooMDEMr+cuvbwwDwy77kHT+8JeUuIAamyqP/OByLytxXm/oKHVAraMhHNsGHvhcsYzULHl+n6JB&amp;#13;
  fhsYeR6rZdksS+QkgeUYohEktodl20/kyug4ymZjbJ7rCtH6+nRRR1nqc8oVT2ZpgfEaPHqWO06V&amp;#13;
  QURYYkuQEPOsNgFUu+YiWAX9pz94tlsOlLu6efBUP4lDZbCSq75J7nVZonmTbj/+mPl/oxpLCAgG&amp;#13;
  utWpL1RwyWn454G+Rd/AG3+MLWnbPVVSWUTcNK2gv4S2MVmosGxBnKwA71Zu30S+KaDwoktzZ62X&amp;#13;
  ViDLMmf6YbTKhiCIZYdjXPXr9QwSOHr+2B5GNUwo/CoOENJY/sXNHiHXxw+d+cyoowN4faJoVb5C&amp;#13;
  YFT7DACHyRd/d6TGdVEviHToTak+xPIK0HGnLvmkqzpICX8SFuMybur5Tttex4hqJNmXI7XbI9pk&amp;#13;
  YGLESBvKmzp4O9wLTJdABsLLxZSwU1plagu+5nb8ujIzmngVEHx4yBRprRVr3cBrHKoQBOHAiaGQ&amp;#13;
  96qUVTFogIX3vxN/1Q8xKDfB99FlzDdqnc2SW5lgYHnkuHHStJhoaCKRraUWVtU1miT/gMES+YM=
  &lt;/ds:SignatureValue&gt;
  &lt;ds:KeyInfo&gt;
  &lt;ds:X509Data&gt;
  &lt;ds:X509Certificate&gt;
  MIIFgTCCA2mgAwIBAgIJAPzDOBvbJQYvMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkFVMRMw&amp;#13;
  EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEDAO&amp;#13;
  BgNVBAMMB1Fwcm90ZXgwHhcNMTcxMTI5MDIwMjIyWhcNMTgxMTI5MDIwMjIyWjBXMQswCQYDVQQG&amp;#13;
  EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg&amp;#13;
  THRkMRAwDgYDVQQDDAdRcHJvdGV4MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt1+k&amp;#13;
  sAGGc1kvhs3AjTfIyBRRBb3sB5C+IlGplS1lOpViUsYOZKT/t0u1PWTxWnTNYpEChSg4ECnbaNje&amp;#13;
  nuyIQct5AS+MMMD2R8SSGGfvlhwr/yypEzcIfsOjFMhnV95Kto0abqLDucOyZotZfbaQQcwK7ATI&amp;#13;
  /TrumoUX6lRaryeIYBhENRCvmTjcR3ecinL+FSEpEOdXSh0jtHRtoV/HCzHdgNvXXLPD2YkyjY/0&amp;#13;
  D9rvHmVmKXtRfnLsiNcc2vMuE0XlfBz/WbP+lOpMKpka5F7ocnDeMJ2Tb24tL60M+DS7IYWOJ4wm&amp;#13;
  Vpb9FsBI3mDZ1AndsTIp5lljLIT7CVvgIvIbCxlOx6vcRxjOhpzNLmCJuMuI2dLtg5qn6q4QoLrE&amp;#13;
  6LAQZ8Zt9ljK2s33Vc84FZi+nZx6A1enTnLyHjds6BdrzvKLOJeUtLlTbufxNrkQzWSIhI2ZbfhY&amp;#13;
  Mn4yC1REj4kH30AKD6YkN028TasJDnv30g9n9eSbZ0fq2buT2DawGAA9GP02daaaOyTmBVJMonpi&amp;#13;
  xSD7lN7iR3zvDUxtjIoOi15XZw+2k28VqkwVdOwo3xkz5zVhSxm7Xv1NHdiUO2AUzvWMdBNMTS2t&amp;#13;
  0rr31B232UQvuqDHW1ws6em1iA+Lu1X3Z59Mer6Hg2mVclNKSBrYxUSwSv9poZqxXlGH6R0CAwEA&amp;#13;
  AaNQME4wHQYDVR0OBBYEFNG3ss8QEfGFgyxHpb54iRRNz9BDMB8GA1UdIwQYMBaAFNG3ss8QEfGF&amp;#13;
  gyxHpb54iRRNz9BDMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBACuhTI0prkRc15OI&amp;#13;
  HGQq+xhHRfbnG3dUEaXuAYhyDbrRXz2urEjIf2vGPIn7hheOrScSbQgblHq/tV1nQTyRsyHCvZlV&amp;#13;
  aE2+OWCfrQDdrwZKE2N2xC1ALgGTtF+I4lXgy6/9OzNVFnV0oZUnO6PN5cH6SVy+RHpO9Lsr5ndI&amp;#13;
  YBSuu0Zd7/IsOYY/vWcfJjq3+SnRotgGj0Jf4F7SH74XPz0QkoVKM1z3zGlbF/w8OzJw71yRVkaX&amp;#13;
  Ld+TDFC6jDFV+kjQ1k8pa4Hjs2Yko2AmNmpOZmMVjRLTdGLdSU/Gt1ewDp5TsEa2y/5u2PcZY/fd&amp;#13;
  dNaMyH7Qx0SmqvYvgG0C3mSGhhFv6++SaXXmo1lQCDgY9OK975KnQPSIHXeuK7oh/82a2ZhmQau0&amp;#13;
  B/ISxrjtRJbSHByLefJAkJpRVGowa14Nq/jI/Dvl46LVepTq2eNxbbMmbaW60HMwDS+YfNIwRpRS&amp;#13;
  n/W1/7mWLQRRP0Mb1/fjZlIZBV83fynZU5BSsoW+LZ8EWXt+VhtC8SWZ3m3ffk3KKqZDKJTih5c1&amp;#13;
  IFz2veIrHZH6O9n3taU+mVuNC8piuG+GBCBPo7dQwFmGo2zZ9BvSqUdytLniuej1PcPBTkcxfhCN&amp;#13;
  h5lKWwZCNE5v8RlEd9RbjEC5nAm8kCVvHX5SZivd77Yum8eBMAUQ++M2oNfz
  &lt;/ds:X509Certificate&gt;
  &lt;ds:X509SubjectName&gt;CN=Qprotex,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU&lt;/ds:X509SubjectName&gt;
  &lt;ds:X509IssuerSerial&gt;
  &lt;ds:X509IssuerName&gt;CN=Qprotex,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU&lt;/ds:X509IssuerName&gt;
  &lt;ds:X509SerialNumber&gt;18213463010308326959&lt;/ds:X509SerialNumber&gt;
  &lt;/ds:X509IssuerSerial&gt;
  &lt;/ds:X509Data&gt;
  &lt;ds:KeyValue&gt;
  &lt;ds:RSAKeyValue&gt;
  &lt;ds:Modulus&gt;
  t1+ksAGGc1kvhs3AjTfIyBRRBb3sB5C+IlGplS1lOpViUsYOZKT/t0u1PWTxWnTNYpEChSg4ECnb&amp;#13;
  aNjenuyIQct5AS+MMMD2R8SSGGfvlhwr/yypEzcIfsOjFMhnV95Kto0abqLDucOyZotZfbaQQcwK&amp;#13;
  7ATI/TrumoUX6lRaryeIYBhENRCvmTjcR3ecinL+FSEpEOdXSh0jtHRtoV/HCzHdgNvXXLPD2Yky&amp;#13;
  jY/0D9rvHmVmKXtRfnLsiNcc2vMuE0XlfBz/WbP+lOpMKpka5F7ocnDeMJ2Tb24tL60M+DS7IYWO&amp;#13;
  J4wmVpb9FsBI3mDZ1AndsTIp5lljLIT7CVvgIvIbCxlOx6vcRxjOhpzNLmCJuMuI2dLtg5qn6q4Q&amp;#13;
  oLrE6LAQZ8Zt9ljK2s33Vc84FZi+nZx6A1enTnLyHjds6BdrzvKLOJeUtLlTbufxNrkQzWSIhI2Z&amp;#13;
  bfhYMn4yC1REj4kH30AKD6YkN028TasJDnv30g9n9eSbZ0fq2buT2DawGAA9GP02daaaOyTmBVJM&amp;#13;
  onpixSD7lN7iR3zvDUxtjIoOi15XZw+2k28VqkwVdOwo3xkz5zVhSxm7Xv1NHdiUO2AUzvWMdBNM&amp;#13;
  TS2t0rr31B232UQvuqDHW1ws6em1iA+Lu1X3Z59Mer6Hg2mVclNKSBrYxUSwSv9poZqxXlGH6R0=
  &lt;/ds:Modulus&gt;
  &lt;ds:Exponent&gt;AQAB&lt;/ds:Exponent&gt;
  &lt;/ds:RSAKeyValue&gt;
  &lt;/ds:KeyValue&gt;
  &lt;/ds:KeyInfo&gt;
  &lt;ds:Object&gt;&lt;xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#" Target="#xmldsig-f5700b65-334e-4905-96f6-ca6156139686"&gt;&lt;xades:SignedProperties Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686-signedprops"&gt;&lt;xades:SignedSignatureProperties&gt;&lt;xades:SigningTime&gt;2017-11-30T20:58:18.009-05:00&lt;/xades:SigningTime&gt;&lt;xades:SigningCertificate&gt;&lt;xades:Cert&gt;&lt;xades:CertDigest&gt;&lt;ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/&gt;&lt;ds:DigestValue&gt;JkEubWWYvvoh7kOnuAvYeXE4cFamHJ5FOBYt3b3dCj4=&lt;/ds:DigestValue&gt;&lt;/xades:CertDigest&gt;&lt;xades:IssuerSerial&gt;&lt;ds:X509IssuerName&gt;CN=Qprotex,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU&lt;/ds:X509IssuerName&gt;&lt;ds:X509SerialNumber&gt;18213463010308326959&lt;/ds:X509SerialNumber&gt;&lt;/xades:IssuerSerial&gt;&lt;/xades:Cert&gt;&lt;/xades:SigningCertificate&gt;&lt;xades:SignaturePolicyIdentifier&gt;&lt;xades:SignaturePolicyId&gt;&lt;xades:SigPolicyId&gt;&lt;xades:Identifier Qualifier="OIDAsURI"&gt;oid:/1.2.4.0.9.4.5&lt;/xades:Identifier&gt;&lt;xades:Description&gt;Policy description&lt;/xades:Description&gt;&lt;/xades:SigPolicyId&gt;&lt;xades:SigPolicyHash&gt;&lt;ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/&gt;&lt;ds:DigestValue&gt;MaW9PDxJruPHhjBVAMWyrF9zP+kMnNqkoQOUXxDDGAk=&lt;/ds:DigestValue&gt;&lt;/xades:SigPolicyHash&gt;&lt;xades:SigPolicyQualifiers&gt;&lt;xades:SigPolicyQualifier&gt;&lt;xades:SPURI&gt;http://www.example.com/policy&lt;/xades:SPURI&gt;&lt;/xades:SigPolicyQualifier&gt;&lt;/xades:SigPolicyQualifiers&gt;&lt;/xades:SignaturePolicyId&gt;&lt;/xades:SignaturePolicyIdentifier&gt;&lt;/xades:SignedSignatureProperties&gt;&lt;/xades:SignedProperties&gt;&lt;/xades:QualifyingProperties&gt;&lt;/ds:Object&gt;
  &lt;/ds:Signature&gt;
  </code></pre>
  
  <p>And this is my verify code that prints Bad XML signature.</p>
  
  <pre><code>void verifyXML(OptionSet options) {
      try {
          File file = new File(options.valueOf("certificate").toString());
          FileSystemDirectoryCertStore store = new FileSystemDirectoryCertStore(file.getAbsoluteFile().getParent());
          FileInputStream fis = new FileInputStream(options.valueOf("certificate").toString());
          KeyStore ks = KeyStore.getInstance("pkcs12");
          ks.load(fis, options.valueOf("password").toString().toCharArray());                         
          fis.close();            
          CertificateValidationProvider provider = new PKIXCertificateValidationProvider(ks, false, store.getStore());
  
          XadesVerifier verifier = new XadesVerificationProfile(provider).newVerifier();
  
          Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(options.valueOf("input").toString()));
  
          doc.getDocumentElement().normalize();
  
          Element sig = (Element)doc.getElementsByTagName("ds:Signature").item(0);
          PrintWriter out = null;
          try {
              out = new PrintWriter(options.valueOf("output").toString());
              XAdESVerificationResult result = verifier.verify(sig, null);
              out.println("true");
          } catch (Exception e) {
              System.out.println(e.getMessage());
              out.println("false");
          }
          out.close();
  
  
      } catch (Exception ex) {
          System.err.println("Error: " + ex.getMessage());
      }
  </code></pre>
  
  <p>I will appreciate if someone can point me where the issue could be. Thanks!</p>
  
  <p><strong>UPDATE</strong>
  After I checked the stack trace I found the following exception:</p>
  
  <pre><code>    xades4j.xml.unmarshalling.UnmarshalException: Bad XML signature
      at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:130)
      at com.qprotex.Main.verifyXML(Main.java:190)
      at com.qprotex.Main.&lt;init&gt;(Main.java:99)
      at com.qprotex.Main.main(Main.java:81)
  Caused by: org.apache.xml.security.exceptions.XMLSecurityException: Cannot create a null:null from a http://www.w3.org/2000/09/xmldsig#:Signature element
  </code></pre>
  
  <p>I found <a href="https://stackoverflow.com/questions/24685913/xades4j-verification-cannot-create-a-nullnull-from-a-http-www-w3-org-2000-0">this post</a> that mentions the same error and after enabling factory.setNamespaceAware(true) in the verification method I get the following exception:</p>
  
  <pre><code>java.lang.NullPointerException
  at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.getLocationUrl(FromXmlSignaturePolicyConverter.java:71)
  at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:64)
  at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:1)
  at xades4j.xml.unmarshalling.UnmarshallerModule.convertProperties(UnmarshallerModule.java:64)
  at xades4j.xml.unmarshalling.DefaultQualifyingPropertiesUnmarshaller.unmarshalProperties(DefaultQualifyingPropertiesUnmarshaller.java:83)
  at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:175)
  at com.qprotex.Main.verifyXML(Main.java:190)
  at com.qprotex.Main.&lt;init&gt;(Main.java:99)
  at com.qprotex.Main.main(Main.java:81)
  </code></pre>
  
  <p><strong>UPDATE 2</strong>
  As I am not using a a SignaturePolicyIdentifier, I did changed my sign function to use XadesBesSigningProfile instead of XadesEpesSigningProfile. The only issue I have now is that it works only if I use KeyStore.getInstance("Windows-ROOT")</p>
  
  <p>This works:</p>
  
  <pre><code>            KeyStore trustAnchors = KeyStore.getInstance("Windows-ROOT"); 
              trustAnchors.load(null);
  
              CertificateValidationProvider provider = new PKIXCertificateValidationProvider(trustAnchors, false);
  </code></pre>
  
  <p>But this does not work and I get back a "xades4j.providers.CannotBuildCertificationPathException: Trust anchors KeyStore has no trusted certificate entries" exception.</p>
  
  <pre><code>            FileInputStream fis = new FileInputStream(options.valueOf("certificate").toString());
              KeyStore ks = KeyStore.getInstance("pkcs12");
              ks.load(fis, options.valueOf("password").toString().toCharArray());                         
              fis.close();
              CertificateValidationProvider provider = new PKIXCertificateValidationProvider(ks, false);
  </code></pre>