TCPDF icon indicating copy to clipboard operation
TCPDF copied to clipboard

Implement TimeStamping feature

Open hidasw opened this issue 2 years ago • 33 comments

Also add some file for parsing asn.1 data, and logging (debug only). should merged with main tcpdf.php but its not meet oop standar yet. still use procedural style.

hidasw avatar May 14 '23 10:05 hidasw

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar May 14 '23 10:05 CLAassistant

@williamdes i think this will be merged. :)

hidasw avatar Dec 05 '23 06:12 hidasw

@williamdes i think this will be merged. :)

did you get some news ?

williamdes avatar Dec 06 '23 19:12 williamdes

@williamdes i think this will be merged. :)

did you get some news ?

No, what news?

hidasw avatar Dec 08 '23 03:12 hidasw

No, what news?

None. So we still have to wait for more review by users that can merge this PR

williamdes avatar Dec 20 '23 10:12 williamdes

Hello. I need this feature. @hidasw are you willing to update your fork until this gets merged so my project can use the fork as a dependency?

csalzano avatar Mar 13 '24 18:03 csalzano

@csalzano There are no updates planned at this time. Still waiting for everyone's suggestions regarding what updates and features need to be made. Currently it works quite well with existing tcpdf signatures.

hidasw avatar Mar 15 '24 14:03 hidasw

Hi @hidasw

I would like to use this functionallity in my project and I identified a few lines that require adjustments.

I've just sent you some feedback on your code, but I'm unsure of the next steps. Should I perhaps suggest the changes via a pull request to your fork?

Thank you for your efforts.

evamtinez avatar Apr 15 '24 09:04 evamtinez

@evamtinez of course you are welcome

hidasw avatar Apr 15 '24 16:04 hidasw

@evamtinez of course you are welcome

I created a PR in your fork https://github.com/hidasw/TCPDF/pull/2

Feel free to give feedback or to make changes @hidasw 🙂

evamtinez avatar Apr 17 '24 07:04 evamtinez

Hello. I need this feature. @hidasw are you willing to update your fork until this gets merged so my project can use the fork as a dependency?

see example_052.php on my fork

hidasw avatar Apr 20 '24 16:04 hidasw

The latest update has support for LTV.

hidasw avatar Apr 22 '24 23:04 hidasw

Hi @hidasw,

I have noticed that the code does not validate the TSA URL at any point, and passing an invalid URL does not display any error. It simply does not apply the timestamp to the signature. I wanted to ask if this is a functionality planned to be added to the pull request.

Thanks

evamtinez avatar Jun 12 '24 07:06 evamtinez

