---
title: "Your certificates in the browser"
product: "Web PKI"
slug: "certificates-in-the-browser"
language: "en"
canonical_url: "https://try.lacunasoftware.com/en/web-pki/certificates-in-the-browser"
docs_url: "https://docs.lacunasoftware.com/en-us/articles/web-pki"
samples:
  - title: "List the user's certificates with Web PKI"
    language: "dotnet"
    framework: "aspnet-mvc"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ListCertJQueryController.cs"
  - title: "Read a certificate's details with Web PKI"
    language: "dotnet"
    framework: "aspnet-mvc"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ReadCertJQueryController.cs"
  - title: "Authenticate with a digital certificate using Rest PKI Core"
    language: "java"
    framework: "spring-boot"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/AuthenticationRestPkiCoreController.java"
  - title: "List the user's certificates with Web PKI"
    language: "java"
    framework: "spring-boot"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ListCertJQueryController.java"
  - title: "Read a certificate's details with Web PKI"
    language: "java"
    framework: "spring-boot"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ReadCertJQueryController.java"
  - title: "List the user's certificates with Web PKI"
    language: "nodejs"
    framework: "express"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/list-cert-jquery.js"
  - title: "Read a certificate's details with Web PKI"
    language: "nodejs"
    framework: "express"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/read-cert-jquery.js"
  - title: "List the user's certificates with Web PKI"
    language: "python"
    framework: "flask"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/list_cert_jquery.py"
  - title: "Read a certificate's details with Web PKI"
    language: "python"
    framework: "flask"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/read_cert_jquery.py"
  - title: "List the user's certificates with Web PKI"
    language: "ruby"
    framework: "rails"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/list_cert_jquery_controller.rb"
  - title: "Read a certificate's details with Web PKI"
    language: "ruby"
    framework: "rails"
    url: "https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/read_cert_jquery_controller.rb"
samples_repo: null
trace_recorded: "2026-10-12"
last_generated: "2026-10-12T15:24:28Z"
---

# Your certificates in the browser

See the certificates on your computer through Web PKI, right in the browser, then prove you hold one's private key, checked on the server by Rest PKI Core.

