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 (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 | 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 | Your backend is .NET: PKI SDK does the server side of web remote signatures, with Web PKI in the browser. |
| PKI Express | 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 | 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 |
<script type="text/javascript" src="https://cdn.lacunasoftware.com/libs/web-pki/lacuna-web-pki-2.18.0.min.js"
integrity="sha256-utM/CTsggW5QWTZgkLcAwVGkMBhYKTz3n0992V4r2y4="
crossorigin="anonymous"></script>
npm install web-pki --save
With npm, import the class as the Angular sample does:
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 and, for Windows networks, distribution through 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.
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
allowedDomainsandhomologDomains(staging); the latter include the private IP ranges 10.x, 127.x, 172.16–172.31 and 192.168.x. Use the whole license: thesignaturefield alone is not a license. See Licensing. - To get a license, contact Lacuna; 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 |
license | The license, when not passed to the constructor | Licensing |
defaultFail | Fail callback for every call without its own | Default fail callback |
notInstalled | Replaces the redirect to the installation page | Not installed |
restPkiUrl | Your Rest PKI instance, when it is not the standard https://pki.rest | Custom Rest PKI URL |
requiredApiVersion | API feature set the page needs (default API 1.3), avoiding needless updates | API versions |
brand | Customized installation page | Customized installation page |
angularScope, ngZone | Runs callbacks inside AngularJS or Angular cycles | Callbacks and Angular |
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). The API reference has every method, including those not shown here, such as sendAuthenticatedRequest() for authenticated requests 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.
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 and Certificate properties.
Show all certificates and pre-validate the selected one rather than using filters, which the docs advise against.
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.
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.
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.
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.
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.
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) and run only on Windows. See Web local signatures.
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.
- Component missing or outdated, or browser not supported: not an error code.
init()redirects to the installation page, or calls yournotInstalled(status, message)withNOT_INSTALLED,OUTDATEDorBROWSER_NOT_SUPPORTED. See Not installed. - Error codes:
codetells which error occurred, and Default fail callback describes each one. Onlicense_not_set,license_invalid,license_expired,license_domain_not_allowedandlicense_restricted, check the license against Licensing; other common codes areuser_cancelled(the user cancelled the operation) andcertificate_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.
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; never trust that PKI in production.
- To try Web PKI on Windows, you need a certificate in the Windows certificate store:
certmgr.mscshould show one under Personal with its private key. To use a test certificate, import its PKCS #12 file (password1234) 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
trustedRoottrust 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: