@@ -1274,8 +1274,7 @@ class TCPDF {
12741274 * @protected
12751275 * @since 4.6.005 (2009-04-24)
12761276 */
1277- // protected $signature_max_length = 11742;
1278- protected $signature_max_length = 20742;
1277+ protected $signature_max_length = 16742;
12791278
12801279 /**
12811280 * Data for digital signature appearance.
@@ -13646,7 +13645,7 @@ protected function getSignatureAppearanceArray($x=0, $y=0, $w=0, $h=0, $page=-1,
1364613645 * @since 6.0.090 (2014-06-16)
1364713646 */
1364813647 // other options suggested to be implement: reqPolicy, nonce, certReq, extensions
13649- // Also option to abort signing if timestamping failed and LTV enable (embed crl and or ocsp revocation info)
13648+ // and option to abort signing if timestamping failed and LTV enable (embed crl and or ocsp revocation info)
1365013649 public function setTimeStamp($tsa_host='', $tsa_username='', $tsa_password='', $tsa_cert='') {
1365113650 $this->tsa_data = array();
1365213651 if (!function_exists('curl_init')) {
@@ -13679,128 +13678,51 @@ protected function applyTSA($signature) {
1367913678 if (!$this->tsa_timestamp) {
1368013679 return $signature;
1368113680 }
13682- //@TODO: implement this feature
13683- // start timestamping
13684- // by Hida (16 Mei 2023)
13685-
13686- // Include minimum asn.1 fuctional script
13681+ // * @author Hida
1368713682 require_once(dirname(__FILE__).'/include/tcpdf_asn1.min.php');
13688-
1368913683 // Parse TCPDF's pkcs#7 Signature structure to get sequence of signed hash
1369013684 $pkcs7 = asn1parse($signature);
1369113685 $pkcs7ContentInfo = asn1parse($pkcs7[0][1]);
13692-
1369313686 $pkcs7content = asn1parse($pkcs7ContentInfo[1][1]);
13694-
1369513687 $pkcs7SignedData = asn1parse($pkcs7content[0][1]);
13696-
1369713688 $pkcs7signerInfos = asn1parse($pkcs7SignedData[4][1]);
13698-
1369913689 $SignerInfo = asn1parse($pkcs7signerInfos[0][1]);
13700-
1370113690 $pkcs7EncryptedDigest = $SignerInfo[5][1];
1370213691
1370313692 // Create timestamp request
13704-
13705- // Create hash of encrypted contents TCPDF signature
13706- // $this->setTimeStamp() have no options for change tsa req hash alg yet, so sha1 selected
1370713693 $hash = hash('sha1', hex2bin($pkcs7EncryptedDigest));
13708-
13709- // Build timestamp request data
13710- $tsReqData = seq(
13711- int(1).
13712- seq(
13713- seq(
13714- "06052B0E03021A". // Obj_sha1
13715- "0500" // Null
13716- ).
13717- oct($hash)
13718- ).
13719- int(hash('crc32', rand())). // Add random nonce request
13720- '0101ff' // set certReq true to tell TSA server to include SigningCertificate
13721- );
13722-
13723- $raw_data = hex2bin($tsReqData);
13724-
13725- //Send request to TSA Server with Curl
13726- if(extension_loaded('curl')) {
13727- $ch = curl_init();
13728- curl_setopt($ch, CURLOPT_URL, $this->tsa_data['tsa_host']);
13729- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
13730- curl_setopt($ch, CURLOPT_POST, 1);
13731- curl_setopt($ch, CURLOPT_HTTPHEADER, array(
13732- 'Content-Type: application/timestamp-query',
13733- 'User-Agent: TCPDF'
13734- )
13735- );
13736- curl_setopt($ch, CURLOPT_POSTFIELDS, $raw_data);
13737-
13738-
13739- // can't send tsRequest, Timestamp failed!
13740- if(!$tsResponse = curl_exec($ch)) {
13741- return $signature;
13742- }
13743-
13744- // parse timestamp response data
13745- $hexTsaResponse = bin2hex($tsResponse);
13746- if(!$parseTimeStampResp = asn1parse($hexTsaResponse)) { // bad TSA Reponse
13747- return $signature;
13748- }
13749-
13750- // verify tsa response PKIStatusInfo and TimeStampToken exists
13751- if(!$TimeStampResp = asn1parse($parseTimeStampResp[0][1])) {
13752- return $signature;
13753- }
13754-
13755- // Select timeStampToken only. must ignore response status data (in first sequence if exist, select 2nd sequence)
13756- if(count($TimeStampResp) > 1) {
13757- $TSTInfo = $TimeStampResp[1][1]; // TSTInfo
13758- } else if (count($TimeStampResp) == 1) {
13759- $TSTInfo = $TimeStampResp[0][1]; // TSTInfo
13760- } else { // TimeStampResp not containts 1 or 2 fields
13761- return $signature;
13762- }
13763-
13764- // Add timestamp in TCPDF Signature
13765- // Create timestamp pkcs#7 data
13766- $TimeStampToken = seq(
13767- "060B2A864886F70D010910020E". // OBJ_id_smime_aa_timeStampToken
13768- set(
13769- seq(
13770- $TSTInfo // TSTInfo
13771- )
13772- )
13773- );
13774-
13775- $time = seq(
13776- $pkcs7signerInfos[0][1].
13777- explicit(1,
13778- $TimeStampToken
13779- )
13780- );
13781-
13782- $pkcs7contentSignedData=seq(
13783- int(1). // version
13784- set($pkcs7SignedData[1][1]). // digestAlgorithms
13785- seq($pkcs7SignedData[2][1]). // contentInfo
13786- explicit(0,
13787- $pkcs7SignedData[3][1]
13788- ). // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates
13789- set(
13790- $time
13791- )
13792- );
13793- $pkcs7ContentInfo = seq(
13794- "06092A864886F70D010702". // ContentType OBJ_pkcs7_signed
13795- explicit(0,($pkcs7contentSignedData)) // content
13796- ).
13797- // "0000"; // sometime needed for backward compatibility
13798- "";
13799-
13800- $signature = $pkcs7ContentInfo;
13694+ $tsReqData = seq(int(1).seq(seq("06052B0E03021A"."0500").oct($hash)).int(hash('crc32', rand())).'0101ff');
13695+ $binarytsReqData = hex2bin($tsReqData);
13696+
13697+ //Send request to TSA Server
13698+ $ch = curl_init();
13699+ curl_setopt($ch, CURLOPT_URL, $this->tsa_data['tsa_host']);
13700+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
13701+ curl_setopt($ch, CURLOPT_POST, 1);
13702+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/timestamp-query','User-Agent: TCPDF'));
13703+ curl_setopt($ch, CURLOPT_POSTFIELDS, $binarytsReqData);
13704+ if(!$tsResponse = curl_exec($ch)) { return $signature; } // can't send tsRequest, Timestamp failed!
13705+ $hexTsaResponse = bin2hex($tsResponse); // parse timestamp response data
13706+ if(!$parseTimeStampResp = asn1parse($hexTsaResponse)) { return $signature; } // bad TSA Reponse
13707+ if(!$TimeStampResp = asn1parse($parseTimeStampResp[0][1])) { return $signature; } // verify tsa response PKIStatusInfo and TimeStampToken exists
13708+
13709+ // Select timeStampToken only. must ignore response status data (in first sequence if exist, select 2nd sequence)
13710+ if(count($TimeStampResp) > 1) {
13711+ $TSTInfo = $TimeStampResp[1][1]; // TSTInfo
13712+ } else if (count($TimeStampResp) == 1) {
13713+ $TSTInfo = $TimeStampResp[0][1]; // TSTInfo
13714+ } else { // TimeStampResp not containts 1 or 2 fields
13715+ return $signature;
1380113716 }
13717+
13718+ // Create timestamp pkcs#7 data
13719+ $TimeStampToken = seq("060B2A864886F70D010910020E".set(seq($TSTInfo)));
13720+ $time = seq($pkcs7signerInfos[0][1].explicit(1,$TimeStampToken));
13721+ $pkcs7contentSignedData=seq(int(1).set($pkcs7SignedData[1][1]).seq($pkcs7SignedData[2][1]).explicit(0,$pkcs7SignedData[3][1]).set($time));
13722+ $pkcs7ContentInfo = seq("06092A864886F70D010702".explicit(0,($pkcs7contentSignedData)));
13723+
13724+ $signature = $pkcs7ContentInfo;
1380213725 return $signature;
13803- // End timestamping
1380413726 }
1380513727
1380613728 /**
0 commit comments