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 Wed, 19 Oct 2016 19:09:32 GMT
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.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>*
> >>>>>>
> >>>>>>
> >>>>>>          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>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>
>

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