I have a service which signs the data and provides me with the signed hash, it correctly generates PKCS#7 DigestInfo as stated in rfc2315#section-9.4
Something like this
The code for the above system is : https://pastebin.com/b3qZH6xW
//prepare signature
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("Ankit");
signature.setLocation("Bhopal, IN");
signature.setReason("Testing");
// TODO extract the above details from the signing certificate? Reason as a parameter?
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
if (accessPermissions == 0)
{
setMDPPermission(document, signature, 3);
}
FileOutputStream fos = new FileOutputStream(new File("signed_file.pdf"));
DetachedPkcs7 detachedPkcs7 = new DetachedPkcs7();
//populate signature options for visible signature. if any.
SignatureOptions signatureOptions = null;
document.addSignature(signature);
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(fos);
InputStream dataToSign = externalSigning.getContent();
byte[] cmsSignature = detachedPkcs7.sign(dataToSign);
externalSigning.setSignature(cmsSignature);
Workflow is something like this
- Grab original PDF
- add signature dictionary and get the hash
- send the hash to client
- Wait for data on Standard Input.
- Wait for Client to send the signed hash back, This data is then feeded
to the paused program, that is, the data is sent to standard input of the
program
- add the CMS. :)
I have no clue why the PDF generated using this process has the signature shown as invalid.
There are at least two problems in the client or the communication with it:
Wrong assumed hash algorithm in DigestInfo structure
The signature value returned by the client, when decrypted using the public key of the signer certificate, contains this
DigestInfo
structure:In particular it claims that SHA512 has been used to calculate the hash. Nonetheless it contains a digest value which is 32 bytes in length, which therefore cannot be a SHA512 digest value!
So your claim
either is incorrect or your code communicating with the service feeds it incorrect data.
Thus, please fix your client or client communication component to make them introduce the correct digest algorithm OID into the signed
DigestInfo
structure.Wrong hash value
Even if the above OID is corrected, the hash value in it is wrong, the correct SHA256 hash value of the signed ranges of your PDF is
Thus, please debug your tool chain to find out where the wrong hash value came from.
Appendix: The structure of the CMS container
Another shortcoming of your solution is that the structure of the generated CMS container is very simple. In particular it does not contain signed attributes at all. While this is allowed by the CMS specification, this is extremely insecure against numerous possible forging attacks. Therefore, hardly any CMS container profile in current specifications considers this kind of signature container valid.
Thus, unless your signed documents are used only in a very controlled environment with organisational measures preventing those forging attacks, their value is effectively nil.