Complex PHP example


Complex PHP example for creating and processing digitally signed claims


Use case participants

On this chapter is presented example solution for creating the claim, signing it digitally, receiving and verifying it. Example solution consists of three parts:

  • Claim creation and digial signing form on the Web server: implemented in PHP
  • Service for processing, verififying and encrypting claims on the Web server: implemented in PHP
  • Alternative command line utility for creating and digitally signing of claims: implemented in Java and .Net

Detailed description:

Let's presume there is an organisation to which claims can be presented. For that, the organisation has to set up a web server with a web form. Communication with the server is carried out over the HTTPS protocol and it requires the user to identify himself (See [1] in the list below). In the form, the name and personal identification number fields have been pre-filled with data taken from the certificate. After that, the user writes down his claim, which the web service will place into a DigiDoc container with the name and personal identification number, using DigiDocService[2.1]. As a last step, the user is asked to sign the container in the web browser[2.2].

The created container is forwarded to another service, which checks the signature [2.3] and issues an automatic response in a container that is signed with the organisation's digital stamp and encrypted with the public key from the user's certificate[3]. The user can save the presented claim and the received answer in his computer and then take a closer look at the answer with the DigiDoc client.

Parallel to the web form, there is also an application where the user has to identify himself[4]. Then the signed container is created in the client's computer[5, 6] and sent as a whole to the same service as the web form. In addition to the claim, the application also includes the information found in the personal data file of the ID card [7]. The server response is the same, but this time it is also decrypted[8] and the signature is verified within the application[8], not the DigiDoc client.

Therefore, the use case demonstrates

  1. personal identification on the Web,
  2. usage of DigiDocService
    1. for creating containers,
    2. signing and
    3. signature verification,
  3. encrypting a file with the sender's certificate,
  4. personal identification in an application,
  5. creating a container in an application,
  6. signing in an application,
  7. reading the personal data file of an ID card,
  8. decrypting a file and
  9. verifying a signature in an application.

Working principles of the example solution

Web-based component for entering the claim and digitally signing it with the ID-card

Web form sequence diagram

This is web-based component for filling out the claim form and for signing it with the help of ID-card.

  1. The web server carries out a personal identification in the course of the SSL/TLS handshake.
  2. The application uses DigiDocService for verifying client certificate validity. See certificate validity check in an SSL/TLS session to learn why it is done like that.
  3. The user is presented a web form that consists of four fields. Three of them (name, surname and personal identification number) are pre-filled with the data obtained at personal identification.
  4. When the form is presented, contents of the fields and the user's signing certificate with its serial number is sent to the server (although the serial number could be read from the certificate, it is better to leave this work to the client's side).
  5. A text file is created from the data inserted into the form and it is saved in a temporary folder.
  6. A new session is started with DigiDocService and a container created, where the freshly created file's hash is put (StartSession). Although it is possible to send the source files to the service, it is more sensible from the point of view of privacy and data volume to send hashes.
  7. Preparations are made to sign the container: The user's certificate is sent to DigiDocService together with the metainformation, i.e. role and location (PrepareSignature). In sample code, constants are used for metainformation, as asking them from the user is trivial and does not require a special example. The service returns a container hash that the client has to sign.
  8. The next page is displayed to the user, with the signing certificate's serial number and the hash to be signed.
  9. The user clicks the button "Sign", upon which the process is handed over to the JavaScript library that obtains the signature to the hash from the user.
  10. The signature is sent back to the web form with the next query, and the web form finalises the signing process (FinalizeSignature), downloads the signed container (GetSignedDoc) and closes the session (CloseSession).
  11. In the downloaded container, the hashes are replaced with the actual files that were saved on the disk beforehand, and forwarded to the claims handling service.
  12. The downloaded container and the response from the organisation are saved on the disk, from where the user can in turn download them using his browser.

Web-based component for entering the claim and digitally signing it with the help of Mobile-ID

Mobile ID's web form sequence diagram. The parts in the blue boxes are repeated until a query result is obtained. The communication between the mobile operator and the user is missing from the scheme, because it is not important from the point of view of development.

