# Lacuna Software documentation > Developer documentation for Lacuna Software's digital certificate, digital signature and PKI products: Web PKI, Rest PKI Core, PKI SDK, PKI Express, Signer, Amplia and related services. Index: https://docs.lacunasoftware.com/llms.txt # [Welcome to Lacuna Docs](https://docs.lacunasoftware.com/en-us/articles/welcome) Welcome to [Lacuna Software](https://www.lacunasoftware.com/)'s new unified documentation portal. Using the same documentation technology as the [Microsoft Docs](https://docs.microsoft.com/) portal, this site combines every technical information you need to know about each of our products into a single, interconnected documentation experience. > **Tip** > > This site is targeted for software developers. If you are an end-user having trouble using one of our products, > such as the Web PKI plugin, please go to our [Support Center](http://lacuna.help/) instead If you encounter an error or spot something that is missing on this documentation, please [create an issue](https://github.com/LacunaSoftware/docs/issues). To get started right away, see the article [PKI Solutions Guide](https://docs.lacunasoftware.com/en-us/articles/pki-guide). ## Where to start - [Choosing a product](https://docs.lacunasoftware.com/en-us/articles/welcome/choosing-a-product): which product fits your integration, with a link to each product's quick reference. - [Using these docs with AI agents](https://docs.lacunasoftware.com/en-us/articles/welcome/using-with-ai-agents): llms.txt, the Markdown version of every page, the OpenAPI specifications, and a paragraph to give your coding agent. # [Choosing a product](https://docs.lacunasoftware.com/en-us/articles/welcome/choosing-a-product) Start from what your application has to do. Each product links to its quick reference: install, configuration, core operations, errors and samples on one page. ## Main products | If your application needs to… | Use | |---|---| | Work with the user's certificates in the browser: list them, read them, sign with them on a web page | [Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki/quick-reference) | | Sign, validate and timestamp documents through a REST API, as a cloud service or on its own instance | [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/quick-reference) | | Sign on its own Windows or Linux servers, from a language other than .NET (Java, PHP, Python, Node.js, Ruby…) | [PKI Express](https://docs.lacunasoftware.com/en-us/articles/pki-express/quick-reference) | | Sign, validate and handle certificates inside a .NET application | [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/quick-reference) | | Send documents to people and collect their signatures, with a workflow | [Signer](https://docs.lacunasoftware.com/en-us/articles/signer/quick-reference) | | Issue certificates: run its own certification authorities or a whole PKI | [Amplia](https://docs.lacunasoftware.com/en-us/articles/amplia/quick-reference) | Already integrated with **Rest PKI** at pki.rest? It is a legacy product that still receives bug and security fixes; see its [quick reference (legacy)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/quick-reference). For a new cloud integration, use Rest PKI Core. ## Common combinations - **Signatures on a web page with the user's certificate**: Web PKI does the part that must run in the browser, and a server-side product (Rest PKI Core, PKI SDK or PKI Express) does the rest. The [web signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures) article in the PKI guide explains the approaches. - **Signatures with a key kept on the server**: no browser step. In .NET, the PKI guide recommends PKI SDK; see [server signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/server-signatures). - **Certificate login**: Web PKI in the browser and a server-side product to check the certificate; see [certificate authentication](https://docs.lacunasoftware.com/en-us/articles/pki-guide/cert-auth). ## Other products | Product | What it does | |---|---| | [Amplia Reg](https://docs.lacunasoftware.com/en-us/articles/amplia-reg) | Registration authority for Amplia: confirms who the holder is before a certificate is issued | | [PSC](https://docs.lacunasoftware.com/en-us/articles/psc) | Stores and manages cloud certificates, together with Amplia | | [TSA](https://docs.lacunasoftware.com/en-us/articles/tsa) | Timestamp server (RFC 3161) | | [GrantID](https://docs.lacunasoftware.com/en-us/articles/grant-id) | Single sign-on and multiple authentication factors for your applications | | [Bulk Signer](https://docs.lacunasoftware.com/en-us/articles/bulk-signer) | On-premises service that signs files in bulk | | [Scanner](https://docs.lacunasoftware.com/en-us/articles/scanner) | Adds document scanning to a web application | | [Digiploma](https://docs.lacunasoftware.com/en-us/articles/digiploma) | Issues, registers and publishes digital diplomas following Portaria MEC 554/2019 | | [TrustBridge](https://docs.lacunasoftware.com/en-us/articles/trustbridge) | Remote signatures with ICP-Brasil certificates held by people, on smart cards or USB tokens | To hand these docs to an AI coding agent, see [Using these docs with AI agents](https://docs.lacunasoftware.com/en-us/articles/welcome/using-with-ai-agents). # [Using these docs with AI agents](https://docs.lacunasoftware.com/en-us/articles/welcome/using-with-ai-agents) When an AI coding agent (Claude Code, Cursor, GitHub Copilot, Codex…) writes your integration, point it at the resources below. They hold the same content as the pages you read, in forms an agent fetches and parses easily. The [last section](https://docs.lacunasoftware.com/en-us/articles/welcome/using-with-ai-agents#paste-ready) has a paragraph you can paste into your agent's instructions. ## Start with llms.txt | File | What it holds | |---|---| | [llms.txt](https://docs.lacunasoftware.com/llms.txt) | Index of the English pages, grouped by product, each with its Markdown URL and a one-line description. A product's quick reference comes first. Pages not yet in English link the Portuguese version, marked (pt-br). It ends with the OpenAPI specifications. | | [llms-full.txt](https://docs.lacunasoftware.com/llms-full.txt) | The same pages in full, in one file, each under a heading with its URL. | | [pt-br/llms.txt](https://docs.lacunasoftware.com/pt-br/llms.txt), [pt-br/llms-full.txt](https://docs.lacunasoftware.com/pt-br/llms-full.txt) | The same for the Portuguese pages. | Both follow the [llms.txt](https://llmstxt.org/) format. ## Every page as Markdown Add `.md` to any page URL to get the page as plain Markdown. For example, https://docs.lacunasoftware.com/en-us/articles/signer/get-started.md is the Markdown version of https://docs.lacunasoftware.com/en-us/articles/signer/get-started. - The front matter gives the title, description, canonical URL, locale, product and the date of the last change. - Tabs become one code block per tab, each with a bold label; notes and warnings become blockquotes; links and images are absolute URLs. - Each page links its Markdown version in its HTML head (``) and under its content (**View as Markdown**, **Copy page as Markdown**). - The PKI SDK .NET API reference works the same way: https://docs.lacunasoftware.com/api/Lacuna.Pki/PKCertificate.md. ## Quick references One page per product with what an integration needs first: install, configuration and authentication, core operations with code, errors, test certificates, demos and samples. Facts the docs do not cover yet are marked `TODO(docs)` instead of guessed. - [Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki/quick-reference) - [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/quick-reference) - [PKI Express](https://docs.lacunasoftware.com/en-us/articles/pki-express/quick-reference) - [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/quick-reference) - [Signer](https://docs.lacunasoftware.com/en-us/articles/signer/quick-reference) - [Amplia](https://docs.lacunasoftware.com/en-us/articles/amplia/quick-reference) - [Rest PKI (legacy)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/quick-reference) Not sure which product fits? See [Choosing a product](https://docs.lacunasoftware.com/en-us/articles/welcome/choosing-a-product). ## API specifications The OpenAPI specification of each cloud API is copied to a stable URL on this site. On-premises instances serve their own at `/swagger`. | API | Specification | Live specification | |---|---|---| | Rest PKI Core | [openapi/rest-pki-core.json](https://docs.lacunasoftware.com/openapi/rest-pki-core.json) | https://core.pki.rest/swagger/api/swagger.json | | Signer | [openapi/signer.json](https://docs.lacunasoftware.com/openapi/signer.json) | https://www.dropsigner.com/swagger/api/swagger.json | | Amplia | [openapi/amplia.json](https://docs.lacunasoftware.com/openapi/amplia.json) | https://amplia.lacunasoftware.com/swagger/api/swagger.json | | Amplia Reg | [openapi/amplia-reg.json](https://docs.lacunasoftware.com/openapi/amplia-reg.json) | https://ar.lacunasoftware.com/swagger/api/swagger.json | | CloudHub | [openapi/cloudhub.json](https://docs.lacunasoftware.com/openapi/cloudhub.json) | https://cloudhub.lacunasoftware.com/swagger/v1/swagger.json | | Digiploma | [openapi/digiploma.json](https://docs.lacunasoftware.com/openapi/digiploma.json) | https://www.digiploma.com.br/swagger/api/swagger.json | | Scanner | [openapi/scanner.json](https://docs.lacunasoftware.com/openapi/scanner.json) | https://scn.lacunasoftware.com/swagger/api/swagger.json | | Rest PKI (legacy) | [openapi/rest-pki.json](https://docs.lacunasoftware.com/openapi/rest-pki.json) | https://pki.rest/swagger/docs/v1 | ## Demos and samples - **Demos**: https://try.lacunasoftware.com/demos.json lists the live demos of [try.lacunasoftware.com](https://try.lacunasoftware.com/en), with the product, the docs page and the samples of each. - **Samples**: the [PkiSuiteSamples](https://github.com/LacunaSoftware/PkiSuiteSamples) and [SignerSamples](https://github.com/LacunaSoftware/SignerSamples) repositories each keep a `samples.json` catalog: one entry per task and language, with the file to read, how to run it, the docs page and the demo. - Pages that cover a task end with a **Demos and samples** box linking the demo and the sample in each language. ## A paragraph to give your agent Paste this into your agent's instructions (for example `CLAUDE.md`, `AGENTS.md` or `.cursor/rules`), and name the product you use: ```text This project integrates Lacuna Software products (digital certificates, digital signatures, PKI). Use the official docs at https://docs.lacunasoftware.com and read them as Markdown: - Start with https://docs.lacunasoftware.com/llms.txt, the index of all pages by product. - Add ".md" to any docs page URL to get its Markdown version. - Read the product's quick reference first (listed first under the product in llms.txt): packages, configuration, core operations, errors and samples. - For REST APIs, use the OpenAPI specs at https://docs.lacunasoftware.com/openapi/ (listed at the end of llms.txt). - For working code, follow the samples linked from the docs pages (PkiSuiteSamples and SignerSamples on GitHub) in this project's language. Do not guess package names, versions, endpoints or headers: take them from the quick reference, the OpenAPI spec or a sample. When developing, use the test certificates from https://docs.lacunasoftware.com/en-us/articles/pki-guide/test-certs, never production certificates. ``` # [Lacuna product licensing](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing) This page brings together, in one place, what you need to **obtain, activate, renew and use** the licenses of Lacuna Software products. It was compiled from each product's documentation, which remains the detailed reference: each product's section ends with links to the source articles. > **Tip: Are you an end user?** > > If you only use a website or system that asks for Web PKI to sign documents or sign in with a digital certificate, > **you don't need to buy or configure any license**. The license belongs to whoever develops and maintains the website. > See [For end users](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#usuario-final). ## Summary by product | Product and scenario | License needed? | What is used | |---|---|---| | [Web PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki) in an application on *localhost* (development) | No | — | | [Web PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki) with cloud Rest PKI (`https://pki.rest`) | No, even in production | — | | [Web PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki) in all other cases, outside *localhost* | Yes | Web PKI license, set in the page's JavaScript | | Cloud [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki) | No license file | Account on `pki.rest` and access token | | On-premises [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki) | Yes | PKI SDK license (`LacunaPkiLicense.txt` file) | | Cloud [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core) (`core.pki.rest`) | No license file | Endpoint and API key, provided by support | | On-premises [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core) | Yes | PKI SDK license (required) and Web PKI license (for signing in the browser) | | [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-sdk) | Yes | PKI SDK license (`LacunaPKILicense.config` file or Base64 text) | | [PKI Express](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-express) | Yes | `LacunaPkiLicense.config` file, used to activate PKI Express on the machine | | On-premises [Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer) | Yes | PKI SDK license and Web PKI license | | [Bulk Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#bulk-signer) | Yes | PKI SDK license (Base64 text) | | [End user](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#usuario-final) of a website or system | No | — | ## Understanding the licenses The products on this page use one or more of these licenses: - **PKI SDK license**: the license of Lacuna's .NET library. It is used directly by applications built on the [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-sdk), and it is also required to install [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki), [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core), [Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer) and [Bulk Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#bulk-signer) on-premises. It is delivered as a file (`LacunaPKILicense.config` or, for on-premises Rest PKI, `LacunaPkiLicense.txt`) or as Base64 text. A PKI SDK license may be restricted to use with Rest PKI. - **Web PKI license**: authorizes the browser component on a website's domains. The developer sets it in the page's JavaScript code and, for on-premises Rest PKI Core and Signer, also in the server configuration. - **PKI Express license**: the `LacunaPkiLicense.config` file, used to activate PKI Express on the machine where it is installed. Cloud services use no license file: you access them with your account's credentials, such as the Rest PKI **access token** and the Rest PKI Core **API key**. These credentials don't replace the Web PKI license where one is needed (see [When the Web PKI license is needed](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki-quando)). > **Info: What "updating the license version" means** > > In practice, it is one of these situations: > > 1. **The license has expired, is about to expire, or must cover something new**, such as a new domain for Web PKI. > You receive a new license and replace the configured value. > 2. **You are about to upgrade an on-premises product.** A PKI SDK license only accepts SDK versions released up to a > certain date. So, before upgrading Signer or Rest PKI Core, check the changelog to see whether your license covers > the target version. If it doesn't, ask for an updated license before upgrading. > > The [step-by-step guide to updating a license](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#atualizar) applies to both cases. ## How to obtain a license | Product | How to request it | |---|---| | PKI SDK | Free trial license from the pki.lacunasoftware.com website | | Web PKI | Through [Contact us](https://www.lacunasoftware.com/en/home/purchase) or by email at [support@lacunasoftware.com](mailto:support@lacunasoftware.com), stating the hostnames or URLs where the component will be used. PKI SDK licenses usually come with a Web PKI license | | PKI Express | Test license through [Contact us](https://www.lacunasoftware.com/en/home/purchase) | | On-premises Rest PKI | Test license through [Contact us](https://www.lacunasoftware.com/en/home/purchase) | | On-premises Rest PKI Core and Signer | Use the PKI SDK and Web PKI licenses (rows above) | | Bulk Signer | Lacuna provides the license (Base64 text) together with the credentials to access the product | | Cloud Rest PKI | Create an account on [pki.rest](https://pki.rest/) and generate an access token on the **Control Panel**. See the [pricing](https://www.lacunasoftware.com/en/pricing/#cloud-simulator) | | Cloud Rest PKI Core | Ask [developer support](mailto:support@lacunasoftware.com) for the endpoint and the API key | When you make the request, we recommend stating: - the product and the environment where the license will be used (production, staging or testing); - for **Web PKI**, the production and staging hostnames or URLs. Private IP ranges are already allowed for staging (see [Usage on private IPs](https://docs.lacunasoftware.com/en-us/articles/web-pki/licensing#usage-on-private-ips)); - if the license is meant for **upgrading** an on-premises product, the version you intend to install. ## Step-by-step guide to updating a license 1. **Identify the license and where it is configured**, using the table below. One product may use more than one license: Signer, for example, uses the PKI SDK license and the Web PKI license. 2. **If the replacement comes with a version upgrade**, read the product's changelog between the current version and the target version. Look for notices such as *"make sure your license supports PKI SDK versions released until YYYY-MM-DD"*. 3. **Obtain the new license** through the channels in [How to obtain a license](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#adquirir). 4. **Replace the whole value** in the same place where the old license is configured. Base64 licenses must be pasted in full, on a single line. The Web PKI JSON license must be used in full. 5. **Restart the application or service** for products that read the license at startup (PKI SDK, Rest PKI Core, Signer and Bulk Signer). For on-premises Rest PKI, the license is replaced on the administration screen. 6. **Confirm that the new license was loaded**, with the check given for the product. | Product | Where the license is | How to confirm | |---|---|---| | [Web PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki-atualizar) | Page JavaScript: `new LacunaWebPKI(license)` or the `license` parameter of `init()` | No license error from the component. In the JSON format, check `expiration` and the domains | | [On-premises Rest PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-trocar) | **Administration** > **System status** > **SDK license loaded** | The same screen shows the licensee and the expiration date | | [On-premises Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core-trocar) | Configuration file or environment variables (on Azure, `PkiSuite__SdkLicense` and `PkiSuite__WebLicense`) | The service responds again on `/api/system/info` (which shows only the version, not the license details); test a signature | | [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-sdk-atualizar) | `LacunaPKILicense.config`, `Web.config`/`App.config` or `PkiConfig.LoadLicense` | `PkiInfo.License` (licensee and expiration) | | [PKI Express](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-express-atualizar) | Machine activation (`pkie activate` or `pkiemgr.exe`) | Commands run without the activation and license error codes (17 to 21) | | [On-premises Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-trocar) | `PkiSuite` section (`SdkLicense` and `WebLicense`) | Since 2.2.0, an invalid PKI SDK license stops startup: check `/api/system/info`. For the Web PKI license, test a signature in the browser | | [Bulk Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#bulk-signer-trocar) | `Signing__PkiSdkLicense` (or `Signing:PkiSdkLicense`) | License fingerprint in the startup banner and on the dashboard | ## Web PKI [Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki) is the component that lets a website use the digital certificates on the user's computer. The Web PKI license belongs **to the website**: it covers the application's domains and is set by the developer, in the page code. ### When the license is needed The license is **not** needed: - to test in an application running on *localhost* (any port); - when Web PKI is used with **cloud Rest PKI** (`https://pki.rest`), even in production. In all other cases outside *localhost*, the license is needed. This includes: - applications that use Web PKI with the [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-sdk), [PKI Express](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-express) or any other backend (PKI SDK licenses usually come with a Web PKI license); - applications that use an [on-premises Rest PKI instance](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-on-premises), that is, a Rest PKI other than `https://pki.rest`. In that case, also set the instance URL in `restPkiUrl`; - applications that use [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core), including in the cloud (`core.pki.rest`): the exemption applies only to cloud Rest PKI (`https://pki.rest`). The Web PKI license also goes into the server configuration of on-premises products: for [Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-licencas), it is listed as required in the Linux and Azure installations; for [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core-licencas), it is needed when users sign in the browser through Web PKI. **Staging:** licenses are issued allowing staging use on any private IP (`10.x.x.x`, `127.x.x.x`, `172.16.0.0` to `172.31.255.255` and `192.168.x.x`). Staging domains, such as `staging.patorum.com`, go in the license's `homologDomains` field. ### License formats You receive the license in two equivalent formats: ```javascript // Binary license var webPkiLicense = 'ASYAanNma...Q=='; // JSON license var webPkiLicense = { "format": 1, "allowedDomains": [ "www.patorum.com" ], "homologDomains": [ "staging.patorum.com", "ip4:10.0.0.0/8", "ip4:127.0.0.0/8", "ip4:172.16.0.0/12", "ip4:192.168.0.0/16" ], "productLevel": "Standard", "expiration": null, "signature": "LzdT1cgp...w==" }; ``` - The **binary** format hides the license details. They are not encrypted, only Base64-encoded. - The **JSON** format keeps the details readable, which makes it easier to diagnose problems such as an expired license. - In the server configuration of Rest PKI Core and Signer, use the **binary** license. > **Warning** > > The `signature` field of the JSON license does not work as a license on its own. Use the whole binary license or the > whole JSON license: any attempt to use only part of the license makes the component reject it. ### How to configure it Pass the license to the constructor of the `LacunaWebPKI` class: ```javascript var pki = new LacunaWebPKI('ASYAanNma...Q=='); // or the whole JSON object pki.init({ ready: onWebPkiReady }); ``` The license can also be set in the `license` parameter of the `init()` method, if it was not passed to the constructor. With a Rest PKI other than `https://pki.rest`, also set the instance URL: ```javascript var pki = new LacunaWebPKI('ASYAanNma...Q=='); pki.init({ restPkiUrl: 'https://YourRestPKI.com/', ready: onWebPkiReady }); ``` ### How to update the license 1. Request the new license by email at [support@lacunasoftware.com](mailto:support@lacunasoftware.com) or through [Contact us](https://www.lacunasoftware.com/en/home/purchase) (because it is expiring or to add a domain, for example), stating the production and staging hostnames or URLs. 2. Replace the old license with the new one **in the same place** where it is set: in the `new LacunaWebPKI(...)` constructor, in the `license` parameter of `init()` or, for the [ICPBravoAccess replacement](https://docs.lacunasoftware.com/en-us/articles/web-pki/icpbravo-replacement), in `window.lacunaWebPkiLicense`. Replace the whole license. 3. Publish the page and test it on the staging and production domains. 4. If the Web PKI license is also configured in an on-premises product, replace it there too: [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core-trocar) and [Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-trocar). > **Note** > > Don't confuse the license with the component version. Web PKI is updated automatically on users' computers, and the > JavaScript library (`lacuna-web-pki-{version}.js`) must be updated by the developer. See > [Web PKI updates](https://docs.lacunasoftware.com/en-us/articles/web-pki/update). ### License errors When there is a problem with the license, the component returns one of these error codes ([`LacunaWebPKI.ErrorCodes`](https://docs.lacunasoftware.com/content/typedocs/web-pki/enums/_lacuna_web_pki_d_.lacunawebpki.errorcodes.html)): | Code | Meaning | |---|---| | `license_not_set` | A license is required and was not set | | `license_invalid` | The license provided is not valid | | `license_restricted` | The license does not allow the requested command | | `license_expired` | The license has expired | | `license_domain_not_allowed` | The license does not allow the domain in use | **Source articles:** [Web PKI licensing](https://docs.lacunasoftware.com/en-us/articles/web-pki/licensing) · [Get started](https://docs.lacunasoftware.com/en-us/articles/web-pki/get-started) · [Specifying the Rest PKI URL](https://docs.lacunasoftware.com/en-us/articles/web-pki/customizing-restpki-url) · [Updates](https://docs.lacunasoftware.com/en-us/articles/web-pki/update) ## Rest PKI > **Note: Rest PKI and Rest PKI Core are different products** > > Each has its own documentation, its own cloud (`pki.rest` and `core.pki.rest`) and its own access method. This > section covers [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/rest-pki). Rest PKI Core has [its own section](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core). ### Cloud Rest PKI Cloud Rest PKI uses no license file. Access is granted with an **access token** from your account: 1. Sign in to the Rest PKI website ([pki.rest](https://pki.rest/)). 2. On the **Control Panel**, click **Generate new access token** and copy the generated value. 3. Configure the token in your application (in the sample projects, in the configuration file, such as `web.config`). In direct HTTP calls, such as timestamp requests, send it in the `Authorization: Bearer ` header. A **401 Unauthorized** response means that the token provided is not valid. With cloud Rest PKI, Web PKI needs no license, even in production. ### On-premises Rest PKI An on-premises Rest PKI instance, on Windows Server or Azure App Service, requires a **Lacuna PKI SDK license**, requested during setup. Since version 1.5.0, Rest PKI also accepts PKI SDK licenses restricted to use with Rest PKI. To install it, you need: - the Rest PKI binaries package; - the binary PKI SDK license (`LacunaPkiLicense.txt` file). If you don't have one yet, [request a test license](https://www.lacunasoftware.com/en/home/purchase). On Windows Server, setup follows chapter 2 of the [setup manual](https://cdn.lacunasoftware.com/restpki/restpki-admin-guide-pt.pdf) (in Portuguese). On Azure App Service, once you have the package and the license, [contact us](https://www.lacunasoftware.com/en/home/purchase) to get the setup instructions. If your application uses Web PKI with the on-premises instance, also configure the **Web PKI license** and the instance URL (see [How to configure Web PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki-configurar)). Starting with version 1.14.0, the Rest PKI dashboard shows a warning when the PKI SDK license is close to expiring. Version 1.12.0 fixed an error that occurred when changing the PKI SDK license; on older instances, consider upgrading before changing the license. ### How to change the license 1. Sign in as administrator on your Rest PKI instance. If you don't know the password, see [Recover administrator password](https://docs.lacunasoftware.com/en-us/articles/rest-pki/on-premises/admin-recover). 2. On the top menu, click **Administration** > **System status**. 3. On the **SDK license loaded** item, click the **Change** button. 4. In the `LacunaPkiLicense.txt` file, locate the binary PKI SDK license, under the *Binary license content (Base64-encoded)* section: ```text Binary license content (Base64-encoded) --------------------------------------- AxAA........................................iw== ``` 5. Copy and paste **the entire line** and click the **Configure license** button. ![SDK license loaded item on the Rest PKI system status screen](https://docs.lacunasoftware.com/images/rest-pki/sdk-license.png) The same screen shows the licensee and the expiration date of the loaded license. **Source articles:** [Change license](https://docs.lacunasoftware.com/en-us/articles/rest-pki/on-premises/change-license) · [Rest PKI on-premises](https://docs.lacunasoftware.com/en-us/articles/rest-pki/on-premises) · [Setup on Windows Server](https://docs.lacunasoftware.com/en-us/articles/rest-pki/on-premises/windows-setup) · [Setup on Azure App Service](https://docs.lacunasoftware.com/en-us/articles/rest-pki/on-premises/azure-setup) · [Requesting timestamps](https://docs.lacunasoftware.com/en-us/articles/rest-pki/requesting-timestamps) ## Rest PKI Core [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core) can be used in the cloud (SaaS), at [core.pki.rest](https://core.pki.rest/), or on your own instance (on-premises). ### Cloud Rest PKI Core On SaaS, the application uses no license file. It needs two parameters, which you request from [developer support](mailto:support@lacunasoftware.com): - the API **endpoint**; - the **API key**. In ASP.NET Core, both go in the `RestPki` section of `appsettings.json` (keys `Endpoint` and `ApiKey`). When you call the API directly, the API key goes in the `X-Api-Key` header (on the timestamp endpoints, use `Authorization: ApiKey YOUR_API_KEY`; see [Requesting timestamps](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/requesting-timestamps)). A **401** response means a missing or invalid key, and a **403** means the application is not allowed to perform the operation. If your application uses Web PKI with Rest PKI Core, the Web PKI license is needed: the exemption applies only to cloud Rest PKI (`https://pki.rest`). ### On-premises instance licenses An on-premises instance needs two licenses: - the **PKI SDK license**, in Base64; - the **Web PKI license**, in binary (Base64) format. | Platform | Where the licenses are configured | |---|---| | [Windows Server](https://docs.lacunasoftware.com/articles/rest-pki/core/on-premises/windows-server) (in Portuguese) | `appsettings.ini` file in the `C:\Program Data\Lacuna Software\Rest PKI Core` folder (not the copy in `config-templates`) | | [Linux (Ubuntu)](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises/linux/install-ubuntu) | `/etc/restpkicore/appsettings.conf` file | | [Docker](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises/docker) | Environment variables (sample file `restpkicore.env`) | | [Azure App Services](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises/azure/install) | App Service *Configuration*: `PkiSuite__SdkLicense` and `PkiSuite__WebLicense` | On Azure, `PkiSuite__SdkLicense` is required, and `PkiSuite__WebLicense` is only required if users will sign documents with certificates on their computers (signing in the browser through Web PKI). On the other platforms, both licenses are listed as setup prerequisites. For Rocky Linux, see [Setup on Rocky Linux](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises/linux/install-rocky). In the configuration files (Windows, Linux and Docker), fill in the licenses following the instructions in the template file itself. For environment variables, the name is the section and the setting separated by `__` (two underscores): the `SdkLicense` setting of the `PkiSuite` section, for example, becomes `PkiSuite__SdkLicense`. ### How to change the license > **Note** > > The Rest PKI Core documentation has no specific article on changing the license. The steps below follow each > platform's configuration and restart procedures. - **Linux**: edit `/etc/restpkicore/appsettings.conf`, replace the license and restart the service with `systemctl restart restpkicore`. Follow the logs with `journalctl -u restpkicore -f`. - **Windows Server**: edit `appsettings.ini`, replace the license and restart the site in IIS (*Stop* and *Start*). - **Docker**: change the license in the environment variables file (for example, `restpkicore.env`). Because the variables are read when the container is created, remove the current container (`docker rm -f restpkicore`) and create it again with the same `docker run --name restpkicore --env-file restpkicore.env ...` command used for setup. Check the logs with `docker logs -f restpkicore`. - **Azure App Services**: in *Configuration*, change `PkiSuite__SdkLicense` and/or `PkiSuite__WebLicense` and click **Save**. After the change, check that the instance responds on `https://your-restpki-core-address/api/system/info`. ### Before upgrading Some versions require the PKI SDK license to support versions released up to a certain date: | Rest PKI Core version | The PKI SDK license must support versions released until | |---|---| | [2.0.0 RC 8](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/changelog#v2.0.0-rc08) | 2023-06-27 | | [2.0.0 RC 7](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/changelog#v2.0.0-rc07) | 2022-10-19 | Before upgrading, read the [changelog](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/changelog) between your version and the target version. The installed version is shown on `/api/system/info` (see [Checking the installed version](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises/check-version)). **Source articles:** [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core) · [Getting started with integration](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/get-started) · [On-premises environments](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises#platforms) · [Setup on Azure App Services](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/on-premises/azure/install) · [Changelog](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/changelog) ## PKI SDK [Lacuna PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk) is a .NET library, distributed through NuGet (package `Lacuna.Pki`). To use it, the application must load the license at startup. ### How to obtain the license If you don't have a license yet, get in touch through the pki.lacunasoftware.com website for a free trial license. The license can be used in two formats: - `LacunaPKILicense.config` file; - Base64 text. If your application signs in the browser, it also uses [Web PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#web-pki), which needs its own license outside *localhost*. PKI SDK licenses usually come with a Web PKI license. ### How to load the license There are three ways. The recommended one depends on the type of application: | Method | Recommended for | |---|---| | `LacunaPKILicense.config` file in the DLL directory | Web applications | | Key in `Web.config` or `App.config` | — | | Programmatically, with `PkiConfig.LoadLicense` | Desktop applications | **1. File in the DLL directory.** The SDK automatically looks for the `LacunaPKILicense.config` file next to `Lacuna.Pki.dll`. A convenient way is to include the file in the project with **Build Action** = **Content** and **Copy to Output Directory** = **Copy Always**. **2. `Web.config` or `App.config`.** In the `appSettings` section, set the file path or the Base64 license: ```xml ``` **3. Programmatically.** In the startup code of the website or application, load the decoded license: ```csharp byte[] binLicense = Convert.FromBase64String("[Base64 license]"); PkiConfig.LoadLicense(binLicense); ``` This method embeds the license in the source code, which makes it harder to leak to third parties. There is also `PkiConfig.LoadLicense(string)`, which takes the path of the `.config` file, but it is not recommended for desktop applications. ### How to update the license > **Note** > > The PKI SDK licensing page does not describe how to change the license. Because the license is loaded at startup, the > procedure is to replace it where it was configured and restart the application. 1. Replace the license in the same place where it was configured: the `LacunaPKILicense.config` file, the `LacunaPKI.LicensePath` or `LacunaPKI.BinaryLicense` key, or the value passed to `PkiConfig.LoadLicense`. 2. If the license is included in the project or embedded in the code, rebuild and publish the application. 3. Restart the application or website. 4. To check the loaded license, use the `PkiInfo.License` property (class [`PkiInfo`](https://docs.lacunasoftware.com/en-us/api/Lacuna.Pki.Util/PkiInfo)), which gives the licensee (`Licensee`) and the expiration date (`Expiration`). In on-premises products that use the PKI SDK license, the license is replaced in each product's configuration: see [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-trocar), [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core-trocar), [Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-trocar) and [Bulk Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#bulk-signer-trocar). ### License and SDK versions A PKI SDK license may have an expiration date (check `PkiInfo.License.Expiration`), and it only accepts SDK versions released up to a certain date. That is why the products that use the PKI SDK state, in their changelogs, what coverage the license needs before an upgrade (see [Signer](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-versao) and [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#rest-pki-core-versao)). **Source articles:** [PKI SDK licensing](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/get-started/licensing) · [Accessing NuGet packages](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/get-started/nuget) · [Signing in the browser](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/signatures/web-remote) ## PKI Express [PKI Express](https://docs.lacunasoftware.com/en-us/articles/pki-express) is installed on Windows or Linux and **requires a license**: the `LacunaPkiLicense.config` file, used to activate PKI Express on the machine. ### How to obtain the license [Contact us](https://www.lacunasoftware.com/en/home/purchase) for a test license. ### Activation on Windows 1. Install PKI Express with the installer or, without administrator permissions, with one of the zip packages (see [Setup on Windows](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/windows)). 2. Open the installation folder and run the **PKI Express Configuration Manager** (`pkiemgr.exe` file). There is no Start menu shortcut: you must browse to the folder. 3. Follow the app's instructions to activate PKI Express. On Windows, both network and manual activation are done through this app. ### Activation on Linux After installing the package and configuring the logs folder (see [Ubuntu or Mint](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/linux-ubuntu#install), [Red Hat Enterprise Linux](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/linux-rhel#install) or [CentOS, Oracle Linux or Fedora](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/linux-centos#install)), activate PKI Express with the license file: ```sh sudo pkie activate LacunaPkiLicense.config ``` If automatic activation fails, use [manual activation](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-express-manual). ### Manual activation (Linux) 1. Generate the activation request: ```sh pkie activate LacunaPkiLicense.config --request ``` A file named `pkie-activation-request.pem` is saved in the current folder. 2. Send this file through the [Support Center](http://lacuna.help). 3. You will receive back the `pkie-activation.pem` activation file. Copy it to the current folder and run: ```sh sudo pkie activate ``` Or, if you prefer, give the file path: ```sh sudo pkie activate --file /path/to/pkie-activation.pem ``` ### Changing the license and upgrading > **Note** > > The PKI Express documentation has no specific article on changing the license. To apply a new license, activate again > with the new `LacunaPkiLicense.config` file: on Linux, with `sudo pkie activate LacunaPkiLicense.config` (or through > [manual activation](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#pki-express-manual)); on Windows, through `pkiemgr.exe`. Manual activation with a new license was > fixed in version [1.6.2](https://docs.lacunasoftware.com/en-us/articles/pki-express/changelog#v1-6-2); use that version or later. Upgrading the PKI Express **version** is a different procedure: - **Windows**: download the new version and run the installer (see [Update](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/windows#update)). - **Linux**: download the new package, delete the contents of the target folder and extract the new package into it (see Update on [Ubuntu or Mint](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/linux-ubuntu#update), [RHEL](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/linux-rhel#update) or [CentOS, Oracle Linux or Fedora](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/linux-centos#update)). If you are upgrading from a 1.0.x version, also configure the logs folder and activate again. ### Return codes | Code | Name | Meaning | |---|---|---| | 17 | `NotActivated` | PKI Express is not activated | | 18 | `ActivationError` | PKI Express activation failed | | 19 | `BadLicense` | Invalid Base64 (of the activation license) | | 20 | `LicenseNeeded` | No license file was provided | | 21 | `InvalidLicense` | Invalid license | **Source articles:** [PKI Express](https://docs.lacunasoftware.com/en-us/articles/pki-express) · [Setup](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup) · [Manual activation](https://docs.lacunasoftware.com/en-us/articles/pki-express/setup/manual-activation) · [Return codes](https://docs.lacunasoftware.com/en-us/articles/pki-express/return-codes) ## Signer An on-premises [Signer](https://docs.lacunasoftware.com/en-us/articles/signer) instance needs two licenses: - the **PKI SDK license**, in Base64; - the **Web PKI license**, in binary (Base64) format. ### Where the licenses are configured | Platform | Where to configure them | |---|---| | [Linux (Ubuntu)](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/linux/install-ubuntu) | `/etc/lacuna-signer/appsettings.linux.json` file, `PkiSuite` section: `SdkLicense` and `WebLicense` | | [Azure App Services](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/azure) | App Service *Configuration*: `PKiSuite__SdkLicense` and `PKiSuite__WebLicense` | | [Windows Server](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/windows) | `appsettings.iis.json` file, `PkiSuite` section: `SdkLicense` and `WebLicense` | | [Docker](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/docker) | `PkiSuite__SdkLicense` and `PkiSuite__WebLicense` environment variables | On the Linux and Azure setup pages, both licenses are required. In the Windows Server and Docker articles, only `SdkLicense` is listed as required, and `WebLicense` appears as conditional. Either way, the Web PKI license is needed for [embedded signature](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-embutida). Starting with version 2.2.0, the PKI SDK license is validated at startup: if it is not valid, startup is aborted. ### How to change the license > **Note** > > The Signer documentation has no specific article on changing the license. The steps below follow each platform's > setup and update procedures. - **Linux**: edit `/etc/lacuna-signer/appsettings.linux.json`, replace `SdkLicense` and/or `WebLicense` in the `PkiSuite` section and restart the service with `systemctl restart lacuna-signer`. Check it with `systemctl status lacuna-signer` and follow the logs with `journalctl -u lacuna-signer -f`. - **Azure App Services**: in *Configuration*, change `PKiSuite__SdkLicense` and/or `PKiSuite__WebLicense` and click **Save**. - **Windows Server**: stop the site in IIS, change the `PkiSuite` section of `appsettings.iis.json` and start the site again. - **Docker**: change the `PkiSuite__SdkLicense` and/or `PkiSuite__WebLicense` variables and recreate the container. After the change, check that the instance responds on `/api/system/info` (on Linux, for example, `curl http://localhost:5001/api/system/info`). ### Before upgrading Signer Some versions require the PKI SDK license to support SDK versions released up to a certain date. Read the [changelog](https://docs.lacunasoftware.com/en-us/articles/signer/changelog) between the current version and the target version: | Signer version | The license must support PKI SDK versions released | |---|---| | [2.2.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v2-2-0) | until 2025-08-01 | | [2.0.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v2-0-0) | until 2025-05-20 | | [1.72.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v1-72-0) | until 2024-07-03 | | [1.64.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v1-64-0) | until 2023-09-27 | | [1.61.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v1-61-0) | until 2023-08-01 | | [1.59.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v1-59-0) | until 2023-06-28 | | [1.58.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v1-58-0) | until 2023-05-25 | | [1.43.0](https://docs.lacunasoftware.com/en-us/articles/signer/changelog#v1-43-0) | after 2022-04-29 | If your license doesn't cover the required date, get an updated PKI SDK license before upgrading. ### Embedded signature To use [embedded signature](https://docs.lacunasoftware.com/en-us/articles/signer/embedded-signature) (the `LacunaSignerWidget` component) in another application, Signer must be configured with a Web PKI license that includes the domain where the component will be loaded. To add a new domain, get a new Web PKI license and replace it as described in [How to change the license](https://docs.lacunasoftware.com/en-us/articles/welcome/licensing#signer-trocar). **Source articles:** [Setup on Ubuntu Server](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/linux/install-ubuntu) · [Setup on Azure App Services](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/azure) · [Update on Linux](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/linux/update) · [Changelog](https://docs.lacunasoftware.com/en-us/articles/signer/changelog) ## Bulk Signer [Bulk Signer](https://docs.lacunasoftware.com/en-us/articles/bulk-signer) uses a single license: the **Lacuna PKI SDK license**, a Base64 text provided by Lacuna Software. It is required: without it, the service does not start. ### How to obtain it Lacuna delivers three items, which are not interchangeable: - the registry credentials (user name and access token), to pull the container image; - a unique identifier, used in the binaries download URLs; - the PKI SDK license, which unlocks the running service. Because the license is just text, and not a download, it also works on air-gapped servers. ### Where to configure it The preferred way is the `Signing__PkiSdkLicense` environment variable. You can also use the `Signing:PkiSdkLicense` key in `appsettings.Production.json`, as long as the file is kept out of version control and its access is restricted to the service account. The variable is preferred because it keeps the license out of the file tree, and it takes precedence at startup. | Target | Where to set `Signing__PkiSdkLicense` | How to apply | |---|---|---| | Linux (systemd) | `/etc/bulksigner/bulksigner.env` file (mode `0640`, owned by `bulksigner`) | `sudo systemctl restart bulksigner` | | Windows (service) | Machine-scope environment variable | `Restart-Service LacunaBulkSigner` | | Docker / Compose | `deploy/docker/.env` file | `docker compose up -d` | | Azure App Service | *App settings*, as a Key Vault reference | See [Azure App Service](https://docs.lacunasoftware.com/en-us/articles/bulk-signer/azure) | On Windows, set the variable in an elevated PowerShell: ```powershell [Environment]::SetEnvironmentVariable("Signing__PkiSdkLicense", "", "Machine") Restart-Service LacunaBulkSigner ``` > **Warning: Upgrading from 1.0.x** > > In version 1.0.x, the key was named `Signing:License` (`Signing__License`). It was renamed in 1.1.0 and the old name > is no longer read: an upgraded installation that still uses the old name fails at startup with > `Signing:PkiSdkLicense is required`. Rename the key as part of the upgrade. ### How to change the license 1. Note the fingerprint of the current license: the `pki license` line of the startup banner, or the **System** page (`/system`) of the dashboard, **License fingerprint** field. 2. Replace the value of `Signing__PkiSdkLicense` in the place given for your target (table above). If you use `Signing:PkiSdkLicense` in `appsettings.Production.json`, make sure no old environment variable is set, because it takes precedence. 3. Restart the service. 4. Check that the license fingerprint changed and that the `/api/ready` endpoint does not report a failure in the `license` check. ### Troubleshooting - **`Signing:PkiSdkLicense is required`**: neither the environment variable nor the configuration has a value. Set the variable on the target and restart the service. - **`/api/ready` returns 503 with a failure in the `license` check**: the license was not loaded. If the fingerprint does not appear in the banner, the license was rejected at startup. **Source articles:** [Installation](https://docs.lacunasoftware.com/en-us/articles/bulk-signer/installation) · [Configuration](https://docs.lacunasoftware.com/en-us/articles/bulk-signer/configuration) · [Security](https://docs.lacunasoftware.com/en-us/articles/bulk-signer/security) · [Troubleshooting](https://docs.lacunasoftware.com/en-us/articles/bulk-signer/troubleshooting) ## For end users This section is for people who use a website or system that asks for **Web PKI**, Lacuna's browser extension, to sign documents or sign in with a digital certificate. ### Do I need to buy or configure a license? No. When Web PKI requires a license, it belongs to the website: it covers the website's domains and is configured by whoever develops it, in the page code (websites that use cloud Rest PKI don't even need one). People who only install the extension to use the website don't buy or configure any license. If the website shows a Web PKI license error (for example, an expired license or a domain that is not allowed), the problem lies in the website's configuration. Report it to the company responsible for the website. ### Digital certificate: who issues it? Web PKI does not issue digital certificates. It lets the website use a certificate you already have, either an A1 certificate, installed on the computer, or an A3 certificate, on a cryptographic device such as a token or smart card. ICP-Brasil certificates are purchased from an accredited Certification Authority (CA), listed on the [official ITI list](https://www.gov.br/iti/pt-br/assuntos/icp-brasil/entidades-icp-brasil) (in Portuguese). Questions about buying, validity or renewal of the certificate should be taken to the CA that issued it. To check, on Windows, whether there is a certificate with a private key on the computer: 1. **Start** > **Run...** > **certmgr.msc** 2. In the **Personal** folder, double-click the certificate. 3. The message "You have a private key that corresponds to this certificate." should appear. ### Installing Web PKI - If the component is not installed, is out of date or the browser is not supported, the website usually takes you to the installation page and, at the end, you are automatically sent back to the website (the website may show its own message first). - Web PKI is only installed from [get.webpkiplugin.com](https://get.webpkiplugin.com): the extension comes from the browser's official store, and the native app is downloaded from that same domain. - Once installed, Web PKI is updated automatically. - See the [supported browsers](https://docs.lacunasoftware.com/en-us/articles/web-pki/browser-support). ### Where to get help - **License errors or questions about the website's service**: talk to the company responsible for the website. Requests about your personal data should also be made to it, as it is the data controller. - **Problems installing or using Web PKI**: visit Lacuna's [Support Center](http://lacuna.help/). - When asking for support, it helps to turn on verbose logging: click the extension icon and go to **Settings** > **Advanced** > **Verbose logging** (see [Logs](https://docs.lacunasoftware.com/en-us/articles/web-pki/logs)). ## Contacts | Channel | What for | |---|---| | [Contact us](https://www.lacunasoftware.com/en/home/purchase) | Requesting licenses, test licenses and sales information | | [support@lacunasoftware.com](mailto:support@lacunasoftware.com) | Developer support, Web PKI license requests and the parameters for cloud Rest PKI Core | | [Support Center](http://lacuna.help/) | End users and PKI Express manual activation | | pki.lacunasoftware.com | Free PKI SDK trial license | | +55 61 3030-5700 | Phone. Address: EQN 102/103, Ed. Avenida 102, 2nd floor, Asa Norte, Brasília-DF, Brazil | # [Contributing](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing) We are not taking public contributions at the moment, but will soon begin accepting pull requests. For now, if you encounter an error or spot something that is missing on this documentation portal, please [create an issue](https://github.com/LacunaSoftware/docs/issues) ## Creating a new article Follow these guidelines to create a new article: 1. Create the article **on both en-us and pt-br projects** with encoding UTF-8 BOM 1. Alter the `toc.md` **from both projects** including the article > **Tip** > > An easy way to ensure that the new article has UTF-8 BOM encoding is to copy an existing article instead of creating a new file. You don't need to write both versions of the article right away, you can write one of the versions and put this on the other one: ```md # Article title {/* link to version in Portuguese */}
``` or ```md # Título do Artigo {/* link to version in English */}
``` ## Authoring documentation Here are the most important links about how to author documentation: * [Mastering Markdown - GitHub Guides](https://guides.github.com/features/mastering-markdown/) * [DocFX Flavored Markdown - DocFX website](https://dotnet.github.io/docfx/spec/docfx_flavored_markdown.html) * [Links and Cross References - DocFX website](https://dotnet.github.io/docfx/tutorial/links_and_cross_references.html) * [Overwrite Files - DocFX website](https://dotnet.github.io/docfx/tutorial/intro_overwrite_files.html) ## Markdown cheatsheet Here are sintaxes for the most common elements: * [Headers](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#headers) * [Bold](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#bold) * [Italic](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#italic) * [Inline code](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#inline-code) * [Lists](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#lists) * [Horizontal rulers](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#hr) * [Links](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#links) * [Code snippets](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#code-snippets) * [Includes](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#includes) * [Include code snippets](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#include-code-snippets) * [Images](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#images) * [Blockquotes, notes and warnings](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#blockquotes-notes-and-warnings) * [Tables](https://docs.lacunasoftware.com/en-us/articles/welcome/contributing#tables) ### Headers Top level (H1) header: ```md # Article title ``` Level 2 (H2) header: ```md ## Section title ``` Level 3 (H3) header: ```md ### Subsection title ``` ### Bold ```md This is a **bold** statement ``` This is a **bold** statement ### Italic ```md This is a *foreign word*. ``` This is a *foreign word*. ### Inline code ```md Pass the `callback` parameter ``` Pass the `callback` parameter ### Lists Unordered: ```md * Item A * Item B * Subitem (prefix spaces to align with parent) * And so on * Item C ``` * Item A * Item B * Subitem (prefix spaces to align with parent) * And so on * Item C Ordered: ```md 1. Item 1 1. Item 2 1. Subitem (prefix spaces to align with parent) 1. And so on 1. Item 3 ``` 1. Item 1 1. Item 2 1. Subitem (prefix spaces to align with parent) 1. And so on 1. Item 3 > The actual numbering does not matter, DocFX will order the list when rendering the file. Prefer repeating `1.` on every item instead of writing `1.`, `2.`, `3.` etc because this allows for easy reodering of items. ### Horizontal rulers Use `***` to insert a horizontal ruler: ```md Something *** Some other thing ``` > **Note** > > **Do not** use the syntax `---`, as it has a special meaning on DocFX ### Links ```md [text](url) ``` To articles on same folder: ```md See the article [Welcome](index.md) ``` See the article [Welcome](https://docs.lacunasoftware.com/en-us/articles/welcome) To articles on other folders: ```md You can use the [Lacuna PKI SDK](../pki-sdk/index.md) for this purpose ``` You can use the [Lacuna PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk) for this purpose To classes: ```md See class @Lacuna.RestPki.Client.RestPkiClient ``` See class @Lacuna.RestPki.Client.RestPkiClient To methods: ```md See method @Lacuna.RestPki.Client.RestPkiClient.GetPkiBrazilTimestamper ``` See method @Lacuna.RestPki.Client.RestPkiClient.GetPkiBrazilTimestamper > To find out the exact UIDs of classes and methods, see .yml files on folder `api` after building the docfx project. In some cases, the syntax `@uid` does not work for cross referencing. In such cases, use: ```md ``` If the uid contains a `#`, encode it as `%23`: ```md ``` Links to article sections: First, you need to declare the anchor name right before the section header: ```md ## Section title \{#anchor-name} ``` > **Note** > > If the article is in English and the section title matches the anchor name (transformed to lowercase and replacing spaces with hyphens), you don't > need to declare the anchor Then, to link to the section: ```md See [Default error callback](../web-pki/advanced.md#default-error-callback) ``` See [Default error callback](https://docs.lacunasoftware.com/en-us/articles/web-pki/advanced#default-error-callback) ### Code snippets ```languageid code ``` Common language IDs: * csharp or cs * javascript or js * html Code snippets can be indented with lists: 1. Installation 1. Set things up 1. Run this: ```bash sudo apt install something ``` 1. Finish things up 1. Done See all supported [Language names and aliases](https://github.com/highlightjs/highlight.js#supported-languages). ### Includes ```md {/* include: url */} ``` Include blocks common to both languages are kept on the [includes/](https://github.com/LacunaSoftware/docs/tree/master/includes) folder. For instance, to include the [rest-pki-samples-matrix.md](https://github.com/LacunaSoftware/docs/blob/master/includes/rest-pki-samples-matrix.md) block from a location such as `docs.en-us/articles/project-name/article.md`: ```md {/* include: ../../../includes/rest-pki-samples-matrix.md */} ``` Example: [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/rest-pki) ### Include code snippets * [Syntax](https://dotnet.github.io/docfx/spec/docfx_flavored_markdown.html#code-snippet) * Example: @Lacuna.Pki.Cades.CadesSignatureCompression \[[src](https://github.com/LacunaSoftware/docs/blob/master/docs.en-us/apidoc/Lacuna.Pki.Cades.CadesSignatureCompression.md)\] ### Images ```md ![Alt Text](url) ``` `url` can be a remote URL, but is usually a relative reference to an image on the [images/](https://github.com/LacunaSoftware/docs/tree/master/images) folder. For instance, to reference the image [images/pki-sdk/pades-rectangle.png](https://github.com/LacunaSoftware/docs/blob/master/images/pki-sdk/pades-rectangle.png) from the following locations: From `docs.en-us/articles/project-name/article.md`: ```md ![Image name](/images/pki-sdk/pades-rectangle.png) ``` From `docs.en-us/articles/project-name/subfolder/article.md`: ```md ![Image name](/images/pki-sdk/pades-rectangle.png) ``` Samples: * [PKI SDK / Get started / Adding the nuget package](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/get-started/nuget) * [Web PKI / Browser support](https://docs.lacunasoftware.com/en-us/articles/web-pki/browser-support) ### Blockquotes, notes and warnings Blockquotes: ```md As Jeffrey Lebowski once said: > Far out. ``` As Jeffrey Lebowski once said: > Far out. Notes: ```md :::note This is an important notice ::: ``` > **Note** > > This is an important notice Warnings: ```md :::warning Watch out! ::: ``` > **Warning** > > Watch out! Also supported: > **Tip** > > This is a tip > **Info** > > This is important > **Caution** > > Proceed with caution ### Tables ```md First Header | Second Header --------------------------- | ------------- Content from cell 1 | Content from cell 2 Content in the first column | Content in the second column ``` First Header | Second Header --------------------------- | ------------- Content from cell 1 | Content from cell 2 Content in the first column | Content in the second column It's not really needed to align columns, this renders the exact same output: ```md First Header | Second Header ------------ | ------------- Content from cell 1 | Content from cell 2 Content in the first column | Content in the second column ``` First Header | Second Header ------------ | ------------- Content from cell 1 | Content from cell 2 Content in the first column | Content in the second column For more complex cases, for instance having the leftmost upper cell blank, use this slightly more complex syntax: ```md | | Second Header | | --- | ------------- | | Content from cell 1 | Content from cell 2 | | Content in the first column | Content in the second column | ``` | | Second Header | | --- | ------------- | | Content from cell 1 | Content from cell 2 | | Content in the first column | Content in the second column | > GitHub markdown specification (which DocFX extends) mandates at least three hyphens (`---`) in each column of the header row (like shown above on the first column). The header row is always rendered in bold. If you also need the first column in bold, do this: ```md | | Ease of use | Awesomeness | | ------------ | ------------- | ------------ | | **Web PKI** | Very easy | So good | | **Rest PKI** | Super easy | Much awesome | | **PKI SDK** | Easy peasy | Wow | ``` | | Ease of use | Awesomeness | | ------------ | ------------- | ------------ | | **Web PKI** | Very easy | So good | | **Rest PKI** | Super easy | Much awesome | | **PKI SDK** | Easy peasy | Wow | Text in cells is normally left-aligned. For other alignments: ```md | Left-aligned | Center-aligned | Right-aligned | | :--- | :---: | ---: | | git status | git status | git status | | git diff | git diff | git diff | ``` | Left-aligned | Center-aligned | Right-aligned | | :--- | :---: | ---: | | git status | git status | git status | | git diff | git diff | git diff | See also: * [Organizing information with tables - GitHub Help](https://help.github.com/articles/organizing-information-with-tables/) * Examples * Table with leftmost upper cell blank: [Web PKI / Introduction](https://docs.lacunasoftware.com/en-us/articles/web-pki) * Table with centered text: [Web PKI / Browser support](https://docs.lacunasoftware.com/en-us/articles/web-pki/browser-support) # [Privacy Policy](https://docs.lacunasoftware.com/en-us/articles/welcome/privacy-policy) * Last amended: June 16, 2020 * Effective Date: June 16, 2020 Lacuna Software Ltda (collectively, "Lacuna", "we", "us", or "our") respects your privacy. The services we offer are tools for organizations and developers to make use of digital certification and related technologies with security. This Privacy Policy describes the types of Personal Data we collect through our products and services (“Services”) and via our online presence, which include our main website at [Lacuna Software](https://lacunasoftware.com/), as well as services and websites that we enable Internet users to access, such as [Dropsigner](https://www.dropsigner.com/) (coletivamente, nossos “Sites”). This policy also describes how we use Personal Data, with whom we share it, your rights and choices, and how you can contact us about our privacy practices. This policy does not apply to third-party websites, products, or services, even if they link to our Services or Sites, and you should consider the privacy practices of those third-parties carefully. In order to facilitate referencing, our Privacy Policy is segmented by product and service, observing the specifics of each one. You can find all articles in the list below: * [Privacy Policy - Rest PKI](https://docs.lacunasoftware.com/en-us/articles/rest-pki/privacy-policy) * [Privacy Policy - Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki/privacy-policy) ## Privacy Questions / Feedback If you have questions or concerns about Lacuna's Privacy Policy please contact us at [suporte@lacunasoftware.com](mailto:suporte@lacunasoftware.com) or EQN 102/103, Ed. Avenida 102, 2º Andar - Asa Norte, Brasília - DF, Brazil. Phone: +55 61 3030-5700. # [Web PKI quick reference](https://docs.lacunasoftware.com/en-us/articles/web-pki/quick-reference) The essentials of Web PKI on one page, with links to the full articles. ## What it is for Web PKI lets web applications use the certificates on the user's computer through JavaScript: list them, read their properties and binary encoding, and sign data or a pre-computed digest with them. Its main job is the client-side part of a signature: a server-side SDK prepares the bytes to sign and assembles the signed file, because `signData` and `signHash` return only the raw output of the signature algorithm. If you already have a crypto SDK or write the backend yourself, Web PKI alone covers the frontend part. | Choose instead | When it fits better | | --- | --- | | [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/rest-pki/quick-reference) (legacy) | Your backend already uses Rest PKI at pki.rest: the PKI guide recommends Rest PKI with Web PKI for web remote signatures from any language. | | [Rest PKI Core](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/quick-reference) | You prefer not to write signature code: your application creates a signature session and Rest PKI Core hosts the signing page, where users sign through Web PKI or with cloud certificates. | | [PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/quick-reference) | Your backend is .NET: PKI SDK does the server side of web remote signatures, with Web PKI in the browser. | | [PKI Express](https://docs.lacunasoftware.com/en-us/articles/pki-express/quick-reference) | Your backend runs on Windows or Linux in virtually any language: PKI Express signs on the server, and its samples use Web PKI in the browser. | | [Signer](https://docs.lacunasoftware.com/en-us/articles/signer/quick-reference) | You need a complete document and signature manager rather than a component; its embedded signature widget needs a Web PKI license for your page's domain. | ## Install | Language | Package | Current major | Registry | | --- | --- | --- | --- | | JavaScript / TypeScript (npm) | `web-pki` | 2 (latest 2.18.0) | https://www.npmjs.com/package/web-pki | | Script tag (CDN) | `lacuna-web-pki-2.18.0.min.js` | 2 | https://cdn.lacunasoftware.com/libs/web-pki/lacuna-web-pki-2.18.0.min.js | ```html ``` ```bash npm install web-pki --save ``` With npm, import the class as the Angular sample does: ```javascript import LacunaWebPKI from 'web-pki'; ``` Web PKI also needs its components on the user's computer: when they are missing or outdated, or the browser is not supported, `init()` sends the user to the installation page, which returns to your page when done. The components update themselves; update the JavaScript library in your application regularly, as updates are backward compatible. See [Browser support](https://docs.lacunasoftware.com/en-us/articles/web-pki/browser-support) and, for Windows networks, [distribution through GPO](https://docs.lacunasoftware.com/en-us/articles/web-pki/installation-webpki-gpo). ## Configuration and authentication Web PKI runs in the user's browser: there is no API key. Outside localhost, your page needs a **license** bound to its domains, passed to the `LacunaWebPKI` constructor in binary or JSON format. ```javascript var webPkiLicense = 'ASYAanNma...Q=='; var pki = new LacunaWebPKI(webPkiLicense); ``` - No license is needed on localhost (any port), nor with Rest PKI on cloud, even in production. - The JSON license lists `allowedDomains` and `homologDomains` (staging); the latter include the private IP ranges 10.x, 127.x, 172.16–172.31 and 192.168.x. Use the whole license: the `signature` field alone is not a license. See [Licensing](https://docs.lacunasoftware.com/en-us/articles/web-pki/licensing). - To get a license, [contact Lacuna](https://www.lacunasoftware.com/en/home/purchase); PKI SDK licenses usually come with a Web PKI license. The `init()` arguments a client sets: | Argument | Purpose | Article | | --- | --- | --- | | `ready` | Callback run when the component is ready | [Get started](https://docs.lacunasoftware.com/en-us/articles/web-pki/get-started) | | `license` | The license, when not passed to the constructor | [Licensing](https://docs.lacunasoftware.com/en-us/articles/web-pki/licensing) | | `defaultFail` | Fail callback for every call without its own | [Default fail callback](https://docs.lacunasoftware.com/en-us/articles/web-pki/default-error-callback) | | `notInstalled` | Replaces the redirect to the installation page | [Not installed](https://docs.lacunasoftware.com/en-us/articles/web-pki/customizing-not-installed) | | `restPkiUrl` | Your Rest PKI instance, when it is not the standard https://pki.rest | [Custom Rest PKI URL](https://docs.lacunasoftware.com/en-us/articles/web-pki/customizing-restpki-url) | | `requiredApiVersion` | API feature set the page needs (default API 1.3), avoiding needless updates | [API versions](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions) | | `brand` | Customized installation page | [Customized installation page](https://docs.lacunasoftware.com/en-us/articles/web-pki/brand) | | `angularScope`, `ngZone` | Runs callbacks inside AngularJS or Angular cycles | [Callbacks and Angular](https://docs.lacunasoftware.com/en-us/articles/web-pki/angularjs) | With Rest PKI, Web PKI talks to the Rest PKI instance directly, by default through `https://restpki.lacunasoftware.com/`, an alternative URL of the cloud service at https://pki.rest that firewalls are less likely to block. ## Core operations All methods are asynchronous: they return a `Promise` on which you register `success()` and `fail()` callbacks ([Asynchronous calls](https://docs.lacunasoftware.com/en-us/articles/web-pki/async)). The [API reference](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference) has every method, including those not shown here, such as `sendAuthenticatedRequest()` for [authenticated requests](https://docs.lacunasoftware.com/en-us/articles/web-pki/auth-request) with the user's certificate over mutual SSL/TLS. ### Initialize the component Create a `LacunaWebPKI` and call `init()` before any other method; your `ready` callback runs once the component is ready. See [Get started](https://docs.lacunasoftware.com/en-us/articles/web-pki/get-started). ```javascript var pki = new LacunaWebPKI(); pki.init({ ready: onWebPkiReady, defaultFail: onWebPkiFail }); ``` ### List the user's certificates `listCertificates()` returns the certificates sorted by `subjectName`, each with properties such as `thumbprint`, `subjectName`, `issuerName` and `validityEnd`; with `selectId` it fills a select element. See [Customizing certificate selection](https://docs.lacunasoftware.com/en-us/articles/web-pki/cert-select) and [Certificate properties](https://docs.lacunasoftware.com/en-us/articles/web-pki/cert-properties). Show all certificates and [pre-validate the selected one](https://docs.lacunasoftware.com/en-us/articles/web-pki/cert-validation) rather than using [filters](https://docs.lacunasoftware.com/en-us/articles/web-pki/filters), which the docs advise against. ```javascript pki.listCertificates({ selectId: 'certificateSelect', selectOptionFormatter: getCertText }); function getCertText(cert) { return cert.subjectName + ' (issued by ' + cert.issuerName + ')'; } ``` ### Read a certificate `readCertificate()` returns the certificate's encoding in Base64, which you send to your backend when it starts a remote signature. See [Get started](https://docs.lacunasoftware.com/en-us/articles/web-pki/get-started). Pass `{ thumbprint }`: the library also accepts the thumbprint string, as the Java sample does, but the TypeScript typings (`lacuna-web-pki.d.ts`) accept only the object. ```javascript pki.readCertificate({ thumbprint: selectedCertThumbprint }).success(function (certEncoding) { // certEncoding contains the certificate's encoding (in Base64) }); ``` ### Sign data `signData()` signs Base64-encoded bytes with the selected certificate's private key and returns the signature in Base64. See [signData and signHash](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/sign-data-vs-hash). ```javascript pki.signData({ thumbprint: '...', // as returned by the listCertificates method data: '...', // bytes encoded in Base64 (typically given by server) digestAlgorithm: '...' // for instance 'SHA-256' (typically given by server) }).success(function (signature) { // signature contains the result of the signature operation (encoded in Base64) }); ``` ### Sign a hash from your backend `signHash()` signs the digest that your server-side SDK returns when it starts a remote signature (PKI Express, PKI SDK, Rest PKI Core); your backend then completes the signature with the result. See [Web remote signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures/remote). ```javascript pki.signHash({ thumbprint: formElements.certThumbField.val(), hash: formElements.toSignHashField.val(), digestAlgorithm: formElements.digestAlgorithmField.val() }).success(function (signature) { // Fill the "signature" field, needed on server-side to complete the signature. formElements.signatureField.val(signature); formElements.form.submit(); }); ``` ### Sign with Rest PKI `signWithRestPki()` takes the token your backend got from Rest PKI and the certificate thumbprint; Web PKI exchanges the signature data with Rest PKI directly, and your backend then finishes the signature. See [Rest PKI](https://docs.lacunasoftware.com/en-us/articles/rest-pki/quick-reference). ```javascript pki.signWithRestPki({ token: formElements.token, thumbprint: selectedCertThumbprint }).success(function () { // Once the operation is completed, we submit the form. formElements.form.submit(); }); ``` ### Sign a local PDF `signPdf()` signs a PDF on the user's computer, with nothing sent to a server; pick the file with `showFileBrowser()`. Local signatures need the local signature extension ([contact Lacuna](https://www.lacunasoftware.com/en/home/purchase)) and run only on Windows. See [Web local signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures/local). ```javascript pki.signPdf({ fileId: file.id, output: { mode: 'autoSave', fileNameSuffix: '-signed' }, certificateThumbprint: $('#certificateSelect').val(), policy: 'basic', trustArbitrators: [pki.standardTrustArbitrators.pkiBrazil] }).success(function (result) { // result.isValid, result.signatureInfo }); ``` ## Errors A failed call runs its `fail()` callback, or the `defaultFail` set in `init()`; with neither, an exception is thrown. The callback receives an `ExceptionModel` with `userMessage` (for the user), `code`, `error`, `origin` and `message`. See [Default fail callback](https://docs.lacunasoftware.com/en-us/articles/web-pki/default-error-callback). - **Component missing or outdated, or browser not supported**: not an error code. `init()` redirects to the installation page, or calls your `notInstalled(status, message)` with `NOT_INSTALLED`, `OUTDATED` or `BROWSER_NOT_SUPPORTED`. See [Not installed](https://docs.lacunasoftware.com/en-us/articles/web-pki/customizing-not-installed). - **Error codes**: `code` tells which error occurred, and [Default fail callback](https://docs.lacunasoftware.com/en-us/articles/web-pki/default-error-callback#error-codes) describes each one. On `license_not_set`, `license_invalid`, `license_expired`, `license_domain_not_allowed` and `license_restricted`, check the license against [Licensing](https://docs.lacunasoftware.com/en-us/articles/web-pki/licensing); other common codes are `user_cancelled` (the user cancelled the operation) and `certificate_not_found` (the certificate is not in the user's store or crypto device). - **"Could not get pending signature"** with `signWithRestPki()`: Web PKI cannot talk to the Rest PKI instance, which is common with on-premises instances; first check that the user's computer can access it. See [the troubleshooting article](https://docs.lacunasoftware.com/en-us/articles/rest-pki/troubleshoot/could-not-get-pending-sig). TODO(docs): 13 error codes have no description, in the docs or in the library's typings: `algorithm_not_supported`, `signed_pdf_to_mark`, `json_error`, `io_error`, `keychain_error`, `keychain_sign_error`, `decode_error`, `csp_invalid_algorithm`, `csp_invalid_provider_type`, `mobile_not_authorized`, `command_decrypt_error`, `blocked_domain` and `invalid_operation`. ## Test certificates and credentials - Use the Lacuna Test PKI certificates from [Test certificates](https://docs.lacunasoftware.com/en-us/articles/pki-guide/test-certs#web-pki); never trust that PKI in production. - To try Web PKI on Windows, you need a certificate in the Windows certificate store: `certmgr.msc` should show one under **Personal** with its private key. To use a test certificate, import its PKCS #12 file (password `1234`) into that store. - No license is needed on localhost, and staging hosts on private IPs are covered by the license's `homologDomains`. - With Rest PKI, trust the test PKI through the security context ID given on the Test certificates page; for local signatures, add the test root, Lacuna Root Test v3, as a `trustedRoot` trust arbitrator (development only). The .NET sample does this with an older root, Lacuna Root Test v1, which expired in January 2025 and does not accept the current test certificates. TODO(docs): how to install the test PKCS #12 files so that Web PKI lists them on Linux and macOS. ## Try it Run the Web PKI demos, or the samples in your language: **Demos and samples** - Live demo: [Your certificates in the browser](https://try.lacunasoftware.com/en/web-pki/certificates-in-the-browser) - Live demo: [Sign a file with your certificate](https://try.lacunasoftware.com/en/pki-suite/sign-a-file) - Sign a local PDF in the browser with Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/PadesSignatureWebController.cs) - Sign a local file with CAdES in the browser using Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/CadesSignatureWebController.cs) - List the user's certificates with Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ListCertJQueryController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ListCertJQueryController.java) · [Node.js](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/list-cert-jquery.js) · [Python](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/list_cert_jquery.py) · [Ruby](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/list_cert_jquery_controller.rb) - Read a certificate's details with Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ReadCertJQueryController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ReadCertJQueryController.java) · [Node.js](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/read-cert-jquery.js) · [Python](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/read_cert_jquery.py) · [Ruby](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/read_cert_jquery_controller.rb) - Sign data with RSA in the browser using Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/RSAWebController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/RSAWebController.java) · [Node.js](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/rsa-web.js) · [Python](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/rsa_web.py) · [Ruby](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/rsa_web_controller.rb) # [Lacuna Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki) The Lacuna Web PKI component enables web applications to interact with digital certificates through javascript. > **Tip** > > Web PKI is part of our line of public key infrastructure (PKI) solutions. We encourage you to check out the > [PKI Solutions Guide](https://docs.lacunasoftware.com/en-us/articles/pki-guide) to make sure this is the right product for your case. The main features are: * Displaying available certificates (either software- or hardware-based) * Obtaining public properties of certificates (name, email address, etc.) * Reading a certificate's binary encoding * Signing data (or a pre-computed digest) with a certificate The Web PKI component's main goal is to perform the client-side processing necessary for operations with digital certificates. An example would be performing digital signatures in a [web remote signature](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures/remote) using a server-side SDK (*Software Development Kit*): | | Client-side (Lacuna Web PKI) | Server-side (SDK on server) | | - | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | Retrieve the certificate's binary encoding and submit to the server | Prepare the signature, preparing the actual bytes that will serve as input to the signature algorithm ("to-sign-bytes" or "signed attributes") | | 2 | Sign the "to-sign-bytes" using a signature algorithm and send the output to the server | Assemble the signature package -- either a signed PDF, a CMS envelope (PKCS#7) or a XmlDSig node, depending on the kind of signature being done | > **Note** > > If you don't have a server-side SDK to perform the server-side processing, you can use the [Lacuna PKI SDK](https://docs.lacunasoftware.com/en-us/articles/pki-sdk). > [Contact us](https://www.lacunasoftware.com/en/home/purchase) for licensing information. See the article [Get started](https://docs.lacunasoftware.com/en-us/articles/web-pki/get-started) to start using Web PKI. # [Web PKI - Frequently Asked Questions](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq) Here you'll find answers to the most common questions on how to use the [Web PKI](https://docs.lacunasoftware.com/en-us/articles/web-pki) component. > **Tip** > > This FAQ is targeted for **software developers**. If you are an end-user having trouble using > one of our products, please go to our [Support Center](http://lacuna.help/) instead. Questions: * [What is the difference between the functions signData and signHash?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/sign-data-vs-hash) * [What is the signature format outputted by the functions signData and signHash?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/sign-data-output) * [How can I perform a digital signature with Web PKI?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/digital-signature) * [Does Web PKI support establishing SSL connections with the user's certificate?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/ssl) # [How can I perform a digital signature with Web PKI?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/digital-signature) See article [Web signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures). **Demos and samples** - Live demo: [Sign a file with your certificate](https://try.lacunasoftware.com/en/pki-suite/sign-a-file) - Sign a local PDF in the browser with Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/PadesSignatureWebController.cs) - Sign a local file with CAdES in the browser using Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/CadesSignatureWebController.cs) # [What is the signature format outputted by the functions signData and signHash?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/sign-data-output) The functions `signData` and `signHash` perform a *digital signature* ***algorithm*** using the private key of one of the user's certificates. Therefore, their output is the raw output of the algorithm, encoded in Base64. In the most common case of an RSA algorithm using a 2048-bit key, the output is 256 bytes long (344 characters in Base64). This question normally arises from the confusion between a *digital signature*, such as CMS/CAdES, XmlDSig/XAdES and PAdES, and a *digital signature* ***algorithm***, such as RSA. Usually, digital signature algorithms are a small part of the implementation of digital signatures. The `signData` and `signHash` perform only the algorithm, not the entire digital signature. Please see the FAQ [How can I perform a digital signature with Web PKI?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/digital-signature) for information on how to use Web PKI to perform digital signatures. # [What is the difference between the functions signData and signHash?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/sign-data-vs-hash) Both functions -- `signData` and `signHash` -- run a digital signature algorithm with the private key of one of the certificates on the user's computer. To understand the difference between the two functions, we need to talk briefly about the details of a signature algorithm. > **Note** > > The term *digital signature* ***algorithm*** should not be confused with *digital signature*. Read more about > this subject in the article [Digital signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/signatures). The RSA algorithm, broadly speaking, has 4 steps: 1. Computing the hash of the bytes to be signed 1. Encoding the [DigestInfo](https://tools.ietf.org/html/rfc2313#section-10.1.2) structure, which contains the hash and the OID of the hash algorithm used to produce it 1. *Padding* the encoded DigestInfo 1. A mathematical operation on the encoded and *padded* DigestInfo > **Note** > > The hash computed in the first step is usually **not the hash of the document being signed**. In the CMS/CAdES, PAdES and XmlDSig/XAdES signature schemes, > the bytes used as input to the signature algorithm are the encoding of the "signed attributes", a > structure that contains various data, among them the document hash. The `signData` function takes the *to-sign-data* as input and performs all the steps on it, while the `signHash` function takes the *to-sign-hash*, that is, the precomputed hash of the *to-sign-data*, and performs on it only the second step onwards. Both functions can be used to implement [web remote signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures/remote) regardless of the signature scheme (CAdES, PAdES, etc.) being used. Which function to use depends on the *output* of the backend code at the end of the remote signature "preparation". If it produces a *to-sign-data*, use the `signData` function. If it produces a *to-sign-hash*, use the `signHash` function. **Demos and samples** - Sign data with RSA in the browser using Web PKI: [.NET](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/RSAWebController.cs) · [Java](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/RSAWebController.java) · [Node.js](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/rsa-web.js) · [Python](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/rsa_web.py) · [Ruby](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/rsa_web_controller.rb) # [Does Web PKI support establishing SSL connections with the user's certificate?](https://docs.lacunasoftware.com/en-us/articles/web-pki/faq/ssl) Yes. Since [API 1.4](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions#v1-4), the `sendAuthenticatedRequest()` method sends web requests authenticated with the user's certificate through mutual SSL/TLS, from the user's computer. See [Authenticated request](https://docs.lacunasoftware.com/en-us/articles/web-pki/auth-request). To transmit an NFe, however, you usually do not need the user's certificate, as explained below. ## (or How do I to transmit a NFe to Receita/SEFAZ/prefeitura?) Currently, it is common to use the same certificate to issue an electronic invoice and transmit it to the competent agency (transmission is via SSL with mutual authentication). The predominance of this architecture comes from the fact that the first electronic invoice signature products were mostly desktop applications. In a web system, you have to deal with the problem that the client certificate is not available on the backend. To solve the problem of signing NFe in the browser, the Web PKI component fits perfectly (see the [online example](https://www.lacunasoftware.com/en/DemoRestPKI/nfeSignature)). In the case of transmission, it is not necessary to use the same certificate used to issue the electronic invoice. The national standard allows a certificate issued to a company other than the company that issued the electronic invoice to be used for transmission. This enables **the transmission to be done on the backend using an A1 certificate issued on behalf of the company offering the electronic invoice web signing service (your company), rather than using the NFe issuing company certificate (your client)**. This avoids the problem of transmitting the electronic invoice with a certificate available only on the frontend. # [Web PKI API](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference) ## API Reference See the [API Reference](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html) for detailed documentation about each method. ## See also [Api Versions](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions) # [API Versions](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions) The Web PKI provides an API version requirement parameter, in case the developer intends to use a specific feature set and avoid any unnecessary update on the user Web PKI components. In order to do so, use the `requiredApiVersion` parameter on [`init()`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#init) method, e.g.: ```js pki.init({ ready: onWebPkiReady, requiredApiVersion: pki.apiVersions.v1_2 }); ``` In the example above, we defined that we are going to use the feature set of [API 1.2](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions#v1-2) (and lower), thus any Web PKI component update will only be required for users with lower versions than the ones defined by [API 1.2](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions#v1-2). No unnecessary update will be required for users with satisfying versions, even though it is not the latest one. If the parameter is not set, the default requested version is [API 1.3](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions#v1-3). ## API changelog ### 1.8.2 (2023-11-23) Since lib [2.16.3](https://docs.lacunasoftware.com/en-us/articles/web-pki/update) - Improve method [`importCertificate`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#importcertificate) supporting multiple calls ### 1.8.1 (2022-12-17) - Add methods [encrypt](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#encrypt) and [decrypt](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#decrypt) - Add Extended Key Usage info to [CertificateModel](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.certificatemodel.html) - Add parameter `nonExportableKey` on method [generateSoftwareRsaKeyPair](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#generatesoftwarersakeypair) ### 1.7.2 (2022-07-03) - Add support to unrestricted size native responses - Add [CertificateModel](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.certificatemodel.html) international PKI fields: [`PkiArgentinaModel`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.pkiargentinamodel.html), [`PkiEcuadorModel`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.pkiecuadormodel.html), [`PkiParaguayModel`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.pkiparaguaymodel.html), [`PkiPeruModel`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.pkiperumodel.html) - Add [CertificateModel](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.certificatemodel.html) fields: `certificatePolicies`, `subjectDN`, `issuerDN` ### 1.6.1 (2020-05-23) - Add [`downloadToFolder`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#downloadtofolder)* command with TLS 1.2 forced support ### 1.6 (2019-10-13) - Add methods [`keySignData`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#keysigndata) and [`keySignHash`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#keysignhash) for signing with a generated private key Id. - Add `privateKeyId` parameter to the generate key pair response: [`GenerateKeyPairResponse`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.generatekeypairresponse.html) - Fix bug on [`sendAuthenticatedRequest`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#sendauthenticatedrequest) response payload when it comes without content length header property. ### 1.5.2 (2019-07-19) - Add option for returning the signed document content on local signature commands without the 1MB size limit: [`returnContent`](https://docs.lacunasoftware.com/content/typedocs/web-pki/enums/_lacuna_web_pki_d_.lacunawebpki.outputmodes.html#returncontent) - Add certificate validation levels on local signature commands: [`CertificateValidationLevels`](https://docs.lacunasoftware.com/content/typedocs/web-pki/enums/_lacuna_web_pki_d_.lacunawebpki.certificatevalidationlevels.html) - Add vertical and horizontal direction control on PAdES (PDF) visual representation: [`PadesVisualAutoPositioning`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.padesvisualautopositioning.html) - Add native app life cycle control on `init` method: [`useDomainNativePool`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#init) ### 1.5 (2018-11-27) - Add more efficient batch signature command: [`signHashBatch`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signhashbatch) - Add license v3 - Add mobile integration ### 1.4.1 (2018-06-15) - Fix [`sendAuthenticatedRequest`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#sendauthenticatedrequest)* empty buffer bug ### 1.4 (2018-02-23) - Add XML local signature features: - [`signFullXml`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signfullxml)* - [`signXmlElement`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signxmlelement)* - [`openXmlSignature`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#openxmlsignature)* - Add authenticated request feature: - [`sendAuthenticatedRequest`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#sendauthenticatedrequest)* - Add user error message field on exception object: - [`userMessage`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.exceptionmodel.html#usermessage) ### 1.3 (2017-11-10) - Add improved error handler with exception model - [`fail`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.promise.html#fail) ### 1.2 (2017-06-19) - Add local store and PKCS#11 certificate generation features: - [`generateSoftwareRsaKeyPair`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#generatesoftwarersakeypair) - [`importCertificate`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#importcertificate) - [`listTokens`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#listtokens) - [`generateTokenRsaKeyPair`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#generatetokenrsakeypair) - [`importTokenCertificate`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#importtokencertificate) ### 1.1 (2016-08-19) - Add license v2 - Add local signature features: - [`showFileBrowser`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#showfilebrowser)* - [`openFile`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#openfile)* - Add PAdES local signature features: - [`signPdf`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signpdf)* - [`openPades`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#openpades)* - Add CAdES local signature features: - [`signCades`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signcades)* - [`openCades`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#opencades)* ### 1.0 (2015-04-28) - Add basic features: - [`init`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#init) - [`listCertificates`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#listcertificates) - [`readCertificate`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#readcertificate) - [`signHash`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signhash) - [`signData`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signdata) - [`redirectToInstallPage`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#redirecttoinstallpage) - Add sign batch feature: - [`preauthorizeSignatures`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#preauthorizesignatures) - Add download and directory selection features: - [`showFolderBrowser`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#showfolderbrowser) - [`downloadToFolder`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#downloadtofolder) - [`openFolder`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#openfolder) - Add RestPKI sign integration: - [`signWithRestPki`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#signwithrestpki) * Methods supported only on Windows. For more information see [Web signatures](https://docs.lacunasoftware.com/en-us/articles/pki-guide/web-signatures) article. # [privacy-policy](https://docs.lacunasoftware.com/en-us/articles/web-pki/privacy-policy) > **Note** > > We have reviewed our policies in order to make sure we are in compliance with the European Union's General Data Protection Regulation # Privacy Policy - Web PKI * Last amended: June 16, 2020 * Effective Date: June 16, 2020 This Privacy Policy applies to the Plugin [Web PKI](https://get.webpkiPlugin.com/Help?brand=&jslib=&returnUrl=#) (the "Plugin", the "Extension") owned and operated by Lacuna Software Ltda (collectively, "Lacuna", "we", "us", or "our"). This Privacy Policy describes how Lacuna collects, uses, shares and secures the personal information you provide, as well as the information about our customers' end users that we process on behalf of our customers. It also describes your choices regarding use, access, correction and deletion of your personal information. ## How we Collect Information We collect the following personal information from you: ### Information that you provide to us about yourself When you sign up for the Services, we ask you for information such as * Contact Information, such as name, email address, mailing address, or phone number; * Unique Identifiers, such as username, account number or password; * IP address. If you do not provide this information, we will not be able to provide the Services to you. ### Information you provide to us about your end users and contacts For the provision of our Services to you, you provide us with information which may identify your end users or employees. Such information includes: * Digital certificate; * IP addresses; * Document Hash. You may also provide us personal information about your employees such as Name and email address where we can send receipts of your purchases. When you provide us with personal information about your employees will only use this information for the specific reason for which it is provided. If you believe that one of your employees has provided us with your personal information and you would like to request that it be removed from our database, please contact us at the contact information below. ### Information collected automatically When you use our Services, we use cookies and similar technologies to collect information about your location, and your activities on our Plugin, information about your device and log information. This is described in more detail below. These cookies and similar technologies collect anonymized Internet protocol (IP) addresses, browser type, Internet service provider (ISP), referring/exit pages, operating system, date/time stamp, and/or clickstream data. Lacuna allows Google Analytics and Snowplow Analytics to use these technologies to analyze trends, administer the Plugin, track users' movements on the Plugin, and to gather demographic information about our user base as a whole for the purpose of analytics. You can control the use of cookies at the individual browser level, but if you choose to disable cookies, it may limit your use of certain features or functions on our Plugin or service. We do not use or allow the use of cookies or similar technologies in connection with your customers' data. *Google Analytics:* We use a tool called "Google Analytics" to collect some information we listed above about your use of the Services. We use the information we get from Google Analytics to improve the Services. In order to collect this information, Google Analytics may set cookies on your browser or mobile device, or read cookies that are already there. Google Analytics may also receive information about you from apps you have downloaded, that partner with Google. We do not combine the information collected through the use of Google Analytics with personally identifiable information. Google's ability to use and share information collected by Google Analytics about your visits to the Services to another application which partners with Google, is restricted by the Google Analytics Terms of Use and the Google Privacy Policy. Please review those and see [https://policies.google.com/technologies/partner-sites](https://policies.google.com/technologies/partner-sites) for information about how Google uses the information provided to Google Analytics and how you can control the information provided to Google. To prevent your data from being used by Google Analytics, you can download the Google Analytics opt-out browser add-on for Google Analytics which can be found here. ## Purpose and Legal basis of the Processing We use the information about you in order to provide the services to you and in order to improve them. We use information about your customers or end users only in order to provide you the services. To the extent EU data protection law applies to these uses of your information, we act as the "data controller". To the extent EU data protection law applies to our processing of your customer or end user data, you serve as the "data controller" and we serve as the "data processor". *To perform the Services:* We use your information to identify you, process your payment, provide you with technical support and assistance; and communicate with you about the Services via email. For example, we will contact you to notify you of any issues with the Services or any suspicious activity in your account. The legal basis for these uses in the performance of the contract with you. *To Optimize or improve the Services:* We use your information to authenticate you, prevent fraud and abuse of our Services and perform research. The legal basis for these uses is our legitimate interest in the improvement and optimization of our service offerings and in ensuring the security of our services and we apply appropriate safeguards to protect your information (see [section Security](https://docs.lacunasoftware.com/en-us/articles/web-pki/privacy-policy#security)). ## How we Share your Information We share information with service providers, as required by law, and in connection with the protection and enforcement of our legal and contractual rights. *With Service Providers:* We share your information with third parties who provide services on our behalf to help with our business activities. This includes: payment processing, providing customer service, sending marketing communications (this does not include information about your customers), conducting research and analysis and providing cloud computing infrastructure. The legal basis for sharing this information is our legitimate interest in providing our Services efficiently and we implement measure to safeguard your information. *With Public Authorities or Law Enforcement:* In certain situations, Lacuna may be required to disclose personal data in response to lawful requests by public authorities, including to meet national security or law enforcement requirements. We may also disclose your personal information as required by law, such as to comply with a subpoena or other legal process, when we believe in good faith that disclosure is necessary to protect our rights, when we believe there is a violation to our Terms of Service (see RestPKI Terms of Service, Beanstalk Terms of Service), protect your safety or the safety of others, investigate fraud, or respond to a government request. If Lacuna is involved in a merger, acquisition, or sale of all or a portion of its assets, you will be notified via email and/or a prominent notice on our website, of any change in ownership, uses of your personal information, and choices you may have regarding your personal information. We do not sell, rent or share personal information with third parties without your prior consent. The legal basis for this is our legitimate interest in protecting our legal rights and those of others, compliance with legal obligations and our legitimate interest in fulfilling legal obligations imposed by legal authorities outside of the EU. *Prevent fraud and abuse of the Services:* We will share information to prevent or detect fraud or to address technical issues and if we believe it is necessary to investigate, prevent, or take action regarding situations that involve abuse of the Services infrastructure. The legal basis for this is our legitimate interest in the maintaining the security of our Services. We also process and share information in an aggregated, de-identified manner, where the information is shared as part of a statistical report and does not contain personal information. ## Security The security of your personal information is important to us. We implement adequate measures to protect the personal information submitted to us, both during transmission and once it is received. Lacuna Software Ltda takes steps to ensure that all source code, files and data remain private and confidential. Due to the sensitive nature of source code we take this very seriously and make it our primary concern for all customers. We restrict access to personal information to Lacuna employees, contractors and agents who need to know that information in order to operate, develop or improve our service. These individuals are bound by confidentiality obligations and may be subject to discipline, including termination and criminal prosecution, if they fail to meet these obligations. If you have any questions about the security of your personal information, you can contact us at the contact information below. ## Rights with respect to your information Upon request Lacuna will provide you with information about whether we hold any of your personal information. You may access, correct, obtain a copy of or request deletion of your personal information by logging into your account or by contacting us at the contact information below. We will respond to your request within a reasonable timeframe. In certain circumstances we may be required by law to retain your personal information, or may need to retain your personal information in order to continue providing a service. Lacuna Software Ltda acknowledges that you have the right to access your personal information. Lacuna has no direct relationship with your end users whose personal data it processes. An individual who seeks access, or who seeks to correct, amend, or delete inaccurate data should direct their query to the Lacuna Software Ltda's Client (the data controller). If requested to remove data we will respond within a reasonable timeframe. In certain circumstances we may be required by law to retain your personal information, or may need to retain your personal information in order to continue providing a service. ## Your Choices with respect to the information Promotional Email communication: You may sign-up to receive email or newsletter or other communications from us. If you would like to discontinue receiving this information, you may update your email preferences by using the "Unsubscribe" link found in emails we send to you or by contacting us at the contact information below. Google Analytics: see [https://policies.google.com/technologies/partner-sites](https://policies.google.com/technologies/partner-sites) for information about how Google uses the information provided to Google Analytics and how you can control the information provided to Google. To prevent your data from being used by Google Analytics, you can download the Google Analytics opt-out browser add-on for Google Analytics which can be found [here](https://tools.google.com/dlpage/gaoptout/). ## Data Retention We may retain your information for as long as your account is active or as needed to provide you services, comply with our legal obligations, resolve disputes and enforce our agreements. In certain circumstances we may be required by law to retain your personal information, or may need to retain your personal information in order to continue providing a service. Even if you delete your account, keep in mind that the deletion by our third party providers may not be immediate and that the deleted information may persist in backup copies for a reasonable period of time. ## Policy Regarding Children The Services are not directed to children under the age of 16. We do not knowingly collect Personal Information from children under 16. If you are under 16, please do not use the Services and do not provide any personal information to us. If you become aware that a child under 16 has provided us with personal information without your consent, please contact us at [support@lacunasoftware.com](mailto:support@lacunasoftware.com). If you are a California resident under the age of 18 and you wish to remove publicly available content, please contact us at [support@lacunasoftware.com](mailto:support@lacunasoftware.com) with the subject line "California Eraser". ## Transfers of information not from the EEA To the extent that personal information is transferred to the United States from countries other than countries within the European Economic Area and Switzerland, including personal information that is transferred from Canada, we employ similar safeguards such as selecting third party vendors carefully, ensuring personal information will be used and disclosed only as set out in this privacy policy and that it is protected by appropriate security safeguards. However, in connection with these transfers of personal information, your personal information may be subject to privacy laws that may not provide the same protection as your country of residence. For example, government entities in such other countries may have certain rights to access your personal information. By using this Plugin or using our Service that this privacy notice relates to you are consenting to this transfer of your personal information. ## Browser Do Not Track The Services honor and enforce Do Not Track preferences. Do Not Track (DNT) is a privacy preference you can set in your web browser to indicate that you do not want certain information about your web activity collected across websites when you have not interacted with that service on the page. For all the details, including how to turn on Do Not Track, visit [donottrack.us](http://donottrack.us/). ## Changes to This Privacy Policy We may update this Privacy Policy to reflect changes to our information practices. If we make any material changes we will notify you by email (sent to the e-mail address specified in your account) or by means of a notice on this website prior to the change becoming effective. We encourage you to periodically review this page for the latest information on our privacy practices. ## Privacy Questions / Feedback If you have questions or concerns about Lacuna's Privacy Policy please contact us at [suporte@lacunasoftware.com](mailto:suporte@lacunasoftware.com) or EQN 102/103, Ed. Avenida 102, 2º Andar - Asa Norte, Brasília - DF, Brazil. Phone: +55 61 3030-5700. # [Callbacks and AngularJS](https://docs.lacunasoftware.com/en-us/articles/web-pki/angularjs) If your web application uses AngularJS, you should pass a reference to your controller's or service's `$scope` when calling the `init()` method: ```javascript pki.init({ ready: onWebPkiReady, angularScope: $scope, ... }); ``` If you fail to do so, your callbacks will be called outside AngularJS's "cycles", which might cause changes to the `$scope` not to be reflected on the view. # Angular2+ If your web application uses Angular2+, you should pass a reference to your component's or service's `NgZone` when calling the `init()` method: ```javascript pki.init({ ready: onWebPkiReady, ngZone: this.ngZone, ... }); ``` # [Asynchronous calls](https://docs.lacunasoftware.com/en-us/articles/web-pki/async) Let's have another look at our sample for listing the available certificates: ```javascript pki.listCertificates().success(function (certs) { // do something with the "certs" array }); ``` This is an example of an **asynchronous call**. The [`listCertificates()`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#listcertificates) method cannot immediately do all the processing that it needs to do and return the result. It needs some time to do its magic. We could block the execution until the result is available, but that is poor javascript design and can lead to very nasty things such your web page freezing up and the browser suggesting to the user that the page should be closed because of the freeze. Instead of that, the method immediately returns a [`Promise`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.promise.html). A promise is an object through which you can register callbacks that will be called once the promise is fulfilled -- that is, once the operation is completed. You should always register a callback for when the operation is completed successfully and, optionally, another for when an error occurs during the operation. The methods on the [`Promise`](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.promise.html) class are chainable, meaning you can do this: ```javascript pki.listCertificates().success(function (certs) { // do something with the "certs" array }).fail(function (ex) { alert('An error has occurred while retrieving the certificates: ' + ex.userMessage); }); ``` The success callback always receive a single argument representing the operation's result. However, its type (either string, array or object) and meaning depend on the method that returned the promise. You must check on each method's documentation for such information. For more information about each of the exception object parameters, please refer to the [Promise.fail()](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.promise.html#fail) method documentation and [ExceptionModel](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.exceptionmodel.html). > **Note** > > All methods of the [`LacunaWebPKI`](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html) class are asynchronous, with rare exceptions. # [Authenticated Request](https://docs.lacunasoftware.com/en-us/articles/web-pki/auth-request) Web PKI can send web requests authenticated with the user's digital certificate through mutual SSL/TLS. This is very useful when communicating with services from Receita Federal (the Brazilian federal revenue service), SEFAZ (the state revenue offices) or city governments. ## NFe - Electronic invoices Services involving electronic invoices (NFe) are another area that requires authenticated requests. When an NFe is transmitted, the national standard allows authentication with a certificate from a company other than the one that issued the NFe. This lets the transmission be done on the *backend*, for example with an A1 certificate issued to the company that offers the web NFe signing service. However, other services, such as queries and recipient manifestations (manifestação do destinatário), require authentication with the certificate of the company that issued the NFe. In those cases, authenticated requests with Web PKI let you implement the communication from the user's computer while following good security practices: they allow certificates stored on cryptographic devices (A3) to be used, and they avoid sending A1 certificates to be kept by third parties. ## Examples The example below shows a simple authenticated request that checks the operational *status* of the SEFAZ-RS service in the staging (homologação) environment. ```js // Request parameters var request = { // Service URL url: 'https://nfe-homologacao.svrs.rs.gov.br/ws/NfeStatusServico/NfeStatusServico4.asmx', method: 'post', headers: { 'Content-Type': 'application/soap+xml; charset=utf-8' }, // SOAP envelope of the request body: '253STATUS' }; // Sets the user's certificate used to authenticate the request request.certificateThumbprint = $('#certificateSelect').val(); // Sends the request pki.sendAuthenticatedRequest(request).success(function (response) { // Use the response }); ``` ## See also * Working example on JSFiddle: [Sending an authenticated request](https://jsfiddle.net/LacunaSoftware/3cv5xjov/) * [Documentation of the `sendAuthenticatedRequest()` method](https://docs.lacunasoftware.com/content/typedocs/web-pki/classes/_lacuna_web_pki_d_.lacunawebpki.html#sendauthenticatedrequest) (available since [API version 1.4](https://docs.lacunasoftware.com/en-us/articles/web-pki/api-reference/versions#v1-4)) # [Using a customized installation page](https://docs.lacunasoftware.com/en-us/articles/web-pki/brand) ```javascript pki.init({ ready: onWebPkiReady, brand: 'YourBrand' }); ``` # [Browser support](https://docs.lacunasoftware.com/en-us/articles/web-pki/browser-support) Currently, the following browsers are supported: | ![Chrome](https://docs.lacunasoftware.com/images/web-pki/chrome.gif) | ![Firefox](https://docs.lacunasoftware.com/images/web-pki/firefox.gif) | ![IE](https://docs.lacunasoftware.com/images/web-pki/ie.gif) | ![Edge](https://docs.lacunasoftware.com/images/web-pki/edge.gif) | ![Brave](https://docs.lacunasoftware.com/images/web-pki/brave.png)| |:---------------------------------------------:|:------------------------------------------------:|:-------------------------------------:|:-----------------------------------------:|:-----------------------------------------:| | Chrome Version 44+ | Firefox Version 50+ | IE9+ | Microsoft Edge Version 42+ | Brave Version 1.2+ | | Windows, Linux and Mac | Windows, Linux and Mac | Windows | Windows | Windows | Supported system versions: * Windows 7 SP2 or superior\* * Linux (Debian, RedHat and Slackware based distributions) * Mac OS X 10.12+ > **Note** > > \*Windows XP and Vista: **no official support, USE AT YOUR OWN RISK**, since the systems were discontinued by Microsoft. In order to run, the system must be in the latest possible version. # [Certificate properties](https://docs.lacunasoftware.com/en-us/articles/web-pki/cert-properties) When you call the function `listCertificates()`, your callback receives an array with the available certificates on the user's machine. Each item on that array is an object of type [CertificateModel](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.certificatemodel.html) having several properties with information about the certificate: ```javascript pki.listCertificates().success(function (certs) { for (var i = 0; i < certs.length; i++) { var cert = certs[i]; console.log(cert.subjectName); console.log(cert.email); console.log(cert.validityEnd); console.log(cert.pkiBrazil.cpf); console.log(cert.pkiItaly.codiceFiscale); } }); ``` The same object is received on the `selectOptionFormatter` callback which may be passed when calling `listCertificates()`: ```javascript pki.listCertificates({ selectId: 'certificateSelect', selectOptionFormatter: function (cert) { var text = cert.subjectName + ' (' + 'issued by ' + cert.issuerName + ' on ' + cert.validityEnd.toLocaleDateString() + ')'; if (new Date() > cert.validityEnd) { text = '[EXPIRED] ' + text; } return text; } }); ``` Some of the properties available are: * `subjectName`: The Common Name (CN) part of the certificate's subject name field * `email`: The subject's e-mail address * `validityEnd`: The *not after* field of the certificate (JavaScript type `Date`) * `pkiBrazil`: Object with Brazil-specific fields * `pkiBrazil.cpf`: Certificate holder's CPF (*CPF do titular/responsável*) * `pkiBrazil.cnpj`: Company's CNPJ * `pkiBrazil.responsavel`: Name of the certificate's holder (*nome do titular/responsável*) * `pkiItaly`: Object with Italy-specific fields * `pkiItaly.codiceFiscale`: The subject's *codice fiscale* > **Note** > > The properties `pkiBrazil` and `pkiItaly` are guaranteed to be not-null, even if the certificate is not a Brazilian or Italian certificate. > Therefore, statements such as `if (cert.pkiBrazil.cpf) { ... }` are safe from exceptions. The sub-properties themselves (`pkiBrazil.*` / > `pkiItaly.*`) are `null` if they do not apply. For a complete list of the properties available, see the API Reference for the type [CertificateModel](https://docs.lacunasoftware.com/content/typedocs/web-pki/interfaces/_lacuna_web_pki_d_.certificatemodel.html). # [Customizing certificate selection](https://docs.lacunasoftware.com/en-us/articles/web-pki/cert-select) You can customize the text that will be displayed for each certificate using any of the [Certificate properties](https://docs.lacunasoftware.com/en-us/articles/web-pki/cert-properties) returned by Web PKI for each certificate: ```js function onWebPkiReady() { pki.listCertificates({ selectId: 'certificateSelect', selectOptionFormatter: getCertText }); } function getCertText(cert) { return cert.subjectName + ' (issued by ' + cert.issuerName + ')'; } ``` The same applies if you are manually processing the certificates array instead of using `selectId` and `selectOptionFormatter`: ```js function onWebPkiReady() { pki.listCertificates().success(function (certs) { var select = $('#certificateSelect'); for (var i = 0; i < certs.length; i++) { var cert = certs[i]; select.append( $('