@evamtinez Last time I checked the script was running fine on php 7.4. I haven't had time to test thoroughly on php 8 or php 5.4. What version of PHP are you currently using? For the display error problem, I can't display it in the output buffer because it will go into the PDF file (currently I haven't used the error handler in TCPDF). To view the log, it is in the '../signature.log' file in the TCPDF directory. Can be set in the tcpdf_cmssignature class by setting $writeLog which is true by default. To really make sure that there are no unhandled error notifications in the PDF file, please open the PDF file in a text editor and make sure there are no PHP error notifications in the PDF file.

hidasw avatar Jun 12 '24 09:06 hidasw

@evamtinez Last time I checked the script was running fine on php 7.4. I haven't had time to test thoroughly on php 8 or php 5.4. What version of PHP are you currently using? For the display error problem, I can't display it in the output buffer because it will go into the PDF file (currently I haven't used the error handler in TCPDF). To view the log, it is in the '../signature.log' file in the TCPDF directory. Can be set in the tcpdf_cmssignature class by setting $writeLog which is true by default. To really make sure that there are no unhandled error notifications in the PDF file, please open the PDF file in a text editor and make sure there are no PHP error notifications in the PDF file.

I'm using PHP 7.2.

I can see the log file correctly, but it would be helpful to get an error if the timestamp is invalid. For instance, if I set a timestamp to something like tsa.example.org (which doesn’t exist), the document appears to be signed correctly, and the process returns OK, but the PDF file doesn’t have the timestamp.

I’m handling this error in the class I'm using in my project, but I'm unsure if it needs to be directly integrated into the TCPDF library. In my implementation, before setting the timestamp, I call a validation function to check if the TSA is valid. However, this validation could be directly implemented in the setTimestamp function. What do you think?

Thanks

evamtinez avatar Jun 13 '24 09:06 evamtinez

@evamtinez Generally tsa is optional, so it's probably better to ignore it if it fails than to abort the entire signature.

I think so. Since first PR, I thought about providing an option to cancel the process if timestamp or LTV validation fails. But maybe this does not cancel the signature field/signature appearance that has been called, so it will provide null data in the signature which makes the signature invalid. I haven't tried it yet, maybe someday.

As a note, for the current version, if the validation process fails on one of certificate chains, then this certificate chain up to the root CA is not embedded in the pdf. (to be fixed in the next update). Thank's for suggestion.

hidasw avatar Jun 15 '24 16:06 hidasw

I am testing this fork and after I added the curl_setopt($ch, CURLOPT_USERPWD, 'username:password'); in the sendReq function (tcpdf_cmssignature.php) it successfuly requested the specified TSA, but I don't think the TSR was added correctly (I am testing the final pdf file with pdfsig utility though).

However, I would like to ask you if you have idea how to add ONLY the the timestamp signature, not the ID signiture /certificate?

rsvitak avatar Jul 25 '24 18:07 rsvitak

whats the mean "but I don't think the TSR was added correctly", is there a problem with tsresponse? About timestamp only, I see that Adobe reader can do it, but I have never tried with php script. I also don't understand what the timestamp is for without a digital signature.

hidasw avatar Jul 27 '24 14:07 hidasw

I am sorry for the late reply, I am struggling with this topic. Everything about PDF format and cryptography is new to me. What I am looking for perfectly demonstrates this: https://stackoverflow.com/questions/65807104/can-you-add-a-timestamped-no-tamper-proof-to-a-pdf-without-signing-it

My situation is: I have a working TSA, I am able to create a valid TSQ of a whole PDF file, send it to the TSA and I receive the valid TSR. As I am generating my PDF files in PHP (currently with DomPdf, but I believe I can switch to TCPDF) I am trying to get to the state the TSR is embedded into the PDF.

Currently I am able to embed the timestamp into the signiture, but as I have only a self generated certificate the acrobat says the validity of the signiture is unknown.

signinfo

Therefore my question is how to embed ONLY the RFC3161, i.e. /Type /DocTimeStamp object into the PDF.

I do appologize for chaotic and unprecise expressions but hopefully it's understandable what I mean.

rsvitak avatar Aug 06 '24 16:08 rsvitak

I was able to get access to an Adobe Acrobat, configure time stamp authority and sign a PDF document only with the DTS. Here is a screenshot how it's then displayed in Acrobat. This is what I need to achieve with TCPDF: dts

rsvitak avatar Aug 08 '24 15:08 rsvitak

I was finally ably to achieve the same result as when adding the TSA timestamp to the document by modifying (locally) this fork.

I made a dirty solution - added support to "special" signiture certificate (signature_data['signcert']) "DTS-ONLY" which turns the signing procedure to adding just the TSR response into the /Type /DocTimeStamp PDF section.

I modified these files: tcpdf.php:

7660c7660
<               if ($this->sign) {
---
>               if ($this->sign || !empty($this->signature_data_tsa)) {
13415a13416,13423
>               if ($this->signature_data['signcert']==='DTS-ONLY') {
>                       $out .= '<<'."\n".'/Filter /Adobe.PPKLite'."\n";
>                       $out .= '/SubFilter /ETSI.RFC3161'."\n";
>                       $out .= TCPDF_STATIC::$byterange_string."\n";
>                       $out .= '/Contents<'.str_repeat('0', $this->signature_max_length).'>'."\n";
>                       $out .= '/Type /DocTimeStamp'."\n";
>                       $out .= '/V 0'."\n";
>               } else {
13475a13484
>       }

include/tcpdf_cmssignature.php:

77a78
>     curl_setopt($ch, CURLOPT_USERPWD, $this->signature_data_tsa['username'].':'.$this->signature_data_tsa['password']);
425a429,430
> 
>     if ($this->signature_data['signcert']!=='DTS-ONLY') {
580a586,596
>    
>     } else {
>       $this->log .= ("info: DTS-ONLY starts ...\n");
>       if ($TSTInfo=self::createTimestamp($binaryData, $hashAlgorithm)) {
>          $this->log .= ("info: DTS-ONLY SUCCESS.\n");
>       } else {
>          $this->log .= ("info: DTS-ONLY FAILED!\n");
>       }
>       $pkcs7ContentInfo=$TSTInfo;
>     }
> 

I am signing my documents with this simple code now:

$pdf=new TCPDF();
$pdf->setSignature('DTS-ONLY', file_get_contents('postsignum_tsa_tsu1.pem'), '', '', 1, []);
$pdf->setTimeStamp(TSA_URL, TSA_USERNAME, TSA_PASSWORD);
$pdf->loadHtml($html);
$pdf->setSignatureAppearance(20,10,50,15);
$output=$pdf->Output($filename,'S');

I get results like this which is exactly what I wanted to achieve: obrazek

rsvitak avatar Aug 28 '24 13:08 rsvitak

I was finally ably to achieve the same result as when adding the TSA timestamp to the document by modifying (locally) this fork.

I made a dirty solution - added support to "special" signiture certificate (signature_data['signcert']) "DTS-ONLY" which turns the signing procedure to adding just the TSR response into the /Type /DocTimeStamp PDF section.

I modified these files: tcpdf.php:

7660c7660
<               if ($this->sign) {
---
>               if ($this->sign || !empty($this->signature_data_tsa)) {
13415a13416,13423
>               if ($this->signature_data['signcert']==='DTS-ONLY') {
>                       $out .= '<<'."\n".'/Filter /Adobe.PPKLite'."\n";
>                       $out .= '/SubFilter /ETSI.RFC3161'."\n";
>                       $out .= TCPDF_STATIC::$byterange_string."\n";
>                       $out .= '/Contents<'.str_repeat('0', $this->signature_max_length).'>'."\n";
>                       $out .= '/Type /DocTimeStamp'."\n";
>                       $out .= '/V 0'."\n";
>               } else {
13475a13484
>       }

include/tcpdf_cmssignature.php:

425a429,430
> 
>     if ($this->signature_data['signcert']!=='DTS-ONLY') {
580a586,596
>    
>     } else {
>       $this->log .= ("info: DTS-ONLY starts ...\n");
>       if ($TSTInfo=self::createTimestamp($binaryData, $hashAlgorithm)) {
>          $this->log .= ("info: DTS-ONLY SUCCESS.\n");
>       } else {
>          $this->log .= ("info: DTS-ONLY FAILED!\n");
>       }
>       $pkcs7ContentInfo=$TSTInfo;
>     }
> 

I am signing my documents with this simple code now:

$pdf=new TCPDF();
$pdf->setSignature('DTS-ONLY', file_get_contents('postsignum_tsa_tsu1.pem'), '', '', 1, []);
$pdf->setTimeStamp(TSA_URL, TSA_USERNAME, TSA_PASSWORD);
$pdf->loadHtml($html);
$pdf->setSignatureAppearance(20,10,50,15);
$output=$pdf->Output($filename,'S');

I get results like this which is exactly what I wanted to achieve: obrazek

Please, can I ask @rsvitak i see you use postsignum TSA. Please can you help me with URL to create on this. I cant go throw autenticatin process. Many thx... $pdf->setTimeStamp('https://tsa.postsignum.cz:444/TSS/HttpTspServer/', TSA_USERNAME, TSA_PASSWORD); ?? Many thx

KruzstofWren avatar Sep 11 '24 10:09 KruzstofWren

@KruzstofWren I had to update the list of changes I made to the @hidasw code in my comment above, thank you for tour post. This is neccessary to add to the sendReq function in the include/tcpdf_cmssignature.pdf to make the code send the autentication data to the server: curl_setopt($ch, CURLOPT_USERPWD, $this->signature_data_tsa['username'].':'.$this->signature_data_tsa['password']);

rsvitak avatar Sep 11 '24 11:09 rsvitak

@rsvitak Good news, you can add support for timestamp only. I don't know much about pdf structure. Maybe in the future it would be nice to add an option for timestamp only.

hidasw avatar Sep 11 '24 12:09 hidasw

@KruzstofWren I had to update the list of changes I made to the @hidasw code in my comment above, thank you for tour post. This is neccessary to add to the sendReq function in the include/tcpdf_cmssignature.pdf to make the code send the autentication data to the server: curl_setopt($ch, CURLOPT_USERPWD, $this->signature_data_tsa['username'].':'.$this->signature_data_tsa['password']);

Many thx for reaction. But still, in logs i have this fail...

info : Timestamping process start...info: sending TSA query to "https://tsa.postsignum.cz:444/TSS/HttpTspServer/"... info : TSA query OK info : Parsing Timestamp response...FAILED!

Something more i need edit?

KruzstofWren avatar Sep 11 '24 12:09 KruzstofWren

@KruzstofWren I had to update the list of changes I made to the @hidasw code in my comment above, thank you for tour post. This is neccessary to add to the sendReq function in the include/tcpdf_cmssignature.pdf to make the code send the autentication data to the server: curl_setopt($ch, CURLOPT_USERPWD, $this->signature_data_tsa['username'].':'.$this->signature_data_tsa['password']);

Many thx for reaction. But still, in logs i have this fail...

info : Timestamping process start...info: sending TSA query to "https://tsa.postsignum.cz:444/TSS/HttpTspServer/"... info : TSA query OK info : Parsing Timestamp response...FAILED!

Something more i need edit?

I can't test it since tsa uses authentication. But I can analyze it if I get the tsa response. You can save the response to a file. In the sendReq() function before return:

  $h = fopen('tsaResp.der','w');
  fwrite($h, $body);
  fclose($h);

parse the response with openssl: openssl asn1parse -i -inform der -in tsaResp.der

Let me know whats wrong.

hidasw avatar Sep 11 '24 13:09 hidasw

I have stored my modifications to https://github.com/rsvitak/TCPDF to avoid missunderstandings with description of my modifications in my post https://github.com/tecnickcom/TCPDF/pull/617#issuecomment-2315346099.

rsvitak avatar Sep 11 '24 13:09 rsvitak

@KruzstofWren I had to update the list of changes I made to the @hidasw code in my comment above, thank you for tour post. This is neccessary to add to the sendReq function in the include/tcpdf_cmssignature.pdf to make the code send the autentication data to the server: curl_setopt($ch, CURLOPT_USERPWD, $this->signature_data_tsa['username'].':'.$this->signature_data_tsa['password']);

Many thx for reaction. But still, in logs i have this fail... info : Timestamping process start...info: sending TSA query to "https://tsa.postsignum.cz:444/TSS/HttpTspServer/"... info : TSA query OK info : Parsing Timestamp response...FAILED! Something more i need edit?

I can't test it since tsa uses authentication. But I can analyze it if I get the tsa response. You can save the response to a file. In the sendReq() function before return:

  $h = fopen('tsaResp.der','w');
  fwrite($h, $body);
  fclose($h);

parse the response with openssl: openssl asn1parse -i -inform der -in tsaResp.der

Let me know whats wrong.

All is working great now. Only mistake is on my side....right URL for https://www.postsignum.cz is: https://www3.postsignum.cz/TSS/TSS_user/ Many thx to all, your are the best!

KruzstofWren avatar Sep 12 '24 07:09 KruzstofWren

If i may, last question. Do you think is much diference bettwen SIGN or CERTIFICATE document? Images are down ... I dont see any diference. Both document have timestamp...

obrazek

obrazek

KruzstofWren avatar Sep 12 '24 08:09 KruzstofWren

@KruzstofWren I am not very sure in this topic, but the difference could be in the authority that proves the "stamp"? Maybe if you could paste the "TCPDF" commands used to create the documents, or if you can provide the final PDF files, it would be easier to tell more...

rsvitak avatar Sep 13 '24 09:09 rsvitak