Following the answers given in this previous question : In Itext 7, how to get the range stream to sign a pdf?, i've tried to reimplement the two steps signing method working in Itext 5 but i encounter an issue when trying to reopen the document result of the first step (with the PdfReader or a pdf reader).(invalid document)
Here is the presigning part for a document already containing an empty signature field named certification ... why is the result of this step invalid ?
PdfReader reader = new PdfReader(fis); Path signfile = Files.createTempFile("sign", ".pdf"); FileOutputStream os = new FileOutputStream(signfile.toFile()); PdfSigner signer = new PdfSigner(reader, os, false); signer.setFieldName("certification"); // this field already exists signer.setCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING); PdfSignatureAppearance sap = signer.getSignatureAppearance(); sap.setReason("Certification of the document"); sap.setLocation("On server"); sap.setCertificate(maincertificate); BouncyCastleDigest digest = new BouncyCastleDigest(); PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest,false); //IExternalSignatureContainer like BlankContainer PreSignatureContainer external = new PreSignatureContainer(PdfName.Adobe_PPKLite,PdfName.Adbe_pkcs7_detached); signer.signExternalContainer(external, 8192); byte[] hash=external.getHash(); byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null,PdfSigner.CryptoStandard.CMS);// sh will be sent for signature And here is the PreSignatureContainer class :
public class PreSignatureContainer implements IExternalSignatureContainer { private PdfDictionary sigDic; private byte hash[]; public PreSignatureContainer(PdfName filter, PdfName subFilter) { sigDic = new PdfDictionary(); sigDic.put(PdfName.Filter, filter); sigDic.put(PdfName.SubFilter, subFilter); } @Override public byte[] sign(InputStream data) throws GeneralSecurityException { String hashAlgorithm = "SHA256"; BouncyCastleDigest digest = new BouncyCastleDigest(); try { this.hash= DigestAlgorithms.digest(data, digest.getMessageDigest(hashAlgorithm)); } catch (IOException e) { throw new GeneralSecurityException("PreSignatureContainer signing exception",e); } return new byte[0]; } @Override public void modifySigningDictionary(PdfDictionary signDic) { signDic.putAll(sigDic); } public byte[] getHash() { return hash; } public void setHash(byte hash[]) { this.hash = hash; } }