A version of the web form that uses mobile ID. In general, it is an application quite like the web form (see also installing requirements there), with two important differences.

First, the client's certificate is not requested in the course of the SSL/TLS handshake -- the certificate is on mobile ID SIM and the user's web browser has no access to it. Instead, we use the DigiDocService method MobileAuthenticate for forwarding an authentication query. As method parameters, we give the user's phone number and language preference. After that, we invoke the method GetMobileAuthenticateStatus every five seconds until it returns authentication results. The method also returns the user's certificate, the validity of which has already been verified.

Second, the document is not signed with a web browser plugin but with mobile ID. Consequently, we do not invoke the methods PrepareSignature and FinalizeSignature, but MobileSign and GetStatusInfo: the first sends a signing query and the second we check every five seconds until we have a result. The rest of the steps needed for hashing documents, creating containers and determining metainformation are the same as with the web form.

The interval of five seconds that has been chosen for both status checks is good for testing, when the test numbers answer quickly. In a product environment, users take much longer to answer mobile ID queries, so that the interval can also be increased (especially the waiting time before the first query is made).

Note: The response obtained from the claims handling service is encrypted and the only receiver is the mobile ID's personal identification certificate - but as mobile ID does not support encryption, this response cannot be read. However, the contents of the response are not important at all -- the fact that the response was returned shows that the statement was correct and its sending successful.

Java and .Net based Claims application

Claims application sequence diagram

This is a command line application that generates a claim on the basis of information gathered from the user and the personal identity document, puts it in a container, signs and sends it to the claims handling service. In response, a new container is delivered. The application decrypts it, verifies the signature and displays the contents of the container to the user.

