npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pkistudio/certgadgets

v0.1.4

Published

Browser certificate investigation tools and reusable Certificate Gadgets API.

Downloads

450

Readme

Certificate Gadgets

Certificate Gadgets is an experimental browser tool for inspecting X.509 certificates. It keeps the loaded certificate in a PkiStudioJS-style tree on the left, shows certificate-focused details on the right, and sends the selected DER object to the embedded PkiStudioJS ASN.1 viewer.

Important for browser validation: Browser applications that use @pkistudio/certgadgets and want to offer network-assisted validation should provide their own fetch proxy or host networking implementation. Certificate AIA, OCSP, and CRL endpoints often use HTTP or omit CORS headers, so direct browser fetches may fail. See GitHub Pages network validation for an example proxy setup.

Current version: 0.1.4

Features

Certificate Investigation

  • Loads X.509 certificates from files, including DER certificates and PEM files with a -----BEGIN CERTIFICATE----- block.
  • Loads certificate data from the clipboard as PEM or HEX.
  • Keeps one loaded certificate document at a time; loading another certificate closes the previous certificate before opening the new one.
  • Shows the certificate source, version, serial number, signature algorithm, issuer, validity, subject, public key, certificate signature algorithm, and signature size.
  • Reverses issuer and subject Distinguished Name display for easier reading in the detail pane.
  • Shows the validity range and calculated validity span in days.
  • Calculates and displays a Subject Key Identifier-style SHA-1 preview for the subject public key bits.
  • Keeps the investigation workflow separate from key-generation and PKCS#12 workflows handled by related PKI Studio modules.

Certificate Tree

  • Displays each loaded certificate as a top-level tree item.
  • Adds child items for TBSCertificate fields, including Version, Serial Number, Signature Algorithm, Issuer, Validity, Subject, Subject Public Key Info, optional unique IDs, Extensions, Certificate Signature Algorithm, and Certificate Signature Value.
  • Displays each X.509 extension as a child item under Extensions.
  • Uses compact tree labels for field values and truncates very long values in the tree while keeping the full value available to assistive technology.
  • Uses certificate-specific tree icons for common extensions such as Basic Constraints, Key Usage, Extended Key Usage, Subject Alternative Name, Issuer Alternative Name, CRL Distribution Points, Certificate Policies, Authority Information Access, Subject Key Identifier, and Authority Key Identifier.
  • Selects a tree item to update the detail pane and, when DER is available, the embedded ASN.1 viewer.

Extension Analysis

  • Parses extension OIDs, critical flags, encoded value lengths, decoded readable values, and network resources.
  • Names common extensions and algorithms from built-in OID tables.
  • Decodes readable strings and GeneralName values from extension ASN.1 data, including DNS names, email names, URI values, IP addresses, and object identifiers.
  • Summarizes Basic Constraints, Key Usage, Extended Key Usage, Subject Key Identifier, and Authority Key Identifier values when possible.
  • Detects HTTP and HTTPS network resources from extensions.
  • Recognizes Authority Information Access OCSP responder URLs and CA Issuers certificate URLs.
  • Recognizes CRL Distribution Point URLs and other likely CRL resources.

Network-Assisted Validation

  • Performs certificate parsing and structural inspection locally by default.
  • Requires a host-provided networking path, such as a fetch proxy, for reliable browser-based AIA, OCSP, and CRL requests from static HTTPS deployments.
  • Does not silently fetch CRLs, OCSP responses, AIA resources, or issuer certificates.
  • Shows explicit action buttons for detected network targets such as OCSP, AIA CA Issuers, and CRL Distribution Points.
  • Asks the user or host application for network access confirmation before each request.
  • Lets host applications provide confirmNetworkAccess and fetchNetworkResource callbacks so browser apps, VS Code Webviews, and other hosts can own their own permission and networking model.
  • Fetches AIA CA Issuers certificate data and records the result when requested.
  • Fetches CRL Distribution Point data and records the HTTP result and received bytes when requested.
  • Generates an OCSP request for the loaded certificate when both an OCSP URL and an AIA CA Issuers URL are available.
  • Sends OCSP requests as application/ocsp-request and asks for application/ocsp-response responses.
  • Parses OCSP response status and checks whether a BasicOCSPResponse contains a SingleResponse for the target certificate when enough issuer data is available.
  • Records follow-up transcript notes for validation work that is not yet a full path-validation engine, such as CRL issuer checks and BasicOCSPResponse signature checks.
  • Uses a Vite-only development fetch proxy on localhost when browser CORS blocks direct network validation requests.

