Pular para o conteúdo principal

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 insteadWhen 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 CoreYou 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 SDKYour backend is .NET: PKI SDK does the server side of web remote signatures, with Web PKI in the browser.
PKI ExpressYour 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.
SignerYou 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​

LanguagePackageCurrent majorRegistry
JavaScript / TypeScript (npm)web-pki2 (latest 2.18.0)https://www.npmjs.com/package/web-pki
Script tag (CDN)lacuna-web-pki-2.18.0.min.js2https://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 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.
  • To get a license, contact Lacuna; PKI SDK licenses usually come with a Web PKI license.

The init() arguments a client sets:

ArgumentPurposeArticle
readyCallback run when the component is readyGet started
licenseThe license, when not passed to the constructorLicensing
defaultFailFail callback for every call without its ownDefault fail callback
notInstalledReplaces the redirect to the installation pageNot installed
restPkiUrlYour Rest PKI instance, when it is not the standard https://pki.restCustom Rest PKI URL
requiredApiVersionAPI feature set the page needs (default API 1.3), avoiding needless updatesAPI versions
brandCustomized installation pageCustomized installation page
angularScope, ngZoneRuns callbacks inside AngularJS or Angular cyclesCallbacks 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 your notInstalled(status, message) with NOT_INSTALLED, OUTDATED or BROWSER_NOT_SUPPORTED. See Not installed.
  • Error codes: code tells which error occurred, and Default fail callback describes each one. On license_not_set, license_invalid, license_expired, license_domain_not_allowed and license_restricted, check the license against 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.

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.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:

View as Markdown