0

A Java program sends a PDF document to an external system and receives a XADES sign of this document.

I would like to check if the hash of the PDF document matches the hash contained inside the Xades sign. So I calculate the SHA1 of the PDF document, but it is different to the hash in the ds:DigestValue (fpm+e6K287hHh1xlYxXoZ3Q3bkQ=). Why? I'm sure I'm calculating properly the PDF document hash.

 <documentoSGIFE>
    <documentoOriginal Id="original" encoding="base64" nombreFichero="371F1EDC7D2D1B22E0500C0AD23624FD.PDF">...</documentoOriginal>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature001">
      <ds:SignedInfo Id="SignedInfo001">
         <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
         <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
         <ds:Reference Id="Reference001_001" URI="#original">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>fpm+e6K287hHh1xlYxXoZ3Q3bkQ=</ds:DigestValue>
         </ds:Reference>
         <ds:Reference Id="Reference001_002" Type="http://uri.etsi.org/01903/v1.2.2#SignedProperties" URI="#SignedProperties001">...</ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue Id="SignatureValue001">...</ds:SignatureValue>
      <ds:KeyInfo Id="KeyInfo001">...</ds:KeyInfo>
      <ds:Object>...</ds:Object>
    </ds:Signature>
</documentoSGIFE>

Thanks

Eduardo
  • 1,169
  • 5
  • 21
  • 56

1 Answers1

1

DigestValue is not directly the hash of the document. It contains the Base64 encoded result of applying the hash algorithm to the transformed resource(s) defined in the Reference element attributes

Check this post for more details https://stackoverflow.com/a/7589216/6371459

XAdES is built on XMLSignatures, that are supported by Java standard. You can use the standard validator to verify the base digital signature. Check the reference documentation http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html

Unfortunately, depending on the characteristics of your XAdES signature, it not always can be verified by Java standard. In this case I suggest to use the open source project SD-DSS supported by European Union at https://joinup.ec.europa.eu/asset/sd-dss/description

Community
  • 1
  • 1
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Thanks for your help. If I don't understand wrong I've to apply first the transformation "http://www.w3.org/2000/09/xmldsig#enveloped-signature" to the data inside "documentoOriginal" element. Then calculate the SHA1 hash, and then calculate base64 string. I know how to calculate the SHA1 and the base64, but I don't know how to apply the transformation "http://www.w3.org/2000/09/xmldsig#enveloped-signature". Could you help me? – Eduardo Jul 13 '16 at 08:01
  • Why you do not validate the full signature? Checking only the hash you are not validating integrity. Probably the code would be simpler. I am not sure, but to calculate the `digestValue` I think you can use `XMLSignatureFactory.newRef` and `XMLSignatureFactory.newSignedInfo`as shown in the Code Sample 1 of the provided link. If it does not provide directly the digestValue, execute the signature with a autogenerated keystore. The signature will be differente, but the hash will be the same. – pedrofb Jul 13 '16 at 08:34
  • I'm validating the full signature with "@firma" (spanish state solution for validating signs). But "@firma" does not check if the sign correspond to the original document. I will try what you are suggesting me. Thanks – Eduardo Jul 13 '16 at 08:41
  • I know @firma. We are close :). It is possible to verify just the signature without the document, but only for detached signature. For enveloped signatures it verifies also the integrity. You can check it at valide.redsara.es – pedrofb Jul 13 '16 at 09:16
  • Oh, yes, we're really close :). You say that for enveloped signatures '@firma' verifies also the integrity. Do you mean that '@firma' verifies that the sign correspond to the original document for enveloped signatures? If so, I've tried with "valide.redsara.es" and it doesn't ask me for the original document. – Eduardo Jul 13 '16 at 10:30
  • Yes, @firma performs integrity check: that neither the signature nor the document has been altered. valide.redsara.es does not ask you for the document because for enveloped signatures the signed document is the XML document itself (the node referenced in signature). If you use a detached signature, valide will ask you for the original – pedrofb Jul 13 '16 at 11:52
  • I've tried with a detached signature (like the signature I've written in my question) and "valide" doesn't ask me for the original document. – Eduardo Jul 13 '16 at 12:08
  • Your signature is enveloped, not detached. But, I have tested valide with a detached one and it fails. Also I have tested with a CAdES detached and it shows the message `Para una validación completa de su firma digital deberás introducir el documento originalmente firmado. Si no dispones de dicho documento, simplemente pulsa Aceptar` – pedrofb Jul 13 '16 at 12:26
  • Are you sure the signature is enveloped? The URI attribute refers to "#original" so I think it is an "internally detached" signature. Now I'm trying to do what you suggested me before. I'm signing the original document, of course applying the "transformation", but the digest obtained is different. I don't know what to do. – Eduardo Jul 13 '16 at 12:49
  • You are using the envelope transform `w3.org/2000/09 xmldsig#enveloped-signature`. Also, a detached should only contain a node. But it is easy to know if integrity is being validated. Verify the signature with @firma, valide or programmatically. After this, change a value in '#original' and verify again. It must fail. – pedrofb Jul 13 '16 at 13:32
  • mmm... We're receiving the signature from a third party, so I'm going to ask them what kind of signature they are returning to us. I thought it was detached because we sent to the third party a PDF document, and they return us the xades signature. In principle, enveloped signature are for xml documents, not for pdf documents, and for this reason I thought it was a detached signature. – Eduardo Jul 13 '16 at 15:22
  • The solution you are suggesting me is not what I'm looking for. I don't want to check the integrity of the signature. What I really want is to check that the signature corresponds to the original document that was signed, and not to the content of the ds:reference. – Eduardo Jul 13 '16 at 15:25
  • I understand. In fact, there is a simpler solution if you are going to use @firma to verify. The enveloped signature protects the `#original` node which embeds your document . So you just need to compare the hash of the contents of the node (decoded from base64) with the hash of your document – pedrofb Jul 13 '16 at 18:14
  • Thanks, this is what I've done exactly for detached and enveloping signatures. With enveloped signatures I've done what you suggested me in a previous comment. I've signed again the original document with any certificate, applying all the transformations of the original signature. And then, I've compared the digest value of both signatures. Thanks for all your help. – Eduardo Jul 14 '16 at 06:18
  • Ok @Eduardo, it is a complex world – pedrofb Jul 14 '16 at 06:51