Validation Results

  • Shows a dedicated Validation pane between the main workspace and API Log.
  • Records the date, result status, target, and detail for each explicit validation request.
  • Uses OK, NG, and ... statuses for completed, failed, and running validation entries.
  • Keeps the newest 200 validation results and drops older entries automatically.
  • Lets validation results be selected to show a detailed transcript in the right pane.
  • Keeps request and response artifacts for validation results when bytes are available.
  • Opens certificate artifacts in a new Certificate Gadgets window.
  • Opens ASN.1 artifacts in a standalone PkiStudioJS viewer window.
  • Offers to wrap non-ASN.1 raw response bytes in an OCTET STRING before opening them in the ASN.1 viewer.
  • Provides a Clear button for resetting visible validation results.

Application Shell

  • Fills the browser viewport with a certificate tree, detail pane, embedded ASN.1 viewer, Validation pane, and API Log pane.
  • Lets the left certificate pane and right detail pane be resized with the vertical splitter between them.
  • Lets the embedded ASN.1 viewer height be resized inside the detail pane.
  • Lets the Validation pane and API Log pane be resized with horizontal splitters.
  • Persists pane sizes in local storage.
  • Follows the browser or operating system light/dark theme preference.
  • Supports ?theme=light and ?theme=dark for forcing the application shell and viewer-only windows to a specific theme.
  • Supports a programmatic theme: 'light' or theme: 'dark' option when the app is mounted by a host.
  • Passes the effective theme to Certificate Gadgets and viewer-only windows opened from validation artifacts.
  • Shows an About dialog with the current Certificate Gadgets version.
  • Follows the PKI Studio family style so certificate tools can feel consistent with related modules.

Loading and Saving

  • Provides a Load menu for loading from a file, from clipboard PEM, or from clipboard HEX.
  • Accepts .cer, .crt, .der, and .pem certificate files from the file picker.
  • Validates loaded data with PKIjs before adding it to the tree.
  • Shows errors in the message area and API Log when input is not a readable X.509 certificate.
  • Provides a Save menu for writing the selected DER-backed tree item as DER.
  • Provides a Save menu item for writing the loaded certificate as PEM.
  • Uses the browser's native save-file picker when available, with a download fallback for browsers that do not support it.
  • Provides a Close action that clears the loaded certificate and validation results.

Embedded ASN.1 Viewer

  • Embeds the npm-provided PkiStudioJS viewer directly in the right pane.
  • Displays the selected certificate, TBSCertificate field, extension, signature algorithm, or signature value DER object.
  • Keeps the embedded viewer in read-only mode for certificate investigation.
  • Uses the PkiStudioJS 0.6 viewer while disabling actions that would edit, insert, delete, load, or close DER data inside the embedded viewer.
  • Keeps PkiStudioJS Save and New Window behavior available for the currently displayed DER object.
  • Opens PkiStudioJS New Window output in a standalone viewer-only page instead of a new Certificate Gadgets application shell.
  • Accepts transferred data from PkiStudioJS windows: certificate data opens in Certificate Gadgets, while other complete ASN.1 DER data is redirected to the standalone viewer-only page.

