Hi, I have tried to certify a PDF with the provided code, but failed. This is the code I'm trying
final PrivateKey privateKey = ... final Certificate certificate = ... PDDocument doc = PDDocument.load(input); // PDSignature PDSignature signature = new PDSignature(); signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); signature.setReason("The reason"); signature.setName("The name"); signature.setSignDate(Calendar.getInstance()); // DocMDP thing COSDictionary dictionary = signature.getCOSObject(); //Create Permissions Dictionary COSDictionary permissions = new COSDictionary(); permissions.setItem("DocMDP", signature); //Add Permissions to Catalog COSDictionary catalog = doc.getDocumentCatalog().getCOSObject(); catalog.setItem("Perms", permissions); // Create a reference dictionary COSDictionary reference = new COSDictionary(); reference.setItem("Type", COSName.getPDFName("SigRef")); reference.setItem("TransformMethod", COSName.getPDFName("DocMDP")); reference.setItem("DigestMethod", COSName.getPDFName("SHA1")); // Now we add DocMDP specific stuff COSDictionary transformParameters = new COSDictionary(); transformParameters.setItem("Type", COSName.getPDFName("TransformParams")); transformParameters.setInt("P", 2); // transformParameters.setItem("V", COSName.getPDFName("1.2")); // Add everything in order reference.setItem("TransformParams", transformParameters); COSArray references = new COSArray(); references.add(reference); // Add SigRef Dictionary to a Array dictionary.setItem("Reference", references); // Add Array to Signature // dictionary // From CreateSignature.java example // register signature dictionary and sign interface doc.addSignature(signature, new SignatureInterface() { @Override public byte[] sign(InputStream content) throws IOException { try { List<Certificate> certList = new ArrayList<Certificate>(); certList.add(certificate); Store certs = new JcaCertStore(certList); CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate .getInstance(ASN1Primitive.fromByteArray(certificate.getEncoded())); ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey); gen.addSignerInfoGenerator( new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()) .build(sha1Signer, new X509CertificateHolder(cert))); gen.addCertificates(certs); CMSProcessableInputStream msg = new CMSProcessableInputStream(content); CMSSignedData signedData = gen.generate(msg, false); /* * if (tsaClient != null) { signedData = * signTimeStamps(signedData); } */ return signedData.getEncoded(); } catch (GeneralSecurityException e) { throw new IOException(e); } catch (CMSException e) { throw new IOException(e); // } catch (TSPException e) { // throw new IOException(e); } catch (OperatorCreationException e) { throw new IOException(e); } } }); // doc.save(output); doc.close(); When I open the PDF in Acrobat [image: Inline image 1] I compared a PDF certified with a paid library and the one generated with my code. There is a difference in *contents, *and the *byte ranges* are wrong. Left paid library, right the code example [image: Inline image 2] The SignatureInterface implementation is the one from CreateSignature.java example. Thanks in advance, Jonathan. On Wed, Oct 19, 2016 at 11:03 AM, Damien Butaye <damien.but...@gmail.com> wrote: > Diego, > > One more times, thanks a lot. I just add the following part of your code > and it works! : > > > > > > > > > * //Create Permissions Dictionary COSDictionary permissions = > new COSDictionary(); permissions.setItem("DocMDP", signature); > //Add Permissions to Catalog COSDictionary catalog = > document.getDocumentCatalog().getCOSObject(); > catalog.setItem("Perms", permissions);* > > Many Thanks! > Damien. > > 2016-10-19 15:43 GMT+02:00 Diego Azevedo <dazev...@esec.com.br>: > > > Ok, I searched for "DocMDP" on ISO 32000 and found this: > > > > * On a 'Signature Field Dictionary', one *could *have a 'Seed Value > > Dictionary' with a 'MDP entry' > > o This entry *shall *have a dictionary with only one entry: 'P' > > and a integer value <0-3>: > > + 0 - Author Signature > > + 1-3 - Same meaning from the P entry on the DocMDP Transform > > Parameters Dictionary > > * A certification Signature *may *be referenced from the DocMDP entry > > in the Permissions Dictionary > > o The signature Dictionary *shall *contain a signature reference > > dictionary with the DocMDP transform method > > o It *should *have a Legal Attestation Dictionary > > o It *shall *be the first signed field in the document > > > > There where a few specific things about these entries and dictionaries, > > but these are the changes that should be made from the beginning: > > > > * Create the Signature Reference Dictionary and add it to the > > signature - OK > > * Create a Permissions Dictionary and add it to Catalog: > > > > //Create Permissions Dictionary > > COSDictionary permissions = new COSDictionary(); > > permissions.setItem("DocMDP", signature); > > > > //Add Permissions to Catalog > > COSDictionary catalog = > > document.getDocumentCatalog().getCOSObject(); > > catalog.setItem("Perms", permissions); > > > > * Create a Legal Attestation Dictionary and add it to catalog: > > > > //Create Legal Attestation Dictionary (I'd totally leave this > > out on my implementation - Way too much trouble for something > > optional) > > COSDictionary legalAttestation= new COSDictionary(); > > <All entries are optional, and are like this:> > > legalAttestation.setInt("JavaScriptActions", 10);// Means there > > are 10 Javascript actions > > legalAttestation.setInt("LaunchActions", 10);// Means there are > > 10 Launch actions > > [...] > > > > //Add Permissions to Catalog > > COSDictionary catalog = > > document.getDocumentCatalog().getCOSObject(); > > catalog.setItem("Legal", legalAttestation); > > > > * Create a Seed Value Dictionary and add it to the Signature Field > > Dictionary > > o The Signature Field Dictionary is manipulated by pdfbox itself > > on document.addSignature. So, if necessary, it would be > > something like this that would be changed in the source code: > > > > //Get the references > > COSArray references = (COSArray) > > signature.getCOSObject().getItem("Reference"); > > COSDictionary reference = null; > > if( references != null){ > > > > // loop all references, looking for a DocMDP TransformMethod > > for(int i = 0; i< references.size(); i++){ > > > > reference = (COSDictionary) references.getObject(i); > > if(reference.getNameAsString(" > TransformMethod").equals("Doc > > MDP")){ > > > > // if it is a DocMDP, it shall heve TransformParams > > as a integer > > COSDictionary transform = (COSDictionary) > > reference.getItem("TransformParams"); > > int pEntry = transform.getInt("P"); > > > > //Add to the SeedValue Dictionary > > PDSeedValue seedValue = ?; //How to get the > > SeedValue? Should we create a new one? - Only > > someone from the project could tell you that (along > > with where this code should be placed) > > PDSeedValueMDP mdp = new PDSeedValueMDP(); > > mdp.setP(pEntry); > > seedValue.setMPD(mdp); > > > > } > > > > } > > > > } > > > > I only saw your reply now. The document you sent me only did the first > > change (permissions Dictionary). Try it and tell me if it worked > > > > []'s > > > > Diego Azevedo > > > > > > On 19/10/2016 09:25, Diego Azevedo wrote: > > > >> Damien, > >> > >> Can you upload a correctly certified PDF somewhere and share the link? > >> Wîth the original one, if possible? > >> > >> I'll try to mimic the behavior. > >> > >> []'s > >> > >> Diego Azevedo > >> > >> On 19/10/2016 07:10, Damien Butaye wrote: > >> > >>> In some Java code of different PDF Signatue framework, I saw the use of > >>> the > >>> "Perms" dictionnary to certify PDF. Do you have any idea if the "Perms" > >>> can > >>> help to see the blue ribbon? > >>> > >>> 2016-10-19 10:48 GMT+02:00 Damien Butaye <damien.but...@gmail.com>: > >>> > >>> Yes but in my case my certificate has the authorization to certify > >>>> document (the cross is green beside the "Certify Document" in your > >>>> previous > >>>> printscreen). > >>>> I wonder me if another information must be present in the PDF to show > >>>> the > >>>> blue ribbon?! > >>>> > >>>> 2016-10-18 17:40 GMT+02:00 Diego Azevedo <dazev...@esec.com.br>: > >>>> > >>>> No, but in my case it would never happen, because my certificate is > >>>>> trusted for signing, but not certifying: > >>>>> > >>>>> Image: http://imgur.com/XYZCB8H > >>>>> > >>>>> []'s > >>>>> > >>>>> Diego Azevedo > >>>>> > >>>>> On 18/10/2016 13:30, Damien Butaye wrote: > >>>>> > >>>>> One last question, have you got the "blue ribbon" on the top the pdf > >>>>>> when you open it with Acrobat? In my case not, although it is well > >>>>>> certified as shown in the Acrobat Signature Panel. > >>>>>> > >>>>>> > >>>>>> > >>>>>> 2016-10-18 15:58 GMT+02:00 Damien Butaye <damien.but...@gmail.com > >>>>>> <mailto:damien.but...@gmail.com>>: > >>>>>> > >>>>>> Nice! Thank you very much! > >>>>>> > >>>>>> (Btw, it could be nice to integrate in a future release a > method > >>>>>> certify() in the PDSignature object). > >>>>>> > >>>>>> obrigado! > >>>>>> > >>>>>> 2016-10-18 15:42 GMT+02:00 Diego Azevedo <dazev...@esec.com.br > >>>>>> <mailto:dazev...@esec.com.br>>: > >>>>>> > >>>>>> Hello Damien, > >>>>>> > >>>>>> I made a typo: > >>>>>> > >>>>>> dictionary.setItem("Reference", reference_*s*_); // > Add > >>>>>> Array to Signature dictionary > >>>>>> > >>>>>> There is no point in creating the array, add the "SigRef" > >>>>>> dictionary to it... and not use the array on the "Sig" > >>>>>> dictionary. So... just add the 'S' to the variable and > >>>>>> re-run > >>>>>> it. Just tested here, and it worked fine =) > >>>>>> > >>>>>> []'s > >>>>>> > >>>>>> > >>>>>> -- *_______________________________________________ > >>>>>> > >>>>>> Diego Azevedo > >>>>>> Developer > >>>>>> E-SEC Segurança Digital > >>>>>> www.esec.com.br <http://www.esec.com.br> > >>>>>> +55 61 3323-4410 <tel:%2B55%2061%203323-4410>* > >>>>>> > >>>>>> > >>>>>> On 18/10/2016 10:21, Damien Butaye wrote: > >>>>>> > >>>>>> Hello Diego, > >>>>>>> > >>>>>>> Thank you for your help. I just tried your code but it > >>>>>>> seems > >>>>>>> that it doesn't work. The result has nor signature nor > >>>>>>> certify element. I'll try again. > >>>>>>> If you have any idea, don't hesitate ;) > >>>>>>> > >>>>>>> Damien. > >>>>>>> > >>>>>>> 2016-10-18 13:04 GMT+02:00 Diego Azevedo > >>>>>>> <dazev...@esec.com.br <mailto:dazev...@esec.com.br>>: > >>>>>>> > >>>>>>> > >>>>>>> From what I'm reading on ISO 32000, the certification > >>>>>>> Signature is a normal signature, but with a DocMDP > >>>>>>> transform method. So the ou should do something like > >>>>>>> this: > >>>>>>> > >>>>>>> PDSignature signature = new PDSignature; > >>>>>>> [..] //do your thing > >>>>>>> COSDictinary dictionary = > signature.getCOSObject(); > >>>>>>> > >>>>>>> //Create a reference dictionary > >>>>>>> COSDictionary reference = new COSDictionary(); > >>>>>>> reference.setItem("Type", > >>>>>>> COSName.getPDFName("SigRef")); > >>>>>>> reference.setItem("TransformMethod", > >>>>>>> COSName.getPDFName("DocMDP")); > >>>>>>> reference.setItem("DigestMethod", > >>>>>>> COSName.getPDFName("SHA1")); //Only MD5 or SHA1... > >>>>>>> Go > >>>>>>> with the least worse > >>>>>>> > >>>>>>> //Now we add DocMDP specific stuff > >>>>>>> COSDictionary transformParameters = new > >>>>>>> COSDictionary(); > >>>>>>> transformParameters.setItem("Type", > >>>>>>> COSName.getPDFName("TransformParams")); > >>>>>>> transformParameters.setInteger("P", <1, 2 or 3>); > >>>>>>> // > >>>>>>> 1- no changes permited; 2- fill forms and signing; > >>>>>>> 3- > >>>>>>> Same as 2 plus annotation creation, deletion an > >>>>>>> modification. > >>>>>>> transformParameters.setItem("V", > >>>>>>> COSName.getPDFName("1.2")); // This is right, > it's a > >>>>>>> name, not a number. > >>>>>>> > >>>>>>> // Add everything in order > >>>>>>> reference.setItem("TransformParams", > >>>>>>> transformParameters ); // Add DocMDP stuff to the > >>>>>>> SigRef Dictionary; > >>>>>>> COSArray references = new COSArray(); > >>>>>>> references.add(reference); // Add SigRef > Dictionary > >>>>>>> to a Array > >>>>>>> dictionary.setItem("Reference", reference); // > Add > >>>>>>> Array to Signature dictionary > >>>>>>> > >>>>>>> I didn't try it myself, just wrote based on PdfBox API > >>>>>>> and ISO specification. May have errors. > >>>>>>> > >>>>>>> On 18/10/2016 06:12, Damien Butaye wrote: > >>>>>>> > >>>>>>> Hello Tilman, > >>>>>>>> > >>>>>>>> Here follows two links explaining the difference : > >>>>>>>> > >>>>>>>> > >>>>>>>> 1.http://www.investintech.com/ > >>>>>>>> resources/articles/certifyingsigningpdf/ > >>>>>>>> <http://www.investintech.com/r > >>>>>>>> esources/articles/certifyingsigningpdf/> > >>>>>>>> 2. > >>>>>>>> http://stackoverflow.com/quest > >>>>>>>> ions/16710439/how-to-add-blank-page-in-digitally-signed-pdf- > >>>>>>>> using-java/16711745#16711745 > >>>>>>>> <http://stackoverflow.com/ques > >>>>>>>> tions/16710439/how-to-add-blank-page-in-digitally-signed-pdf > >>>>>>>> -using-java/16711745#16711745>Damien. > >>>>>>>> 2016-10-18 8:49 GMT+02:00 Tilman Hausherr > >>>>>>>> <thaush...@t-online.de> <mailto: > thaush...@t-online.de> > >>>>>>>> : > >>>>>>>> > >>>>>>>> Dear all, > >>>>>>>>> > >>>>>>>>> I'm looking for a solution to certify a PDF. > >>>>>>>>>> Currently I'm able to > >>>>>>>>>> sign a > >>>>>>>>>> PDF using PDFBox but I can't certify it. Is-it > >>>>>>>>>> possible > >>>>>>>>>> to do it with > >>>>>>>>>> PDFBox? > >>>>>>>>>> > >>>>>>>>>> > >>>>>>>>>> Thank you for your help! > >>>>>>>>>> > >>>>>>>>>> What's the difference? (See my other answer from > >>>>>>>>>> today) > >>>>>>>>>> > >>>>>>>>> Tilman > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> ------------------------------ > >>>>>>>>> --------------------------------------- > >>>>>>>>> To unsubscribe, e-mail:users-unsubscribe@pdfbo > >>>>>>>>> x.apache.org > >>>>>>>>> <mailto:users-unsubscr...@pdfbox.apache.org> > >>>>>>>>> For additional commands, > >>>>>>>>> e-mail:users-help@pdfbox.apach > >>>>>>>>> e.org > >>>>>>>>> <mailto:users-h...@pdfbox.apache.org> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >> >