Hello Jonathan, Try also to use doc.saveIncremental(out) instead of doc.save(out)
Le 19 oct. 2016 23:01, "Diego Azevedo" <dazev...@esec.com.br> a écrit : > Hello Jonathan, > > After 'dictionary.setItem("Reference", references);' line, add: > > //Create Permissions Dictionary > COSDictionary permissions = new COSDictionary(); > permissions.setItem("DocMDP", signature); > > //Add Permissions to Catalog > COSDictionary catalog = document.getDocumentCatalog().getCOSObject(); > catalog.setItem("Perms", permissions); > > It is expected to see a difference in Contents and byteRange using > different libraries, since they may or may not use references, spaces or > line breaks the same way. > []'s > > Diego Azevedo > > On 19/10/2016 17:09, Jonathan Barbero wrote: > > 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 JcaDigestCalculatorProviderBui > lder().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> >> <%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> >> >>>>>>>>> >> >>>>>>>>> >> >>>>>>>>> >> >>>>>>>>> >> >> >> > > > -- > > > > > > > *_______________________________________________ Diego Azevedo > Desenvolvedor E-SEC Segurança Digital www.esec.com.br > <http://www.esec.com.br> 61 3323-4410* > > > Os dados transmitidos, incluindo quaisquer anexos, são destinados apenas > para a pessoa ou entidade ao qual está endereçada e pode conter material > confidencial e/ou privilegiado. É proibida qualquer revisão, retransmissão, > disseminação ou outro uso desta informação, ou a tomada de qualquer ação > com base na confiança, por pessoas ou empresas que não o destinatário, e > qualquer responsabilidade daí decorrente é negada. Se você recebeu por > engano, favor contatar o remetente e apague o material de qualquer > computador > > The information transmitted, including any attachments, is intended only > for the person or entity to which it is addressed and may contain > confidential and/or privileged material. Any review, retransmission, > dissemination or other use of, or taking of any action in reliance upon, > this information by persons or entities other than the intended recipient > is prohibited, and all liability arising therefrom is disclaimed. If you > received this in error, please contact the sender and delete the material > from any computer > >