CertGadgetsCore API

  • Exposes CertGadgetsCore through npm imports and window.CertGadgetsCore as a UI-independent helper API.
  • Creates certificate document models from DER or PEM certificate bytes.
  • Parses X.509 certificate fields and extensions with PKIjs and asn1js.
  • Builds the certificate tree model used by the browser app without depending on DOM APIs.
  • Collects explicit network-validation plans from a parsed certificate document.
  • Provides reusable DER, PEM, HEX, Base64, ASN.1, and ArrayBuffer helpers.
  • Keeps host-specific behavior, file access, dialogs, network access, and Webview lifecycle outside the core module.
  • Reads the package version from the build-time package metadata, so the exported CertGadgetsCore.version value stays aligned with package.json.

CertGadgetsValidation API

  • Exposes CertGadgetsValidation from @pkistudio/certgadgets/validation as a UI-independent helper API for explicit network-assisted validation flows.
  • Creates network validation plans for certificate tree items with AIA, OCSP, CRL, or generic HTTP resources.
  • Prepares OCSP validation plans by fetching the issuer certificate through a host-provided callback and generating an application/ocsp-request body.
  • Assesses HTTP validation responses and records target-specific transcript lines for OCSP, CRL Distribution Points, AIA CA Issuers, and generic AIA resources.
  • Parses OCSP response status and checks matching SingleResponse certificate status when target and issuer certificate bytes are available.
  • Classifies validation request and response artifacts as certificate, ASN.1, or raw bytes.
  • Keeps actual network fetching, user confirmation, persistence, and UI display outside the validation module.
  • Uses the same build-time version source as CertGadgetsCore, so CertGadgetsValidation.version also stays aligned with package.json.

npm Package API

  • Exports the core helper API from @pkistudio/certgadgets and @pkistudio/certgadgets/core.
  • Exports network-assisted validation helpers from @pkistudio/certgadgets/validation.
  • Exports the browser app initializer from @pkistudio/certgadgets/app.
  • Exports app styling from @pkistudio/certgadgets/styles.css.
  • Lets Webview hosts provide network confirmation and fetch callbacks without depending on VS Code APIs inside this package.

API Log

  • Shows a bottom API Log pane for browser, parsing, viewer, file, clipboard, save, and network activity.
  • Logs operations such as PkiStudioJS initialization, file reads, clipboard reads, certificate validation, certificate loading, certificate closing, DER saves, PEM saves, network requests, blocked network requests, and validation artifact opens.
  • Displays timestamps with millisecond precision.
  • Keeps the newest 200 log entries and drops older entries automatically.
  • Provides a right-aligned Clear button for resetting the visible log.

Certificate data is kept in browser memory as DER. Network-assisted validation is intentionally separated from local parsing: users or host applications must approve each network request before Certificate Gadgets sends it.

Development

Install dependencies:

npm install

Start the local development server:

npm run dev

The development server includes a localhost-only fetch proxy for explicit network validation requests that would otherwise be blocked by browser CORS rules.

GitHub Pages network validation

GitHub Pages serves Certificate Gadgets as a static HTTPS site. Browser security rules block many certificate validation URLs directly because certificates often publish AIA, OCSP, and CRL resources over http://, and many responders do not allow the Pages origin with CORS. To make Validation work for Pages users, deploy an HTTPS fetch proxy and pass its URL to the Pages build.

One simple option is Cloudflare Workers. Create a Worker such as certgadgets-fetch, deploy the script below, and use its /fetch URL as VITE_CERTGADGETS_FETCH_PROXY_URL.

const ALLOWED_ORIGIN = 'https://pkistudio.github.io';
const MAX_BODY_BYTES = 5 * 1024 * 1024;