The application is originally written in Java, where the JDigiDoc library is used, and then ported to .NET, where a COM library is used. Some subparts of the application (signing, personal identification, signature verification and data decryption) have also been rewritten in C++, but as its usage is quite similar to Java, there was no need to re-port the whole application.

  1. The application performs personal identification as described in personal identification and executed in the standalone personal identification application.
    • The .NET application verifies certificate validity using only CRL; for OCSP support, third party libraries must be used (e.g. Bouncy Castle).
  2. The user is asked for input for the claim - it is a simple, one-line text input. As libraries are only able to use files that have been saved on the disk, the input information is saved into a temporary file.
  3. The personal data read from the card is temporarily saved on the disk (libraries don't support reading the personal data file, which is why it has to be done manually, on the basis of the EstEID card user manual (in Estonian) -- read more about whether and how to read the personal data file from Using the personal data file.
  4. The data is contained in a DDOC container and signed -- in the course of the latter, the validity of the certificate for signing is also used.
  5. It is checked whether the container verifies and it is written on the disk.
  6. The container is sent to the claims handling service and an encrypted container is received in response.
    • As the COM library does not support decrypting, in the case of a .NET application, the server is requested an unencrypted response. Therefore, the next step is also missed.
  7. The transport key in the container is decrypted with the secret key of the user's personal identification certificate and it is used for decrypting the signed response from the service.
  8. The signed response is saved on the disk and then its signature is verified.
  9. The contents of the response from the service are displayed to the user.

NB! The Java application requires Java version 1.7 or later.

By default, personal identification in the claims application works only with cards employing 2048-bit keys. In order to use older cards, the relevant hash algorithm must be changed in the source code (see The fault in pre-2011 cards).

Claims handling service

Claims handling service sequence diagram

The claims handling service is written in PHP and uses DigiDocService for verifying the signature on the claim. For signing and encrypting the response, a SWIG wrapper around the libdigidoc library is used.

  1. A POST query is presented to the service with two mandatory fields: claim and cert.
    • cert must contain the personal identification certificate of the receiver of the response in a base64 coded DER form (this is not PEM, because the lines BEGIN and END are absent),
    • claim must contain the signed claim. The file's MIME type has to be either application/x-ddoc or application/vnd.bdoc-*.
  2. The service checks if the upload was successful and if the signature on the claim is valid. For validity check, the claim is sent to DigiDocService, using the query StartSession, where the flag bHoldSession has been put to negative so that the connection would be closed immediately. As a response, DigiDocService sends the signature's status.
    • Again, not the whole claim is sent to DigiDocService but data files with their hashes.
  3. The contained data files are read from within the claim and written on the disk.
  4. If the signature is valid, a response is generated. Its contents are not important to us, so it is a constant string.
  5. The libdigidoc library is reset and a signing container created (in the SWIG wrapper, the corresponding methods are initialize and new_signature_container).
  6. The generated response is added to the container (add_data_file) and signed (sign_container). The PIN used for signing can be either an argument of the signing function or a value of the key AUTOSIGN_PIN in the configuration file of the libdigidoc library (in this case when the function is invoked, the value of the parameter pin will remain NULL).
  7. The signed response is written on the disk and released from memory (methods save_signed_document and free_signature_container. NB! Here it would be reasonable to retain the container in the memory, as it will be read from the disk again right away -- but this cannot be done at the moment, as the library function createSignedDocInMemory produces a faulty XML, so we have to use the version that writes on the disk).
  8. The service creates a new encryption container (new_encryption_container) and encrypts the freshly generated response (encrypt_ddoc).
  9. The used transport key is encrypted with the public key of the certificate on the field cert and is added to the container (add_recipient).
  10. The encrypted container is saved on the disk (method save_encrypted_container. NB! Again, it would be better not to write the container on the disk, but the conversion of the container into XML in the memory is hidden from us in the library, and the only way to generate XML is to write the file). The memory taken for the container is freed (free_encryption_container) and the response is sent to the sender of the initial query.

While installing the service, it must be made sure that it has writing rights in its own folder and the conf.php file must be tweaked, where at least the DD_RESPONSE_SERVER address must be changed (this is used by the web form and its value should be set to the address of the claims handling service).

Attention: Keep in mind that the class necessary for the communication with the DigiDoc service is generated by PHP only once, and then saved to disk. If, following that, the developer alters either the rest of the source code or conf.php, or installs the PHP cURL module, then the wsdl.class.php must be deleted so that it could be generated as new.

Installing the sample solution


Dependencies of web-based components

Sample code has been created on the platform Ubuntu 12.04 Long-Term Support a.k.a Precise Pangolin (64-bit), using the default package versions:

  • apache2 2.2.22-1ubuntu1.4
  • php5 5.3.10-1ubuntu3
  • php5-dev 5.3.10-1ubuntu3
  • php5-curl 5.3.10-1ubuntu3
  • swig 2.0.4+really2.0.4-4ubuntu2

By default this platform contains out-of-the-box old DigiDoc libraries. In order to use new libraries the following script should be downloaded and executed from command line:

Dependencies of Java command line utility

In order to be able compile of Java command line utility following packages should be installed into the computer:

  • openjdk-7-jdk
  • ant 1.8.2-4build1

There is also required to install the following external packages:

Deployment scripts and configuration of Java command line application are designed for installing the application into the same computer, where is claims service installed. If this is not the case then there is probably required to do suitable changes in deployment scripts and configuration files. Also on such case there is required to install DigiDoc libraries.

Configuring the Apache web server

General information

The web server should be Apache httpd (naturally other web servers may be used, but these will not be discussed here). It is necessary to have PHP support installed and the server configured to use HTTPS. All of this is done as normal and there is no eID specifics.

For logging in with an ID-card, the server has to be additionally configured to request the user for his certificate on the relevant webpage. Guidelines for it can be found on the corresponding page. In the present use case, an ID-card is only used on the web form so that the guide should be consulted for this application only. If all applications run on the same web server, requesting the certificate should be configured for the web form only; the certificate should definitely not be requested by the claims handling service; otherwise, other applications cannot present claims to it.

Servers configured according to these guidelines verify the validity of users' certificates against revocation lists (CRL, Certificate Revocation List) only -- adding OCSP (Online Certificate Status Protocol) requests would be a good idea. But as mentioned at certificate validity check, it is not easily done in a web server.

As noted above, the client's certificate is only used in the SSL/TLS session at the web form, where DigiDocService support already exists. Therefore, validity confirmation can also be asked through this service. In the mobile-ID web form, DigiDocService performs a validity check for us, so there is no need to do it separately.

In the following there are step by step described how the Apache web server should be configured.

Installing of the certificates

Creating the server certificate

For demonstrating purposes there is sufficient to use self-signed certificates. For real server there should real SSL server certificate obtained. Self-signed certificate can be generated with the help of the following commands:

su -
cd /etc/ssl/private
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out ../certs/server.crt 

Loading the SK certificates

There is needed to download and install suitable SK (AS Sertifitseerimiskeskus) CA certificates:

cd /etc/ssl/certs
cat JUUR-SK.PEM.cer EECCRCA.pem.cer ESTEID-SK\ 2007.PEM.cer ESTEID-SK\ 2011.pem.cer > id.crt

Loading the certificate revocation lists

Certificate revocation list (CRL) contains information about all revoked certificates. CRLs can be downloaded from, but for Apache server they should be converted to PEM format:

mkdir /etc/ssl/crl
cd /etc/ssl/crl
openssl crl -in esteid2007.crl -out esteid2007.crl -inform DER 
openssl crl -in crl.crl -out crl.crl -inform DER 
openssl crl -in eeccrca.crl -out eeccrca.crl -inform DER 
openssl crl -in esteid2011.crl -out esteid2011.crl -inform DER 

Creating the certificate revocation list collection

Apache server is seraching the CRLs from the specified dierctory based by very specific hashed file name. Therefore there is needed to create suitable symbolic links with the help of the following commands:

ln -s crl.crl `openssl crl -hash -noout -in crl.crl`.r0 
ln -s esteid2007.crl `openssl crl -hash -noout -in esteid2007.crl`.r0 
ln -s eeccrca.crl `openssl crl -hash -noout -in eeccrca.crl`.r0 
ln -s esteid2011.crl `openssl crl -hash -noout -in esteid2011.crl`.r0

Enabling mod_ssl in Apache configuration

By default the mod_ssl module is switched off. Use the following commands for switching this on:

cp /etc/apache2/sites-available/default-ssl /etc/apache2/sites-enabled/
cd /etc/apache2/mods-enabled
ln -s ../available/ssl.conf
ln -s ../available/ssl.load

Modifying the Apache configuration files

For enabling the use of correct certificates modify the Apache configuration file /etc/apache2/sites-enabled/default-ssl as follows (insert or modify corresponding parameters):

SSLCertificateFile    /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
SSLCACertificateFile  /etc/ssl/certs/id.crt
SSLCARevocationPath /etc/ssl/crl/

Enabling ID-card authentication support in Apache configuration

For activating the ID-card authentication for some particular location (on current case - for directory "webform"), insert the following lines into configuration file /etc/apache2/sites-enabled/default-ssl:

<Location /eid/avaldused/webform>
SSLVerifyClient require 
SSLVerifyDepth  2 
SSLOptions +StdEnvVars +ExportCertData

Applying Apache configuration changes

For activating the configuration changes there is needed to to restart for Apache service:

/etc/init.d/apache2 restart


For signing and signature verification in PHP, DigiDocService can be used. To enable communication with the service over HTTPS, the cURL extension has to be added to PHP.

The interface of DigiDocService is defined in WSDL, upon which the PHP class for using the service is generated. Although PHP 5 comes with built-in SOAP client and the possibility to generate a class upon WSDL[1], sample code uses the included SOAP module from PEAR, with which the code will also work with older versions. The code should work with PHP 4.3.4 at least, but working on older versions is not excluded either. If the web application uses PHP 5, it is advisable to use built-in tools for new developments.

For reading XML files and DigiDoc containers, a shortened and slightly modified version of sample code is used, which is available at If the shortened version lacks the desired functionality, it may be present in the full version.

Using the test version of DigiDocService

In order to use the test version of DigiDocService, you should first enable this for your ID-card. Service will be enabled for your ID-card if you upload your ID-card certificate into DigiDoc Portal The same logic applies alto for Mobile-ID / you should upload your Mobile-ID certificate using the URL

For more concrete instructions please see

Installing the sample software

All source code for software samples can be accessed through the GitHub environment:

For installing the sample solution, download it, execute build script and install script:

cd /var/www
git clone
cd eid/avaldused
sh ./
su -c ./

NB! Install script changes the global configuration file /etc/digidoc.conf in order to enable usage of test-DigiDocService. After the change the configuration file is no more suitable for production environment. The old configuration file will be backed up to file /etc/digidoc.conf.orig.

By default the signing of the response is turned off on the sample claims processing service. If you like to test this functionality too, then you should connect the ID-card reader to the server, configure it and insert eID card into this reader. For activating the digital signing of responses modify the file eid/avaldused/conf.php and change the definition of the constant DD_SIGN_RESPONSE to 1:

define('DD_SIGN_RESPONSE', 1);

Setting up the web forms

There is no specific actions needed in order to set up the web forms for sample solution. You can just open the right URL https://localhost/eid/avaldused/ in your web browser (replace "localhost" with the computer name where you installed the sample solution) and choose the suitable web form. In case you select the web form with digital signing by the help of ID-card, then immediately ID-card authentication will be required.

Installing Java command line utility

If you like to use Java command line utility then this should be separately compiled. Go to the directory eid/avaldused/client-java and execute the command:

sh ./

Java command line utility can be executed with command:

sh ./

Klient on häälestatud töötama avaldusi töötleva veebiteenusega üle HTTP protokolli. Kui on soov testida üle HTTPS protokolli toimimist (vajalik tingimata pärisrealisatsioonides), tuleb vastavalt modifitseerida skriptis leiduvat URLi. Lisaks tuleb hoolitseda, et serveri sertifikaadi väljaandja oleks süsteemile tuttav. Selleks peab vastav sertifikaat olema keystore'is olemas. Kui teenus kasutab enda allkirjastatud (self-signed) sertifikaate (näiteks testimisel), siis on vaja need enne Java keystore'i lisada:

By default the utility is configured to use web service over HTTP protocol. If an HTTPS connection is created with the service (very advisable), then it is needed to change the URL in file and also checked that the issuer of the server certificate is known to the system. This means that the key should be present in keystore.

If the service uses self-signed certificates (e.g. at testing), these need to be added to the Java keystore beforehand:

keytool -import -alias <certificate alias> -file <certificate location> -keystore <keystore location>

E.g. under Ubuntu:

# keytool -import -alias snakeoil -file /etc/ssl/certs/ssl-cert-snakeoil.pem -keystore /usr/lib/jvm/default-java/jre/lib/security/cacerts

Installing .Net application

The .NET application comes with Visual Studio 2010 project files that can be used for compiling the application. If there is none, a reference to the COM library has to be added to the project. After the reference has been added, under References, the Properties of DIGIDOCLIBCOMLib have to be opened and Embed Interop Types value set to False.

If an HTTPS connection is created with the service (very advisable), then it is checked that the issuer of the server certificate is known to the system. This means that he key should be installed in the Windows certificate repository. For installing a self-signed certificate in the Windows certificate repository, it is enough to double-click it and choose "Install certificate".

The application can be executed with the command:

EidClient.exe [url]

Märkused näiterakenduse kohta

Sample application JavaScript components

Several signing plugins have been made for different operation systems and browsers, but their API-s are somewhat different. To simplify adding signing support to web applications, a JavaScript library was created that offers a unified interface for communicating with all plugins.[2][3]

The library's interface facilitates:

  • loading the best installed plugin for the operating system and the browser
  • reading the user's signing certificate from the ID card and
  • signing the given hash with the user's ID card.

Error messages of the library are in Estonian, English, Lithuanian and Russian. For choosing the desired language, the value of the method loadSigningPlugin() should be set respectively to "est", "eng", "lit" or "rus".

All three are used in the claims presentation web form and the sample code is available there.

The library with documentation is available at:

In addition to the library, a new universal plugin was also created that is distributed as part of the ID card base software and is recommended for use in the future, as the older Java applet is no longer updated.[3]

Sample application in the .NET framework

Although .NET allows several operations to be performed with the smart card with the tools already included in the framework, it lacks support for the DDOC format. Therefore, for signing or verifying a container in a .NET application, a COM-library must be used or the appropriate functionality implemented.

.NET sample code can be seen in the claim application.

There is a plan to create a separate .NET library by 2013 that will replace the COM library.[4]

Using DigiDoc Library in PHP

If there is no wish or possibility to use DigiDocService, DigiDoc libraries can be used as an alternative. None has been written for PHP; therefore, a wrapper around an existing one has to be used.

To simplify interfacing with a library and minimise wrapped surface, a simple middle layer was created in the sample code that hides the usage of libdigidoc library behind a function. The middle layer is transmission-specific, which is why it is not suitable for general use, but it will give an idea of what it could be like. After that, a SWIG wrapper was created around the middle layer, not the library. The result was a PHP extension with the help of which it is possible to use all the methods of the middle layer.

The extension is used for signing and encrypting the server-side response. The latter of these cannot be done with DigiDocService, which is more proof of the necessity of using libraries.

Compiling the SWIG extension

SWIG component resides in directory eid/avaldused/swig. Install script of sample application executes all required actions in order to install this component. Here is given some advices in case there is interest to manually install this comonent.

Because of the created middle layer, the digidoc interface in source code is very simple -- it only contains the directive for the inclusion of digidoc.h headers. From the interface, the wrapper's code can be generated by giving the command:

swig -php digidoc.i

As a result of this, three new files are created: digidoc_wrap.c, digidoc.php and php_digidoc.h.

  • The first, digidoc_wrap.c, contains the code in C needed for compiling the PHP extension.
  • The second, digidoc.php, can be included in PHP scripts. It attempts to load the extension dynamically and places the wrapped functions into the abstract class digidoc.
  • The last, php_digidoc.h, contains necessary header information for when you wish to link the extension statically into a PHP interpreter. If you do not want to do that, this file is not needed.[5]

After that, the middle layer code together with the generated C code of the wrapper should be compiled into one shared object. For compiling, the header locations of PHP interpreter headers must also be given, which can be done with the php-config tool, and then the libdigidoc library should be linked. E.g. using GCC, the compiling would look like this:

$ gcc `php-config --includes` -fPIC -c digidoc.c digidoc_wrap.c
$ gcc -shared digidoc.o digidoc_wrap.o -ldigidoc -o

Loading the extension

When including digidoc.php, it is attempted to dynamically load the created extension with the command dl (if it hasn't been loaded already). As there have been problems with the dl command[6], it is first better to load the module manually. For that, a line has to be added to the php.ini configuration file (or the existing one changed):  # Linux
extension=digidoc.dll # Windows

libdigidoc configuration

As the SWIG wrapper uses the libdigidoc library, the file digidoc.conf must be changed for configuring it. Default values are mostly suitable, but there is one important line: DIGIDOC_OCSP_URL, which determines where the OCSP query will be sent. For testing purposes, the value should be

Attention: Do not forget to change it back when you want to send queries in a product environment using the libdigidoc library.

Configuring the digital stamp

If the service uses a digital stamp instead of an ID card for signing, libdigidoc version 3.7 or newer is needed and the digital stamp drivers must be installed. Also, some changes have to be made in the settings file of libdigidoc library.

For installing drivers, see the chapter Using the crypto-stick.

The default location of the settings file of libdigidoc library is %PROGRAMFILES%\Estonian ID card\digidoc.ini (Windows) or /etc/digidoc.conf (Linux).

The following lines should be present in the settings file (module location may differ):

DIGIDOC_DRIVER_1_DESC=OpenSC projects PKCS#11 driver

Here, it is necessary to use the freshly installed SafeNet eToken module instead of the OpenSC one. For this, just replace the existing module or add a new one. The last version would look like this (again, the actual module locations may differ):

DIGIDOC_DRIVER_1_DESC=OpenSC projects PKCS#11 driver
DIGIDOC_DRIVER_2_DESC=SafeNet eToken PKCS#11 driver
In addition, the number of the slot used for digital signing must be changed:


  2. JavaScript client library (idCard.js) for simplifying signing in web applications.
  3. 3,0 3,1 Signing on web applications with the ID-card and digi-ID.