Live demo: [https://try.lacunasoftware.com/en/web-pki/certificates-in-the-browser](https://try.lacunasoftware.com/en/web-pki/certificates-in-the-browser). It runs against Lacuna's real products; this page describes it for AI coding agents.

## How it works

1. Check Web PKI
2. Choose a certificate
3. Prove you hold the key

## Call sequence

Recorded on 2026-10-12 against the real products with Lacuna's public test certificates and data. Keys, tokens, sessions, ids, file contents and personal data are masked.

### 1. List the visitor's certificates, with no filter.

In the browser: `pki.listCertificates()`

### 2. Rest PKI Core prepares an authentication in the Demo's security context and returns the nonce to sign and the state to keep.

On the server: `IRestPkiService.PrepareAuthenticationAsync`

`POST https://core.pki.rest/api/v2/authentication` → 200

Request:

```json
{
  "SecurityContextId": "00000000-0000-0000-0000-000000000000"
}
```

Response:

```json
{
  "state": "***",
  "toSign": {
    "signatureAlgorithm": {
      "algorithm": "SHA256WithRSA",
      "oid": "1.2.840.113549.1.1.11",
      "digestAlgorithm": "SHA256",
      "digestAlgorithmOid": "2.16.840.1.101.3.4.2.1"
    },
    "data": "<data, 16 bytes>",
    "hash": "<hash, 32 bytes>",
    "digestInfo": "<base64, 51 bytes>"
  },
  "toSignHash": {
    "algorithm": "SHA256",
    "value": "<base64, 32 bytes>",
    "hexValue": "<hex, 32 bytes>"
  }
}
```

### 3. Read the chosen certificate's public part: no PIN is asked, and the key stays where it is.

In the browser: `pki.readCertificate({ thumbprint })`

### 4. Sign the nonce over SHA-256 with the certificate's private key, behind the system's PIN prompt: the key never leaves the browser's store or token.

In the browser: `pki.signData({ thumbprint, data, digestAlgorithm: "SHA-256" })`

### 5. Rest PKI Core completes the authentication with the state, the certificate and the signature: it checks the signature, then validates the certificate, for the result lines.

On the server: `IRestPkiService.CompleteAuthenticationAsync`

`POST https://core.pki.rest/api/v2/authentication/completion` → 200

Request:

```json
{
  "State": "***",
  "Certificate": "<Certificate, 1645 bytes>",
  "Signature": "<Signature, 256 bytes>"
}
```

Response:

```json
{
  "success": true,
  "certificate": {
    "subjectName": {
      "country": "BR",
      "organization": "Lacuna Software",
      "commonName": "Alan Mathison Turing",
      "allValues": {
        "2.5.4.6": [
          "BR"
        ],
        "2.5.4.10": [
          "Lacuna Software"
        ],
        "2.5.4.3": [
          "Alan Mathison Turing"
        ]
      },
      "dnString": "CN=Alan Mathison Turing,O=Lacuna Software,C=BR"
    },
    "issuerName": {
      "country": "BR",
      "organization": "Lacuna Software",
      "organizationUnit": "IT",
      "commonName": "Lacuna CA Test v7",
      "allValues": {
        "2.5.4.6": [
          "BR"
        ],
        "2.5.4.10": [
          "Lacuna Software"
        ],
        "2.5.4.11": [
          "IT"
        ],
        "2.5.4.3": [
          "Lacuna CA Test v7"
        ]
      },
      "dnString": "CN=Lacuna CA Test v7,OU=IT,O=Lacuna Software,C=BR"
    },
    "issuerDisplayName": "Lacuna CA Test v7",
    "serialNumber": "<hex, 19 bytes>",
    "validityStart": "2025-01-03T14:16:57+00:00",
    "validityEnd": "2075-01-03T14:21:14+00:00",
    "issuer": {
      "subjectName": {
        "country": "BR",
        "organization": "Lacuna Software",
        "organizationUnit": "IT",
        "commonName": "Lacuna CA Test v7",
        "allValues": {
          "2.5.4.6": [
            "BR"
          ],
          "2.5.4.10": [
            "Lacuna Software"
          ],
          "2.5.4.11": [
            "IT"
          ],
          "2.5.4.3": [
            "Lacuna CA Test v7"
          ]
        },
        "dnString": "CN=Lacuna CA Test v7,OU=IT,O=Lacuna Software,C=BR"
      },
      "issuerName": {
        "country": "BR",
        "organization": "ICP-Brasil",
        "organizationUnit": "Lacuna Software - LS",
        "commonName": "Lacuna Root Test v3",
        "allValues": {
          "2.5.4.6": [
            "BR"
          ],
          "2.5.4.10": [
            "ICP-Brasil"
          ],
          "2.5.4.11": [
            "Lacuna Software - LS"
          ],
          "2.5.4.3": [
            "Lacuna Root Test v3"
          ]
        },
        "dnString": "CN=Lacuna Root Test v3,OU=Lacuna Software - LS,O=ICP-Brasil,C=BR"
      },
      "issuerDisplayName": "Lacuna Root Test v3",
      "serialNumber": "3",
      "validityStart": "2024-12-16T21:30:30+00:00",
      "validityEnd": "2074-12-16T03:00:00+00:00",
      "issuer": {
        "subjectName": {
          "country": "BR",
          "organization": "ICP-Brasil",
          "organizationUnit": "Lacuna Software - LS",
          "commonName": "Lacuna Root Test v3",
          "allValues": {
            "2.5.4.6": [
              "BR"
            ],
            "2.5.4.10": [
              "ICP-Brasil"
            ],
            "2.5.4.11": [
              "Lacuna Software - LS"
            ],
            "2.5.4.3": [
              "Lacuna Root Test v3"
            ]
          },
          "dnString": "CN=Lacuna Root Test v3,OU=Lacuna Software - LS,O=ICP-Brasil,C=BR"
        },
        "issuerName": {
          "country": "BR",
          "organization": "ICP-Brasil",
          "organizationUnit": "Lacuna Software - LS",
          "commonName": "Lacuna Root Test v3",
          "allValues": {
            "2.5.4.6": [
              "BR"
            ],
            "2.5.4.10": [
              "ICP-Brasil"
            ],
            "2.5.4.11": [
              "Lacuna Software - LS"
            ],
            "2.5.4.3": [
              "Lacuna Root Test v3"
            ]
          },
          "dnString": "CN=Lacuna Root Test v3,OU=Lacuna Software - LS,O=ICP-Brasil,C=BR"
        },
        "issuerDisplayName": "Lacuna Root Test v3",
        "serialNumber": "1",
        "validityStart": "2024-12-16T20:42:10+00:00",
        "validityEnd": "2074-12-16T03:00:00+00:00",
        "pkiBrazil": {
          "certificateType": "Unknown"
        },
        "pkiItaly": {
          "certificateType": "Undefined"
        },
        "binaryThumbprintSHA256": "<base64, 32 bytes>",
        "thumbprint": "<hex, 20 bytes>",
        "thumbprintSHA256": "<hex, 32 bytes>",
        "subjectCommonName": "Lacuna Root Test v3",
        "subjectDisplayName": "Lacuna Root Test v3",
        "organization": "ICP-Brasil"
      },
      "pkiBrazil": {
        "certificateType": "Unknown"
      },
      "pkiItaly": {
        "certificateType": "Undefined"
      },
      "binaryThumbprintSHA256": "<base64, 32 bytes>",
      "thumbprint": "<hex, 20 bytes>",
      "thumbprintSHA256": "<thumbprintSHA256, 44 chars>",
      "subjectCommonName": "Lacuna CA Test v7",
      "subjectDisplayName": "Lacuna CA Test v7",
      "organization": "Lacuna Software"
    },
    "pkiBrazil": {
      "certificateType": "A1",
      "cpf": "***.***.***-**",
      "responsavel": "Alan Mathison Turing",
      "dateOfBirth": "2000-01-01"
    },
    "pkiItaly": {
      "certificateType": "Undefined"
    },
    "binaryThumbprintSHA256": "<base64, 32 bytes>",
    "thumbprint": "<hex, 20 bytes>",
    "thumbprintSHA256": "<hex, 32 bytes>",
    "subjectCommonName": "Alan Mathison Turing",
    "subjectDisplayName": "Alan Mathison Turing",
    "subjectIdentifier": "***",
    "emailAddress": "someone@example.com"
  },
  "validationResults": {
    "passedChecks": [
      {
        "type": "CertificateIssuerInvalid",
        "message": "The certificate issuer is valid and trusted",
        "innerValidationResults": {
          "passedChecks": [
            {
              "type": "CertificateIssuerInvalid",
              "message": "The certificate issuer is valid and trusted",
              "innerValidationResults": {
                "passedChecks": [
                  {
                    "type": "Success",
                    "message": "Success",
                    "detail": "The root Lacuna Root Test v3 is trusted"
                  },
                  {
                    "type": "Success",
                    "message": "Success",
                    "detail": "The certificate's signature for the certificate of Lacuna Root Test v3 is valid"
                  },
                  {
                    "type": "Success",
                    "message": "Success",
                    "detail": "The certificate of Lacuna Root Test v3 is inside its validity period"
                  }
                ],
                "errors": [],
                "warnings": []
              }
            },
            {
              "type": "Success",
              "message": "Success",
              "detail": "The certificate's signature for the certificate of Lacuna CA Test v7 is valid"
            },
            {
              "type": "Success",
              "message": "Success",
              "detail": "The certificate of Lacuna CA Test v7 is inside its validity period"
            },
            "… and 1 more"
          ],
          "errors": [],
          "warnings": []
        }
      },
      {
        "type": "Success",
        "message": "Success",
        "detail": "The certificate's signature for the certificate of Alan Mathison Turing is valid"
      },
      {
        "type": "Success",
        "message": "Success",
        "detail": "The certificate of Alan Mathison Turing is inside its validity period"
      },
      "… and 1 more"
    ],
    "errors": [],
    "warnings": []
  }
}
```

## Patterns to copy

- Load Web PKI in the browser only once the page is interactive, never while it is prerendered on the server, and check the environment first: never call `init()` on a phone (`isSupportedMobile`), and stop in desktop Safari, which Web PKI doesn't support.
- Web PKI's calls aren't native promises: `init()` takes callbacks and later calls return the library's own promise with `.success`/`.fail`. Give every call its own `.fail`, or its failure falls through to `init()`'s `defaultFail`, and treat `user_cancelled` as a cancel, not an error.
- Call `listCertificates()` with no filter: Lacuna advises against filtering, because users then report "missing" certificates. Key certificates by thumbprint.
- Prove possession of the key with Rest PKI Core in two calls around the browser: `PrepareAuthenticationAsync` gives a state and a nonce, Web PKI's `signData` signs the nonce (SHA-256), then `CompleteAuthenticationAsync` takes the state, the certificate from `readCertificate` and the signature. Get a fresh challenge per attempt: the state lasts 60 minutes and is never sent twice.
- Handle every way the completion ends: success, `CertificateFailedValidation` (the signature is fine, the certificate isn't), `StaleSession`, and a bad signature, which arrives as a thrown `RestPkiExceptionV2` with `BadSignature` rather than as a result.

## Links

- Live demo: https://try.lacunasoftware.com/en/web-pki/certificates-in-the-browser (Portuguese: https://try.lacunasoftware.com/pt/web-pki/certificates-in-the-browser)
- Docs: https://docs.lacunasoftware.com/en-us/articles/web-pki
- Sample, .NET (aspnet-mvc): [List the user's certificates with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ListCertJQueryController.cs)
- Sample, .NET (aspnet-mvc): [Read a certificate's details with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/dotnet/mvc/PkiSuiteAspNetMvcSample/Controllers/ReadCertJQueryController.cs)
- Sample, Java (spring-boot): [Authenticate with a digital certificate using Rest PKI Core](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/AuthenticationRestPkiCoreController.java)
- Sample, Java (spring-boot): [List the user's certificates with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ListCertJQueryController.java)
- Sample, Java (spring-boot): [Read a certificate's details with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/java/springmvc/src/main/java/com/lacunasoftware/pkisuite/controller/ReadCertJQueryController.java)
- Sample, Node.js (express): [List the user's certificates with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/list-cert-jquery.js)
- Sample, Node.js (express): [Read a certificate's details with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/nodejs/expressmvc/routes/read-cert-jquery.js)
- Sample, Python (flask): [List the user's certificates with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/list_cert_jquery.py)
- Sample, Python (flask): [Read a certificate's details with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/python/flask/sample/views/read_cert_jquery.py)
- Sample, Ruby (rails): [List the user's certificates with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/list_cert_jquery_controller.rb)
- Sample, Ruby (rails): [Read a certificate's details with Web PKI](https://github.com/LacunaSoftware/PkiSuiteSamples/blob/master/ruby/rails/app/controllers/read_cert_jquery_controller.rb)
- Every demo: https://try.lacunasoftware.com/llms.txt and https://try.lacunasoftware.com/demos.json
