Index
- Getting Started
- The Main Class
- Signature Fields
- Signature Appearance Modules
- Signature Modules
- Timestamp Modules
- Asynchronous Signature Workflow
- Sign Several Times
- Signing PDF Forms
- Long-Term Validation (LTV)
- Trust Settings
- Migrating
- LTV (pre-release)
- API Reference
Individual Module
Table of Contents
Introduction
Sometimes it is needed to delegate the signature process to e.g. an external webservice. This is possible by implementing your own signature module.
You can extend an existing module or implement your own module class by implementing the \setasign\SetaPDF2\Signer\Signature\Module\ModuleInterface
interface.
Additional interfaces are available which allow modifications of the signature dictionary or the document instance: \setasign\SetaPDF2\Signer\Signature\Module\DictionaryInterface
and \setasign\SetaPDF2\Signer\Signature\Module\DocumentInterface
.
Examples
External Serivce that Creates CMS/PKCS#7 Structures
Following example delegates the complete creation of the CMS/PKCS#7 structure to an external service:
<?php use setasign\SetaPDF2\Core\Document; use setasign\SetaPDF2\Core\Reader\FilePath; use setasign\SetaPDF2\Core\Type\PdfDictionary; use setasign\SetaPDF2\Core\Type\PdfName; use setasign\SetaPDF2\Signer\Signature\Module\DictionaryInterface; use setasign\SetaPDF2\Signer\Signature\Module\DocumentInterface; use setasign\SetaPDF2\Signer\Signature\Module\ModuleInterface; class MySignatureModule implements ModuleInterface, DictionaryInterface, DocumentInterface { /** * Create a signature for the file in the given $tmpPath. * * @param FilePath $tmpPath * @return string */ public function createSignature(FilePath $tmpPath) { // get hash $hashAlgorithm = 'sha256'; $hashValue = hash_file($hashAlgorithm, $tmpPath); // e.g. call an external webservice to create the signature $signature = callWebserviceToCreateSignature($hashValue, $hashAlgorithm); // return the signature value return $signature; } /** * Method to update the signature dictionary. * * @param PdfDictionary $dictionary */ public function updateSignatureDictionary(PdfDictionary $dictionary) { // update the signature dictionary if needed // if the webservice returns a PAdES conforming signature update following values: //$dictionary['SubFilter'] = new PdfName('ETSI.CAdES.detached', true); //$dictionary['Filter'] = new PdfName('Adobe.PPKLite', true); } /** * Method to allow updates onto the document instance. * * @param Document $document */ public function updateDocument(Document $document) { // make changes or check to the document instance // if the webservice returns a PAdES conforming signature update following values: //$extensions = $document->getCatalog()->getExtensions(); //$extensions->setExtension('ESIC', '1.7', 2); } }
Exernal Service that Returns a PKCS#1 Signature Value
If a service returns only a signature value (e.g. PKCS#1) it's needed to create the final CMS structure and embed the signature value into it. This is supported by the \setasign\SetaPDF2\Signer\Signature\Module\Cms
and \setasign\SetaPDF2\Signer\Signature\Module\Pades
modules which both come with a
method.setSignatureValue()
As the PAdES module is the most common used module we prepared a trait which proxies most methods of it. By using this, a simple module that embeds a returned signature value into the CMS structure could look like this:
<?php use setasign\SetaPDF2\Core\Reader\FilePath; use setasign\SetaPDF2\Signer\Signature\Module\DictionaryInterface; use setasign\SetaPDF2\Signer\Signature\Module\DocumentInterface; use setasign\SetaPDF2\Signer\Signature\Module\ModuleInterface; use setasign\SetaPDF2\Signer\Signature\Module\PadesProxyTrait; class MySignatureModule implements ModuleInterface, DictionaryInterface, DocumentInterface { use PadesProxyTrait; /** * Create a signature for the file in the given $tmpPath. * * @param FilePath $tmpPath * @return string */ public function createSignature(FilePath $tmpPath) { $hashAlgorithm = 'sha256'; // let's fixiate this for this example $padesModule = $this->_getPadesModule(); $padesModule->setDigest($hashAlgorithm); $hashValue = hash($hashAlgorithm, $padesModule->getDataToSign($tmpPath), true); // e.g. call an external webservice to create the signature value $signatureValue = callWebserviceToCreateSignature($hashValue, $hashAlgorithm); // pass the signature value to the CMS structure $padesModule->setSignatureValue($signatureValue); return $padesModule->getCms(); } }
Build Properties Dictionary
If you want embed information about the software or module that was involved in the signing process, you can save these information in the Build Properties Dictionary, which you can create at runtime by implementing the \setasign\SetaPDF2\Signer\Signature\Module\DictionaryInterface
. For details about the content of this Build Properties Dictionary please see here.
To display the application name and version in e.g. Adobe Acrobat such as this:
You can implement this in your own module like this:
<?php use setasign\SetaPDF2\Core\Reader\FilePath; use setasign\SetaPDF2\Core\Type\PdfDictionary; use setasign\SetaPDF2\Core\Type\PdfName; use setasign\SetaPDF2\Core\Type\PdfString; use setasign\SetaPDF2\Signer\Signature\Module\DictionaryInterface; use setasign\SetaPDF2\Signer\Signature\Module\DocumentInterface; use setasign\SetaPDF2\Signer\Signature\Module\ModuleInterface; use setasign\SetaPDF2\Signer\Signature\Module\PadesProxyTrait; class MySignatureModule implements ModuleInterface, DictionaryInterface, DocumentInterface { use PadesProxyTrait { PadesProxyTrait::updateSignatureDictionary as updateSignatureDictionaryWithPadesInformation; } public function updateSignatureDictionary(PdfDictionary $dictionary) { $this->updateSignatureDictionaryWithPadesInformation($dictionary); $dictionary['Prop_Build'] = new PdfDictionary([ 'App' => new PdfDictionary([ 'REx' => new PdfString('1.2.3'), 'Name' => new PdfName('My awesome signature service') ]) ]); } public function createSignature(FilePath $tmpPath) { // ... } }