pdfbox-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tilman Hausherr <THaush...@t-online.de>
Subject Re: External signature in 2 steps
Date Wed, 09 Nov 2016 21:55:20 GMT
Am 07.11.2016 um 16:10 schrieb Fabricio Pombo Koch:
> Indenting...

Thanks... problem with this code is that it reads all locally. So this 
could be a problem with bigger files. I was thinking of writing directly 
into the existing file with some random access file class, but haven't 
tried it myself. I'll work on that one when I have more time.

Tilman


>
>    public void replaceEmptySignature(String inPDF, String outPDF, byte[] realSignature)
throws IOException {
>      File inFile = new File(inPDF);
>      PDDocument doc = PDDocument.load(inFile);
>      PDSignature signature = doc.getLastSignatureDictionary();
>      int[] br = signature.getByteRange();
>      doc.close();
>      FileInputStream fis = new FileInputStream(inFile);
>      File outFile = new File(outPDF);
>      FileOutputStream fos = new FileOutputStream(outFile);
>      byte[] newSignature = Hex.getBytes(realSignature);
>      byte[] initial = new byte[br[1] + 1];
>      fis.read(initial, 0, initial.length);
>      fis.skip(newSignature.length);
>      fos.write(initial, 0, initial.length);
>      fos.write(newSignature, 0, newSignature.length);
>      boolean itsOver = false;
>      while (!itsOver) {
>        int b = fis.read();
>        if (b != -1) {
>        fos.write(b);
>        } else {
>        itsOver = true;
>        }
>      }
>      fis.close();
>      fos.close();
>    }
>
>
> *If you have a better way to share the code, just tell me.
>
> Att,
> Fabricio P Koch
>
>      Em Segunda-feira, 7 de Novembro de 2016 13:05, Fabricio Pombo Koch <fabriciokoch@yahoo.com.br.INVALID>
escreveu:
>   
>
>   Tilman,
>
> here is the piece of code that I'm using:
>
>    public void replaceEmptySignature(String inPDF, String outPDF, byte[] realSignature)
throws IOException {    File inFile = new File(inPDF);    PDDocument doc = PDDocument.load(inFile);
   PDSignature signature = doc.getLastSignatureDictionary();    int[] br = signature.getByteRange();
   doc.close();    FileInputStream fis = new FileInputStream(inFile);    File outFile = new
File(outPDF);    FileOutputStream fos = new FileOutputStream(outFile);    byte[] newSignature
= Hex.getBytes(realSignature);    byte[] initial = new byte[br[1] + 1];    fis.read(initial,
0, initial.length);    fis.skip(newSignature.length);    fos.write(initial, 0, initial.length);
   fos.write(newSignature, 0, newSignature.length);    boolean itsOver = false;    while (!itsOver)
{      int b = fis.read();      if (b != -1) {      fos.write(b);      } else {      itsOver
= true;      }    }    fis.close();    fos.close();  }
>
>
> Att,
> Fabricio P Koch
>
>   
>
>      Em Sábado, 5 de Novembro de 2016 12:10, Tilman Hausherr <THausherr@t-online.de>
escreveu:
>   
>
>   Am 03.11.2016 um 20:19 schrieb Fabricio Pombo Koch:
>> Tilman
>> thank you for your effort, but the update doesn't actually help me.
>> I add the signature object (name, location, reason), save incremental for external
signature, then I add the empty signature and save the file on disk. Now, I could get the
ByteRange with before saving the file, but I don't have a place to store it. It's easier to
get it from the saved file in the 2nd step.
>>
>> In the 2nd step, I load the pdf as a PDDocument, get the last signature and get the
ByteRange.
>>    Anyways, your comment made it more clear to understand that we must provide an
empty signature to make it all works.
>>
>>
>> I guess that the following features would be nice:
>> - No need to add the empty signature byte array;
>> - A method from PDFBOX to replace the empty signature with the valid signature;
>>
>> I don't know if it's possible, but the first time I tried to add the signature object,
get the file content for signature and discard the changes. In the second step, I added the
signature object with the same info, save incremental for external signature, add the signature
and save the file. The signature got invalid. I guess the signature object has some Date/Time
related info.
> The method that gets the empty array is also saving, that's the problem.
>
> Re method to replace the signature: the problem is that this can't be
> done in PDFBox. If you'd just set it on the COS level and save, the
> signature wouldn't be valid. So what we need is something that does it
> on the file level. Feel free to contribute your code. Probably something
> with RandomAccessFile.
>
> Tilman
>
>
>> Thanks once more,Fabricio P Koch
>>    
>>
>>        Em Quarta-feira, 2 de Novembro de 2016 16:05, Tilman Hausherr <THausherr@t-online.de>
escreveu:
>>    
>>
>>    Am 28.10.2016 um 17:10 schrieb Fabricio Pombo Koch:
>>> Tilman,
>>> thanks to your help I was able to make it works.
>>>
>>> But, I had to add a empty signature hash to get it working. Like this:externalSigning.setSignature(new
byte[100]);
>>>
>>> Otherwise, the PDFBox would create a empty file after closing the document.And
I needed to save the file, because the ByteRange wasn't with the right value before saving.
Its value was something like this:0 1000000000000 1000000000000 1000000000000
>>> So, here is what I did:
>>> - Followed the CreateSignature example to get the content for my signature service
and added a empty signature before closing the PDDocument;- The first step created a PDF with
an invalid signature (an empty one);- Signed the content with my signature service;- Then,
I loaded the PDDocument, got the last signature, got the ByteRange and then, closed the PDDocumento;-
With the ByteRange in hands, I was able to open the PDF (with the empty signature) and replace
the empty signature with the real signature;
>> Hello Fabricio,
>>
>> I've now updated PDFBox as explained, also added a comment in the
>> "visible" example explaining my suggestion plus your important remark
>> (must add a dummy signature).
>>
>> This has been done in
>> https://issues.apache.org/jira/browse/PDFBOX-3552
>>
>> You can access a snapshot at
>> https://repository.apache.org/content/groups/snapshots/org/apache/pdfbox/pdfbox-app/2.0.4-SNAPSHOT/
>>
>> Please test it and give feedback, i.e. that you can now skip the
>> "middle" step, i.e. you can now get the byterange immediately after
>> adding your dummy signature.
>>
>> Don't hesitate to tell whether my comment in the "visible" example is
>> confusing or unclear.
>>
>> Tilman
>>
>>
>>> Thanks again Tilman.
>>>
>>> Att,Fabricio P Koch
>>>
>>>      
>>>
>>>          Em Quinta-feira, 27 de Outubro de 2016 15:24, Fabricio Pombo Koch <fabriciokoch@yahoo.com.br.INVALID>
escreveu:
>>>      
>>>
>>>      Tilman,
>>> I'm gonna try it. And I'm sorry about the indentation of my last e-mail.
>>> Thank you again!Fabricio P Koch
>>>
>>>          Em Quinta-feira, 27 de Outubro de 2016 14:49, Tilman Hausherr <THausherr@t-online.de>
escreveu:
>>>      
>>>
>>>      Am 27.10.2016 um 15:18 schrieb Fabricio Pombo Koch:
>>>> Tilman, thanks for your reply.
>>>> I'm not familiarized with PDF structure, this way, I don't know how to insert
the signature manually into the PDF.
>>>> This code works for me to sign in "one step":
>>>> File inFile = new File("IN_PDF_FILE");PDDocument doc = PDDocument.load(inFile);PDSignature
signature = new PDSignature();signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);signature.setName("USERNAME");signature.setLocation("LOCATION");signature.setReason("TESTING");doc.addSignature(signature);File
outFile = new File("OUT_PDF_FILE");FileOutputStream fos = new FileOutputStream(outFile);ExternalSigningSupport
externalSigning = doc.saveIncrementalForExternalSigning(fos);MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[]
content= IOUtils.toByteArray(externalSigning.getContent());byte[] hash = digest.digest(content);externalSigning.setSignature(VALUE_RETURNED_FROM_MY_SIGNATURE_SERVICE);doc.close();
>>>>
>>>> But, I can't  run the following line because I recieve the "VALUE_RETURNED_FROM_MY_SIGNATURE_SERVICE"
value in a future time:externalSigning.setSignature(VALUE_RETURNED_FROM_MY_SIGNATURE_SERVICE);
>>>> So, I tried using all that code, except the "externalSigning.setSignature"
method. Then, in my 2nd step, I wrote it all again (from PDDocumento.load() until doc.close()).It
sign the file, but the signature is invalid.
>>> What you have to do is to access the PDF file, seek to the appropriate
>>> position, and then write the hex string of your signature.
>>>
>>> If the byterange is
>>>
>>> 0 61887 65989 21205
>>>
>>> then go to 61888, and write there.
>>>
>>> To get the byte range, as I explained yesterday, you need to access the
>>> PDF file with PDFBox again earlier but after the (unfinished) "signing",
>>> get the field (you know its name), and then the signature, then the
>>> ByteRange ( signature.getByteRange() ). Close again.
>>>
>>> So:
>>> 1) unfinished sign, close
>>> 2) reload with pdfbox to get the byte range, close
>>> 3) reload with random access class, access appropriate position, write
>>> sig in ascii hex, close
>>>
>>> I can't give much help now because I'm busy until mid next week.
>>>
>>> Tilman
>>>
>>>
>>>> It would be nice If you create the new feature.Meanwhile, how could I add
the signature manually? I have no idea.
>>>>
>>>> Thanks,Fabricio P Koch
>>>>
>>>> ---------------------------------------------------------------------------------------------------------------------------
>>>>
>>>> From: Tilman Hausherr <T...@t-online.de>Subject: Re: External signature
in 2 stepsDate: 2016-10-26 18:43 (-0200)List: users@pdfbox.apache.orgAm 26.10.2016 um 21:53
schrieb Fabricio Pombo Koch:show/hide original textYou would have to use the new "external"
strategy that exists since 2.0.3, but without writing the signature. Before closing, get the
ByteRange from the signature object.
>>>> HOWEVER... that one isn't available, because after being calculated the ByteRange
isn't assigned back to the PDFBox structure.
>>>> (Open a signed PDF with NOTEPAD++ and search for ByteRange to understand
what II mean)
>>>> So you'd have to reload the PDF; get the field (you know its name), and then
the signature, then the ByteRange ( signature.getByteRange() ). Close again.
>>>> Then write the signature that you got at the appropriate place in the file.
This can be done without PDFBox.
>>>> I could do a change that you can access the byte range, i.e. don't have to
reload the PDF just to get the byte range. However this will have to wait until mid next week,
because I wouldn't have the time to become active if it doens't work. (Although I just tested
it).
>>>> Tilman
>>>> ---------------------------------------------------------------------To unsubscribe,
e-mail: users-unsubscribe@pdfbox.apache.orgFor additional commands, e-mail: users-help@pdfbox.apache.org
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@pdfbox.apache.org
>>> For additional commands, e-mail: users-help@pdfbox.apache.org
>>>
>>>
>>>
>>>        
>>>
>>>        
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@pdfbox.apache.org
>> For additional commands, e-mail: users-help@pdfbox.apache.org
>>
>>
>>
>>      
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@pdfbox.apache.org
> For additional commands, e-mail: users-help@pdfbox.apache.org
>
>
>
>    
>
>     



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: users-help@pdfbox.apache.org


Mime
View raw message