|
libdigidocpp 4.6.0
|
Libdigidocpp is a C++ library for creating applications that create and verify digital signatures. Digitally signed files are created as Associated Signature Containers (ASiC), using the .asice file extension and XML Advanced Electronic Signatures (XAdES) standardized by the European Telecommunications Standards Institute (ETSI).
Additionally, the libdigidocpp library can create, save, read, validate, and extend digitally timestamped containers (using the .asics file extension) with a single data file and RFC 3161 time-stamp tokens. ASiC containers with CAdES signatures, PDF, and DDOC files can be validated with the SiVa service.
Development of the library can be monitored in GitHub environment: https://github.com/open-eid/libdigidocpp.
Changes by version are listed on the separate Release Notes page. Supported container formats are described on the separate Supported container formats page. Configuration is described on the separate Configuration guide page. Implementation notes are described on the separate Implementation notes page.
Libdigidocpp library forms a part of the wider DigiDoc system framework which offers a full-scale architecture for digital signature and documents, consisting of software libraries (C++ and Java), SiVa service and end-user applications such as DigiDoc4 according to the following figure:
It is easy to integrate DigiDoc components into existing applications in order to allow for creation, handling, forwarding and verification of digital signatures. All applications share common digitally signed file formats.
Libdigidocpp is a library of C++ classes offering the functionality of handling digitally signed files in supported DigiDoc formats. The following functions are implemented:
The following table gives overview of functional features that are supported with Libdigidocpp.
| Feature | Supported values |
|---|---|
| DigiDoc document format |
|
| Signature profile | Signature profiles are based on the profiles defined by XAdES (XAdES).
|
| Trust anchors | Information of trusted CA certificates (trust anchors) is used to validate the trustworthiness of certificates used in the signature. The signer certificate's CA, OCSP responder certificate and time-stamping service's certificate (in case of TS signature profile) must be trusted. Trusted certificates' information is obtained from TSL list (Trust Service status list), the trusted certificates' list is retrieved from a signed TSL list that provides information about the status and the status history of the trust services (including certification, OCSP confirmation and time-stamping services). The European Commission's TSL list is used, more information of which can be found from https://ec.europa.eu/information_society/policy/esignature/trusted-list/. For the TSL specification document, see also Trusted Lists. For more information about the TSL implementation and configuration possibilities in Libdigidocpp library, see TSL list usage in Libdigidocpp and Trust anchor/TSL settings. |
| Signature creation module |
|
| Cryptographic token type |
|
| Public-key algorithm |
|
The figure below describes the architecture of software and hardware components that are used when creating signatures with Libdigidocpp library.
| Component | Description |
|---|---|
| PKCS#11 | Widely adopted platform-independent API to cryptographic tokens (HSMs, smart cards and USB tokens), a standard management module of the cryptographic token and its certificates |
| CryptoAPI | Microsoft Cryptography API. Programming API for implementing cryptographic functions in Windows environment. |
| PC/SC | Standard communication interface between the computer and the smart card, a cross-platform API for accessing smart card readers |
| IFDHandler | Interface Device Handler for CCID readers |
| CCID | USB driver for Chip/Smart Card Interface Devices |
| Reader | Device used for communication with a smart card |
Note that Libdigidocpp uses internal memory buffers in case of all the operations, so that intermediary data is not written to temporary files on the disk. Also, the data files to be added to a DigiDoc container can be read from a data stream and later extracted from the container to a stream so that the data can be kept in memory.
All std::string values passed to or returned from the API are UTF-8 encoded. This applies to file paths, media types, and all other string parameters and return values throughout the library.
Libdigidocpp's initialization method conducts the following operations:
If you would like to use non-default configuration settings then call out the configuration file's initialization before initializing the library, for example:
The digidoc::XmlConf class must be used in order to access all the configuration methods that are available.
Create a new container object and specify the DigiDoc document's type, for example:
Container class is used to incorporate the data of a DigiDoc document.
Create an ASiC-S container by using an .asics or .scs output file name. An ASiC-S TimeStampToken container supports exactly one data file and one initial RFC 3161 time-stamp token.
ASiC-S TimeStampToken creation uses the one-step digidoc::Container::sign method. External two-step signing with digidoc::Container::prepareSignature is not supported for this format. Additional archive-manifest time-stamp layers can be added with the workflow described in Extending container validity.
Data files can be added to a DigiDoc container in two alternative ways:
Parameter mediaType in the methods above stands for a MIME type of the data file, for example "text/plain" or "application/msword". Value "application/octet-stream" is used by default. Calling out any of the methods listed above shall create a new DataFile object and add it to the DigiDoc container's data file collection. Note that in order to add a data file to a container, the container has to be unsigned and there shouldn't be an existing data file with the same name in the container. If a container is signed then it is possible to add data files to it only after the signatures are removed.
The stream overload's fileName is the name stored inside the container. It must be a single non-empty path component: ".", "..", forward slashes, and backslashes are rejected. The file-system overload accepts a source path and stores only its base name. When an existing ASiC-E container is opened, safe relative subdirectories separated by forward slashes are accepted, but absolute paths, backslashes, trailing slashes, and empty, ".", or ".." path segments are rejected. ASiC-S data files must be at the container root.
It is possible to add a signature to a container only if it contains at least one data file, multiple signatures can be added to a single container. The signer's certificate and PIN code to access the private signature key are required during signing.
Signing can be done by using PKCS#11 module for accessing the signature token. PKCS#11 module is the default module for singing with smart card (e.g. Estonian ID card or any other smart card provided that you have the external native language PKCS#11 driver for it). See also PKCS#11 settings.
If you would like to add PIN insertion dialog window for the signer to enter the PIN code then you can write a new class which extends the PKCS11Signer class, overwrite the std::string pin(const X509Cert &cert) method and write your own PIN dialog implementation code there.
The supported signature profiles are (see also Supported functional properties, under "Signature profiles"):
If the signature profile value is not specified then then a "time-stamp" profile is used by default.
Set the profile value as follows:
Signature production place and signer role are optional signed meta-data about the signature. If left unspecified then the respective elements in the signatures*.xml file are created with no contents.
By default, the hash that is being signed is calculated with SHA-256 algorithm. You can also use a different digest algorithm for calculating the hash that is signed (this does not affect calculating other hash values). For that, use the digidoc::Signer::setMethod(const std::string &method) method.
The signing method also adds validation data from external services (OCSP and time-stamping servers). Note that the OCSP responder and time-stamping server settings (in case of TS profile) should be configured before calling out the following method (see also Initialization and Configuration parameters). By default, the RIA's time-stamping service https://eid-dd.ria.ee/ts is used. Container holds the Signature object reference and there is no need cleanup memory.
After the signature has been added to the container, it should be validated before writing the signed container to an output file. For validating the signature, do as follows:
The validation method above validates the signed data files', signer certificate's and OCSP confirmation's correspondence to the signature value. Note that the validation method above does not validate other signatures which may belong to the same container.
After the signature has been added and validated, container changes should be saved (Reading and writing DigiDoc documents):
External signing (two-step signing) can be used in case of signing in web applications, where the signature value is calculated externally, via a browser plug-in or extension.
In order to conduct web signing with Libdigidocpp library, do as follows: Container holds the Signature object reference and there is no need cleanup memory.
In order to read an existing DigiDoc file from the file system, do as follows:
The method above reads in the DigiDoc file from the specified location in file system and creates the respective Container object representing the document's data. The file's structure is also validated during its parsing according to the corresponding standards.
Write a DigiDoc file (represented with a Container object) to file system with the following method:
Validation of a signed DigiDoc document consists of three main steps:
You can validate a signature and its validation data - OCSP confirmation and time-stamp (in case of TS profile) - with method:
If an exception is thrown from the validation method then the signature can be either INVALID or VALID WITH WARNINGS; otherwise the signature is VALID. Before determining the final validation status, additional errors must be checked, as described in the following chapters.
If an exception is thrown then its causes can be retrieved with the following method:
There is a validation case that is not checked in the default validation method of the library, instead, separate method for checking this specific situation has to be implemented by the library’s user. In Libdigidocpp library, checking for an old file format must be done separately.
The following subchapter describes how this check can be implemented. After checking for old signature format errors/warnings, collect all of the error codes and continue with determining the validation status as described in the next chapter. It is possible to check the source code of digidoc-tool or DigiDoc desktop application, accessible from https://github.com/open-eid/DigiDoc4-Client.
After validating the signed DigiDoc document, the validation result must be determined by the library's user. Final validation result must be one of the possible validation statuses that are described in the table below, the status must be chosen according to its priority. The validation status priorities have to be applied in two cases:
| Priority | Status | Error code | Description |
|---|---|---|---|
| 1 | INDETERMINATE/UNKNOWN | 10 CertificateIssuerMissing (signer's certificate is unknown) 6 CertificateUnknown (OCSP responder certificate is unknown) | Validation process determines that one or more of the certificates included in the document are unknown or not trusted, i.e. the certificates have been issued by an unknown Certificate Authority (the CA has not been added to trusted list). Notes:
Suggested warning message (also displayed in DigiDoc desktop application): "Signature status is displayed as unknown if you don't have all validity confirmation service certificates and/or certificate authority certificates available in TSL"
|
| 2 | INVALID | All errors except of the ones that are regarded as warnings by the library's user. | Validation process returns error(s), the errors have not been explicitly determined as minor error(s) by the library's user. |
3
VALID WITH WARNINGS
See the next section.
Validation process returns error(s) that have been previously explicitly categorized (by the library's user) as minor technical errors. Note that this status is used only in exceptional cases, more details of which are given in the next chapter.
4
VALID
N/A
Validation process returns no errors. The signature is legally valid.
The error codes described in the table above are defined in Exception.h source file.
Sample code of DigiDoc file validation can be found from digidoc-tool.cpp utility program, from the following method:
In special cases, validation errors can be regarded as minor technical errors and the file's validation status can be regarded as VALID WITH WARNINGS instead.
It is recommended to use the validation status VALID WITH WARNINGS in case of the error situations that are included in the table below - these error situations are regarded as VALID WITH WARNINGS in DigiDoc applications and software libraries, including:
Table 1. Validation error codes recommended to be handled as VALID WITH WARNINGS
| Error code | Related DigiDoc file format | Description |
|---|---|---|
| 12 RefereneceDigest Weak 13 SignatureDigestWeak | BDOC 2.1 / ASiC | Weaker digest method (SHA-1, SHA-224 or SHA3-224) has been used than recommended when calculating either <Reference> or <Signature> element's digest value. Suggested warning message (also displayed in DigiDoc desktop application): "The current DigiDoc container uses weaker encryption method than officially accepted in Estonia."
|
| 16 ProducedATLateWarning | BDOC 2.1 TS / ASiC | The difference between the time-stamp issuance time (RFC 3161 TSTInfo.genTime) and the OCSP response's issuance time (producedAt value) exceeds 15 minutes but is less than 24 hours. Suggested warning message: "Time-stamp and OCSP issuance time difference is over 15 minutes."
|
| 14 DataFileNameSpaceWarning | DDOC 1.0 DDOC 1.1 DDOC 1.2 DDOC 1.3 | <DataFile> element's xmlns attribute is missing. Suggested warning message (also displayed in DigiDoc desktop application): "This DigiDoc documents has not been created according to specification, but the digital signatures is legally valid. You are not allowed to add or remove signatures to this container." More info: https://www.id.ee/en/article/digital-signing-and-electronic-signatures/
|
| 15 IssuerNameSpace Warning | DDOC 1.1 DDOC 1.2 DDOC 1.3 | <IssuerSerial><X509IssuerName> and/or <IssuerSerial><X509SerialNumber> element's xmlns attribute is missing. Suggested warning message (also displayed in DigiDoc desktop application): "This DigiDoc documents has not been created according to specification, but the digital signatures is legally valid. You are not allowed to add or remove signatures to this container." More info: https://www.id.ee/en/article/digital-signing-and-electronic-signatures/
|
| N/A (Separate error code has not been determined. | DDOC 1.0 DDOC 1.1 DDOC 1.2 | DigiDoc file's version is older than currently supported. Note that the error situation affects only the container and not the signatures, therefore, in DigiDoc libraries, it is returned and displayed only at container level. Suggested warning message (also displayed in DigiDoc desktop application): "The current file is a DigiDoc container that is not supported officially any longer. You are not allowed to add or remove signatures to this container" More info: https://www.id.ee/en/article/digidoc-container-format-life-cycle-2/
|
Overview of validation activities is as follows:
For formats validated through SiVa, archive time-stamp information returned by the service is available through digidoc::Signature::ArchiveTimeStamps in the same way as locally validated archive time-stamps.
Since version 4.5.0, digidoc::Container::extendContainerValidity provides the high-level workflow for extending the validity evidence of a container. The method sets the required signer profile automatically and uses the following strategy:
Only signatures with an Estonian signing certificate are considered for in-place extension, and e-seal signatures are skipped. A container with no applicable Estonian signatures, or with only T-level signatures lacking OCSP validation data, cannot be extended by this workflow.
The returned unique pointer is empty when extension was performed in place. It contains the new ASiC-S container when wrapping was necessary; in that case extendedCount is zero. The caller must save the modified or newly returned container.
The generated language bindings expose the same workflow with language-specific return values:
In every binding, replace the original container with the returned container when the return value is not null/None, then save the resulting container. A null/None result means the original object was modified in place.
A data file can be extracted from container and written to the specified location in the file system or to an output stream.
List of all the document’s data files can be retrieved with the following method:
For example, read in a DigiDoc document and write its data files to file system as follows:
In order to remove a signature from DigiDoc document, use the following method:
Data files can be removed from a container only after all of its signatures have been removed. Use the following method to remove a data file from DigiDoc container:
The index parameters of the methods above are the signature and data file sequence numbers in the container, starting from zero.
After finishing work with Libdigidocpp, then the last task is to shut down the library:
The termination method closes libraries used in Libdigidocpp implementation and deletes temporary files that may have been written to disk when working with the library.
The Libdigidocpp library may throw exceptions that are instances of Exception class (defined in Exception.h source file). The code which uses Libdigidocpp’s API should be wrapped in a try/catch block as follows:
An Exception instance thrown by the library may contain a stack trace of the hierarchy of exceptions. For example, to parse the whole stack trace, do as follows:
Libdigidocpp library supports the following identity tokens:
The library is also tested with the following tokens (indirectly via the DigiDoc desktop application that uses Libdigidocpp as a base component):