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 SetaPDF_Signer_Signature_Module_ModuleInterface
interface.
Additional interfaces are available which allow modifications of the signature dictionary or the document instance: SetaPDF_Signer_Signature_DictionaryInterface
and SetaPDF_Signer_Signature_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 class MySignatureModule implements \SetaPDF_Signer_Signature_Module_ModuleInterface, \SetaPDF_Signer_Signature_DictionaryInterface, \SetaPDF_Signer_Signature_DocumentInterface { /** * Create a signature for the file in the given $tmpPath. * * @param \SetaPDF_Core_Reader_FilePath $tmpPath * @return string */ public function createSignature(\SetaPDF_Core_Reader_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 \SetaPDF_Core_Type_Dictionary $dictionary */ public function updateSignatureDictionary(\SetaPDF_Core_Type_Dictionary $dictionary) { // update the signature dictionary if needed // if the webservice returns a PAdES conforming signature update following values: //$dictionary['SubFilter'] = new \SetaPDF_Core_Type_Name('ETSI.CAdES.detached', true); //$dictionary['Filter'] = new \SetaPDF_Core_Type_Name('Adobe.PPKLite', true); } /** * Method to allow updates onto the document instance. * * @param SetaPDF_Core_Document $document */ public function updateDocument(\SetaPDF_Core_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 SetaPDF_Signer_Signature_Module_Cms
and SetaPDF_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 class MySignatureModule implements \SetaPDF_Signer_Signature_Module_ModuleInterface, \SetaPDF_Signer_Signature_DictionaryInterface, \SetaPDF_Signer_Signature_DocumentInterface { use \SetaPDF_Signer_Signature_Module_PadesProxyTrait; /** * Create a signature for the file in the given $tmpPath. * * @param SetaPDF_Core_Reader_FilePath $tmpPath * @return string */ public function createSignature(\SetaPDF_Core_Reader_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 SetaPDF_Signer_Signature_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 class MySignatureModule implements \SetaPDF_Signer_Signature_Module_ModuleInterface, \SetaPDF_Signer_Signature_DictionaryInterface, \SetaPDF_Signer_Signature_DocumentInterface { use \SetaPDF_Signer_Signature_Module_PadesProxyTrait { \SetaPDF_Signer_Signature_Module_PadesProxyTrait::updateSignatureDictionary as updateSignatureDictionaryWithPadesInformation; } public function updateSignatureDictionary(\SetaPDF_Core_Type_Dictionary $dictionary) { $this->updateSignatureDictionaryWithPadesInformation($dictionary); $dictionary['Prop_Build'] = new \SetaPDF_Core_Type_Dictionary([ 'App' => new \SetaPDF_Core_Type_Dictionary([ 'REx' => new \SetaPDF_Core_Type_String('1.2.3'), 'Name' => new \SetaPDF_Core_Type_Name('My awesome signature service') ]) ]); } }