pdfbox-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jonathan Barbero <jonathan.barb...@gmail.com>
Subject Re: How to certify a PDF
Date Thu, 20 Oct 2016 17:42:27 GMT
Great!

The problema was

doc.save(...)

Now the PDF is certified.

I would like to be LTV also.
What are the things that make a signature LTV ?

Thank you Damien and Diego!

On Wed, Oct 19, 2016 at 6:09 PM, Damien Butaye <damien.butaye@gmail.com>
wrote:

> Hello Jonathan,
>
> Try also to use doc.saveIncremental(out) instead of doc.save(out)
>
> Le 19 oct. 2016 23:01, "Diego Azevedo" <dazevedo@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("TransformP
>> arams"));
>> 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("SHA25
>> 6WithRSA").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.butaye@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 <dazevedo@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.butaye@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 <dazevedo@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.butaye@gmail.com
>>> >>>>>> <mailto:damien.butaye@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 <
>>> dazevedo@esec.com.br
>>> >>>>>>      <mailto:dazevedo@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
>>> >>>>>>>          <dazevedo@esec.com.br <mailto:dazevedo@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
>>> >>>>>>>>              <THausherr@t-online.de> <mailto:
>>> THausherr@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-unsubscribe@pdfbox.apache.org>
>>> >>>>>>>>>              For additional commands,
>>> >>>>>>>>> e-mail:users-help@pdfbox.apach
>>> >>>>>>>>> e.org
>>> >>>>>>>>> <mailto:users-help@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
>>
>>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message