Example #1
0
 public function signDocument(&$src_document)
 {
     global $mtlda, $audit;
     if (!is_a($src_document, 'Mtlda\\Models\\DocumentModel')) {
         static::raiseError(__METHOD__ . ' only supports DocumentModels!');
         return false;
     }
     $this->sendMessage('sign-reply', 'Retrieving document copy from archive.', '40%');
     if (!($fqpn = $src_document->getFilePath())) {
         static::raiseError(get_class($src_document) . '::getFilePath() returned false!');
         return false;
     }
     if (!file_exists($fqpn)) {
         static::raiseError("{$fqpn} does not exist!");
         return false;
     }
     if (!is_readable($fqpn)) {
         static::raiseError("{$fqpn} is not readable!");
         return false;
     }
     if (!$src_document->getSigningIconPosition()) {
         static::raiseError("document_signing_icon is not set!");
         return false;
     }
     try {
         $audit->log("signing request", "request", "signing", $src_document->getGuid());
     } catch (\Exception $e) {
         $signing_item->delete();
         static::raiseError("AuditController::log() raised an exception!");
         return false;
     }
     if (($public_key = file_get_contents($this->pdf_cfg['certificate'])) === false) {
         static::raiseError("reading {$this->pdf_cfg['certificate']} failed!");
         return false;
     }
     if (!($public_key = preg_replace('/(\\s*)-----(\\s*)(BEGIN|END) CERTIFICATE(\\s*)-----(\\s*)/', '', $public_key))) {
         static::raiseError("failed to strip RSA headers!");
         return false;
     }
     if (!($public_key = str_replace("\n", '', $public_key))) {
         static::raiseError("failed to strip whitespaces from public key!");
         return false;
     }
     $this->sendMessage('sign-reply', 'Sending SOAP request to signing server ' . $this->pdf_cfg['dss_url'] . '.', '50%');
     try {
         $dss = new \SoapClient($this->pdf_cfg['dss_url'] . '/wservice/signatureService?wsdl', array('soap_version' => SOAP_1_1, 'trace' => 1, 'exceptions' => true, 'cache_wsdl' => WSDL_CACHE_NONE));
     } catch (\DSSException $d) {
         static::raiseError($d);
         return false;
     } catch (\SOAPFault $f) {
         static::raiseError($f->faultcode . ' - ' . $f->faultstring);
         return false;
     } catch (\Exception $e) {
         static::raiseError("Failed to load SoapClient!");
         return false;
     }
     if (!is_callable(array($dss, "getDataToSign"))) {
         static::raiseError("Remote side does not provide getDataToSign() method!");
         return false;
     }
     if (!is_callable(array($dss, "signDocument"))) {
         static::raiseError("Remote side does not provide signDocument() method!");
         return false;
     }
     $parameters = new \stdClass();
     $document = new \stdClass();
     $parameters->asicZipComment = false;
     $parameters->chainCertificateList = array();
     $parameters->chainCertificateList[] = array('signedAttribute' => 'true', 'x509Certificate' => base64_decode($public_key));
     if (isset($this->tsp_cfg['tsp_ca_certificate']) && !empty($this->tsp_cfg['tsp_ca_certificate'])) {
         $parameters->chainCertificateList[] = array('signedAttribute' => 'true', 'x509Certificate' => base64_decode($this->tsp_cfg['tsp_ca_certificate']));
     }
     $parameters->deterministicId = $src_document->getGuid();
     $parameters->signatureLevel = 'PAdES_BASELINE_LTA';
     $parameters->signaturePackaging = 'ENVELOPED';
     $parameters->digestAlgorithm = $this->pdf_cfg['signature_algorithm'];
     $parameters->encryptionAlgorithm = 'RSA';
     $parameters->timestampDigestAlgorithm = $this->tsp_cfg['tsp_algorithm'];
     $parameters->signWithExpiredCertificate = false;
     $parameters->signingCertificateBytes = base64_decode($public_key);
     $parameters->signerLocation = array('city' => 'Obersdorf', 'country' => 'Austria', 'postalAddress' => 'Schloßpark 5/12/5', 'postalCode' => '2120', 'stateOrProvince' => 'Lower Austria');
     $parameters->signingDate = time();
     // set document information
     /*$pdf->SetCreator(PDF_CREATOR);
             $pdf->SetAuthor($this->pdf_cfg['author']);
             $pdf->SetTitle('Test Title');
             $pdf->SetSubject('Test Subject');
             $pdf->SetKeywords('Test, Keywords');
     
             // set additional information
             $info = array(
                 'Name' => $this->pdf_cfg['author'],
                 'Location' => $this->pdf_cfg['location'],
                 'Reason' => $this->pdf_cfg['reason'],
                 'ContactInfo' => $this->pdf_cfg['contact'],
             ); */
     if (!($document->bytes = file_get_contents($fqpn))) {
         static::raiseError("Failed to read {$fqpn}.");
         return false;
     }
     $document->name = basename($fqpn);
     $document->mimeType = new \stdClass();
     $document->mimeType->mimeTypeString = 'application/pdf';
     $document->absolutePath = $fqpn;
     $this->sendMessage('sign-reply', 'Submitting document to signing server ' . $this->pdf_cfg['dss_url'], '60%');
     try {
         $result = $dss->getDataToSign(array('document' => $document, 'wsParameters' => $parameters));
     } catch (\SoapFault $f) {
         static::raiseError($f->faultcode . ' - ' . $f->faultstring . '<br />' . htmlspecialchars($dss->__getLastRequest()));
         return false;
     } catch (\Exception $e) {
         static::raiseError("SOA getDataToSign() method returned unexpected!");
         return false;
     }
     if (!isset($result) || empty($result) || !isset($result->response) || empty($result->response)) {
         static::raiseError("Invalid response on SOAP request 'getDataToSign'!");
         return false;
     }
     if (!isset($this->pdf_cfg['password']) || empty($this->pdf_cfg['password'])) {
         $this->pdf_cfg['password'] = false;
     }
     if (!($key = openssl_pkey_get_private($this->pdf_cfg['private_key'], $this->pdf_cfg['password']))) {
         static::raiseError("Failed to read private key!");
         return false;
     }
     if (!openssl_sign($result->response, $signature, $key, $this->tsp_digest_algorithm)) {
         openssl_free_key($key);
         static::raiseError("openssl_sign() returned false!");
         return false;
     }
     unset($result);
     openssl_free_key($key);
     if (!isset($signature) || empty($signature)) {
         static::raiseError("openssl_sign() returned invalid signature!");
         return false;
     }
     $this->sendMessage('sign-reply', 'Now signing the signing servers response digest.', '70%');
     try {
         $result = $dss->signDocument(array('document' => $document, 'wsParameters' => $parameters, 'signatureValue' => $signature));
     } catch (\SoapFault $f) {
         static::raiseError($f->faultcode . ' - ' . $f->faultstring . '<br />' . htmlspecialchars($dss->__getLastRequest()));
         return false;
     } catch (\Exception $e) {
         static::raiseError("SOA signDocument() method returned unexpected!");
         return false;
     }
     if (!isset($result) || empty($result) || !isset($result->response) || empty($result->response)) {
         static::raiseError("Invalid response on SOAP request 'signDocument'!");
         return false;
     }
     if (!isset($result->response->bytes) || empty($result->response->bytes) || strlen($result->response->bytes) == 0) {
         static::raiseError("No document received up on SOAP request 'signDocument'!");
         return false;
     }
     $this->sendMessage('sign-reply', 'Transfering the signed document into archive.', '80%');
     if (file_put_contents($fqpn, $result->response->bytes) === false) {
         static::raiseError("Failed to write signed document into {$fqpn}!");
         return false;
     }
     unset($result);
     return true;
 }