export default {
  async fetch(request) {
    const corsHeaders = {
      'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
      'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, X-CertGadgets-Target-Method, X-CertGadgets-Target-Content-Type, X-CertGadgets-Target-Accept',
      'Access-Control-Expose-Headers': 'Content-Type, X-CertGadgets-Proxied'
    };

    if (request.method === 'OPTIONS') return new Response(null, { status: 204, headers: corsHeaders });

    const requestUrl = new URL(request.url);
    if (requestUrl.pathname !== '/fetch') return new Response('Not found', { status: 404, headers: corsHeaders });

    const target = requestUrl.searchParams.get('url');
    if (!target || !/^https?:\/\//i.test(target)) return new Response('Missing or unsupported target URL.', { status: 400, headers: corsHeaders });

    const targetUrl = new URL(target);
    if (isPrivateHost(targetUrl.hostname)) return new Response('Target host is not allowed.', { status: 403, headers: corsHeaders });

    const targetMethod = request.headers.get('X-CertGadgets-Target-Method') || (request.method === 'POST' ? 'POST' : 'GET');
    const targetHeaders = new Headers();
    const contentType = request.headers.get('X-CertGadgets-Target-Content-Type');
    const accept = request.headers.get('X-CertGadgets-Target-Accept');
    if (contentType) targetHeaders.set('Content-Type', contentType);
    if (accept) targetHeaders.set('Accept', accept);

    let body;
    if (request.method === 'POST') {
      const bytes = await request.arrayBuffer();
      if (bytes.byteLength > MAX_BODY_BYTES) return new Response('Request body too large.', { status: 413, headers: corsHeaders });
      body = bytes;
    }

    try {
      const targetResponse = await fetch(targetUrl, { method: targetMethod, headers: targetHeaders, body });
      const responseHeaders = new Headers(corsHeaders);
      responseHeaders.set('Content-Type', targetResponse.headers.get('Content-Type') || 'application/octet-stream');
      responseHeaders.set('X-CertGadgets-Proxied', '1');
      return new Response(targetResponse.body, { status: targetResponse.status, headers: responseHeaders });
    } catch (error) {
      return new Response(error instanceof Error ? error.message : String(error), {
        status: 502,
        headers: { ...corsHeaders, 'Content-Type': 'text/plain; charset=utf-8' }
      });
    }
  }
};

function isPrivateHost(hostname) {
  const host = hostname.toLowerCase();
  return host === 'localhost' ||
    host === '127.0.0.1' ||
    host === '::1' ||
    /^10\./.test(host) ||
    /^192\.168\./.test(host) ||
    /^172\.(1[6-9]|2\d|3[0-1])\./.test(host) ||
    /^169\.254\./.test(host);
}

Then configure this repository so the Pages workflow includes the proxy URL in the Vite build:

  1. Open the GitHub repository settings.
  2. Go to Secrets and variables -> Actions -> Variables.
  3. Create a repository variable named VITE_CERTGADGETS_FETCH_PROXY_URL.
  4. Set its value to the Worker endpoint, for example https://certgadgets-fetch.example.workers.dev/fetch.
  5. Re-run the Deploy GitHub Pages workflow or push to main.

When this variable is set, the Pages build fetches certificate validation resources through the configured proxy after direct browser fetch fails. Local development without the variable continues to use the Vite dev proxy on localhost.

Use the checked-in debug certificate when inspecting the UI manually:

fixtures/debug-certificate.pem
fixtures/debug-certificate.der

Open the app, choose Load -> from File, and select either fixture.

Run the TypeScript and production build checks:

npm run check
npm run build

Check the npm package contents before publication:

npm run pack:dry-run

Reusing from npm

Install the package in a browser or Webview project:

npm install @pkistudio/certgadgets

Browser networking note: If your application imports @pkistudio/certgadgets in the browser and enables network-assisted validation, provide a fetch proxy or host networking implementation for AIA, OCSP, and CRL requests. Many certificate endpoints are HTTP-only or do not send CORS headers for arbitrary browser origins, so direct fetch() may fail. The GitHub Pages network validation section shows a concrete proxy configuration.

Use the UI-independent API:

import { CertGadgetsCore } from '@pkistudio/certgadgets';

const bytes = new Uint8Array(await file.arrayBuffer());
const certificate = CertGadgetsCore.createCertificateFromBytes(bytes, file.name);
const plans = CertGadgetsCore.collectNetworkValidationPlans(certificate);

The returned validation plans describe external resources that a host may choose to offer as explicit user actions.

Use the validation helpers directly when a host application owns confirmation, networking, and result display:

import { CertGadgetsCore } from '@pkistudio/certgadgets';
import type { NetworkValidationPlan } from '@pkistudio/certgadgets';
import { CertGadgetsValidation, type NetworkFetchResult } from '@pkistudio/certgadgets/validation';

const certificate = CertGadgetsCore.createCertificateFromBytes(bytes, 'site.cer');
const [plan] = CertGadgetsCore.collectNetworkValidationPlans(certificate);
const fetchResource = async ({ url, method, requestBytes, requestMediaType, acceptMediaType }: NetworkValidationPlan): Promise<NetworkFetchResult> => {
  const response = await fetch(url, {
    method: method ?? (requestBytes ? 'POST' : 'GET'),
    headers: {
      ...(requestMediaType ? { 'Content-Type': requestMediaType } : {}),
      ...(acceptMediaType ? { Accept: acceptMediaType } : {})
    },
    body: requestBytes
  });
  const responseBytes = new Uint8Array(await response.arrayBuffer());
  return {
    status: response.status,
    bytes: responseBytes,
    mediaType: response.headers.get('Content-Type') ?? undefined
  };
};

if (plan) {
  const preparedPlan = await CertGadgetsValidation.prepareNetworkValidationPlan(plan, {
    document: certificate,
    fetchNetworkResource: fetchResource
  });

  const result = await fetchResource(preparedPlan);
  const assessment = await CertGadgetsValidation.assessValidationContent(preparedPlan, result);
  console.log(assessment.status, assessment.transcript);
}

Mount the browser application from an embedded Webview or browser app:

import { initCertificateGadgets } from '@pkistudio/certgadgets/app';
import '@pkistudio/certgadgets/styles.css';

const app = initCertificateGadgets({
  mount: '#app',
  theme: 'dark',
  host: {
    confirmNetworkAccess: async ({ reason, url }) => {
      return window.confirm(`Allow network access for ${reason}?\n\n${url}`);
    },
    fetchNetworkResource: async ({ url, method, requestBytes, requestMediaType, acceptMediaType }) => {
      const response = await fetch(url, {
        method: method ?? (requestBytes ? 'POST' : 'GET'),
        headers: {
          ...(requestMediaType ? { 'Content-Type': requestMediaType } : {}),
          ...(acceptMediaType ? { Accept: acceptMediaType } : {})
        },
        body: requestBytes
      });
      const bytes = new Uint8Array(await response.arrayBuffer());
      return {
        status: response.status,
        byteLength: bytes.byteLength,
        bytes,
        mediaType: response.headers.get('Content-Type') ?? undefined
      };
    }
  }
});

app.loadCertificateBytes(new Uint8Array(await file.arrayBuffer()), file.name);

The package keeps VS Code-specific file access, dialogs, and Webview lifecycle outside @pkistudio/certgadgets; hosts pass those behaviors through callbacks.

License

Certificate Gadgets is licensed under the MIT License. See LICENSE.

PkiStudioJS Dependency

The application imports PkiStudioJS from the published @pkistudio/pkistudiojs npm package for shared ASN.1 viewer behavior:

  • @pkistudio/pkistudiojs/core
  • @pkistudio/pkistudiojs/oid-resolver
  • @pkistudio/pkistudiojs/viewer

The PkiStudioJS OID name table is provided through @pkistudio/pkistudiojs/oid-resolver, so no vendored OID assets are required under public/.

X.509 certificate parsing is handled by PKIjs, with ASN.1 support from asn1js.