0

I need to sign pdf document using external digest. This digest is signed in smart card, then signed digest is inserted into the document. Signed document contains rectangle with text but signature is invalid.

Adobe pdf reader says its "BER encoding problem" and doesn't even show certificate info, pdf studio viewer shows certificate info but says that "Document HAS been modified".

// Create reader & stamper
PdfReader pdfReader = new PdfReader("sample.pdf");
pdfReader.setAppendable(true);
FileOutputStream fileOutputStream = new FileOutputStream("out.pdf");
PdfStamper stp = PdfStamper.createSignature(pdfReader, fileOutputStream, '\0', null, true);

// Create the appearance
PdfSignatureAppearance sap = stp.getSignatureAppearance();
sap.setVisibleSignature(new Rectangle(0, 500, 100, 600), 1, "Signature1");
sap.setLayer2Text("Signed by " + certificate.getSubjectX500Principal().getName());
sap.setCertificate(certificate);
sap.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);

PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.setReason(sap.getReason());
dic.setLocation(sap.getLocation());
dic.setContact(sap.getContact());
dic.setDate(new PdfDate(sap.getSignDate()));
sap.setCryptoDictionary(dic);

// Create space in document for signature
Integer reservedSpace = 8192;
HashMap<PdfName, Integer> exc = new HashMap<>();
exc.put(PdfName.CONTENTS, reservedSpace * 2 + 2);
sap.preClose(exc);

// Create hash
byte[] sapBytes = IOUtils.toByteArray(sap.getRangeStream());
MessageDigest digest = MessageDigest.getInstance(DigestAlgorithms.SHA256);
byte[] hash = digest.digest(sapBytes);

// Create PKCS7 structure
ExternalDigest externalDigest = hashAlgorithm -> DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
PdfPKCS7 sgn = new PdfPKCS7(null, chain, DigestAlgorithms.SHA256, null, externalDigest, false);
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, MakeSignature.CryptoStandard.CMS);
sh = MessageDigest.getInstance(DigestAlgorithms.SHA256, "BC").digest(sh);

// Sign digest with private key (in smart card in real application)
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] signedHash = cipher.doFinal(sh);

// Prepare bytes for insertion into document
sgn.setExternalDigest(signedHash, null, "RSA");
byte[] encodedSign = sgn.getEncodedPKCS7(hash, null, null, null, MakeSignature.CryptoStandard.CMS);
byte[] paddedSig = new byte[reservedSpace];
System.arraycopy(encodedSign, 0, paddedSig, 0, encodedSign.length);

// Insert bytes into document
PdfDictionary dic2 = new PdfDictionary();
dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
sap.close(dic2);

I provide sample document signed using this code. It doesn't matter that it's signed without tsa or ocsp.

I tried different versions of itextpdf, but result was the same. Also I know there could be problem using big documents with IOUtils.toByteArray(), but ignore that for now.

Drifter
  • 85
  • 1
  • 7
  • You are encrypting, not signing, so the result can not be correct. I do not know if you are using the itext api correctly( see examples here (https://developers.itextpdf.com/examples/security/digital-signatures-white-paper/digital-signatures-chapter-4), but you need to replace the hashing+encryption code. – pedrofb Apr 09 '18 at 18:38
  • To my knowledge encrypting hash with private key is same as "signing" that hash. Following code results in idential output: `Signature signature = Signature.getInstance("NONEwithRSA");` `signature.initSign(privateKey);` `signature.update(sh);` `byte[] signedHash = signature.sign();` – Drifter Apr 09 '18 at 20:44
  • Please see https://crypto.stackexchange.com/questions/15997/is-rsa-encryption-of-a-cryptographic-hash-with-a-private-key-the-same-as-signatu – pedrofb Apr 09 '18 at 21:06
  • Your question is a duplicate insofar as the underlying issue is the difference between SHA256withRSA and NONEwithRSA applied to the pure SHA256 hash which exactly is the topic of [Difference between SHA256withRSA and SHA256 then RSA](https://stackoverflow.com/a/33311324/1729265). – mkl Apr 10 '18 at 08:05

0 Answers0