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

@cap-kit/tls-fingerprint

v8.0.1

Published

Runtime TLS leaf certificate SHA-256 fingerprint validation plugin for Capacitor (iOS & Android)

Readme

Overview

This Capacitor plugin validates the SHA-256 fingerprint of a server's TLS leaf certificate at runtime.

What this plugin does

  • Extracts the leaf certificate from an HTTPS connection
  • Computes its SHA-256 fingerprint
  • Compares against expected fingerprints provided at runtime or in static configuration

What this plugin does NOT do

  • It does NOT perform anchor-based certificate pinning
  • It does NOT load local certificate files
  • It does NOT modify or override the system trust store
  • It does NOT validate the certificate chain

Platform Support

| Platform | Status | | -------- | --------------------------------------------------- | | iOS | Supported | | Android | Supported | | Web | Unsupported - methods reject with unimplemented() |


Install

pnpm add @cap-kit/tls-fingerprint
# or
npm install @cap-kit/tls-fingerprint
# or
yarn add @cap-kit/tls-fingerprint
# then run:
npx cap sync

Obtaining Fingerprints

To use this plugin, you need the SHA-256 fingerprint of the server certificate.

Method 1 — Using OpenSSL

openssl x509 -noout -fingerprint -sha256 -inform pem -in /path/to/cert.pem

Example output:

SHA256 Fingerprint=EF:BA:26:D8:C1:CE:37:79:AC:77:63:0A:90:F8:21:63:A3:D6:89:2E:D6:AF:EE:40:86:72:CF:19:EB:A7:A3:62

The plugin normalizes fingerprints to lowercase hex with no separators. For example, EF:BA:26:... becomes efba26...

Method 2 — Using the Built-in CLI Tool

This project includes a CLI utility to retrieve certificates from remote servers:

npx cap-kit-tls-fingerprint example.com
npx cap-kit-tls-fingerprint example.com api.example.com --mode multi

The CLI is for development-time certificate inspection only. It does not perform runtime validation.


Configuration

Configuration options for the TLSFingerprint plugin.

| Prop | Type | Description | Default | Since | | --------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- | | verboseLogging | boolean | Enables verbose native logging. When enabled, additional debug information is printed to the native console (Logcat on Android, Xcode on iOS). This option affects native logging behavior only and has no impact on the JavaScript API. | false | 8.0.0 | | fingerprint | string | Default fingerprint used by checkCertificate() when options.fingerprint is not provided at runtime. | | 8.0.0 | | fingerprints | string[] | Default fingerprints used by checkCertificates() when options.fingerprints is not provided at runtime. | | 8.0.0 | | excludedDomains | string[] | Domains to bypass. Matches exact domain or subdomains. Do not include schemes or paths. | | 8.0.0 |

Examples

In capacitor.config.json:

{
  "plugins": {
    "TLSFingerprint": {
      "verboseLogging": true,
      "fingerprint": "50:4B:A1:B5:48:96:71:F3:9F:87:7E:0A:09:FD:3E:1B:C0:4F:AA:9F:FC:83:3E:A9:3A:00:78:88:F8:BA:60:26",
      "fingerprints": [
        "50:4B:A1:B5:48:96:71:F3:9F:87:7E:0A:09:FD:3E:1B:C0:4F:AA:9F:FC:83:3E:A9:3A:00:78:88:F8:BA:60:26"
      ]
    }
  }
}

In capacitor.config.ts:

/// <reference types="@cap-kit/tls-fingerprint" />

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  plugins: {
    TLSFingerprint: {
      verboseLogging: true,
      fingerprint: '50:4B:A1:B5:48:96:71:F3:9F:87:7E:0A:09:FD:3E:1B:C0:4F:AA:9F:FC:83:3E:A9:3A:00:78:88:F8:BA:60:26',
      fingerprints: ["50:4B:A1:B5:48:96:71:F3:9F:87:7E:0A:09:FD:3E:1B:C0:4F:AA:9F:FC:83:3E:A9:3A:00:78:88:F8:BA:60:26"],
    },
  },
};

export default config;

Note: All network operations have a 10-second timeout. If the server does not respond within this time, the Promise is rejected with TLSFingerprintErrorCode.TIMEOUT.


API

TLS Fingerprint Capacitor Plugin interface.

checkCertificate(...)

checkCertificate(options: TLSFingerprintOptions) => Promise<TLSFingerprintResult>

Checks the SSL certificate of a server using a single fingerprint.

| Param | Type | | ------------- | ----------------------------------------------------------------------- | | options | TLSFingerprintOptions |

Returns: Promise<TLSFingerprintResult>

Since: 8.0.0


checkCertificates(...)

checkCertificates(options: TLSFingerprintMultiOptions) => Promise<TLSFingerprintResult>

Checks the SSL certificate of a server using multiple allowed fingerprints.

| Param | Type | | ------------- | --------------------------------------------------------------------------------- | | options | TLSFingerprintMultiOptions |

Returns: Promise<TLSFingerprintResult>

Since: 8.0.0


getPluginVersion()

getPluginVersion() => Promise<PluginVersionResult>

Returns the native plugin version.

The returned version corresponds to the native implementation bundled with the application.

Returns: Promise<PluginVersionResult>

Since: 8.0.0

Example

const { version } = await TLSFingerprint.getPluginVersion();

Interfaces

TLSFingerprintResult

Result returned by an TLS fingerprint operation.

This object is returned for ALL outcomes:

  • Success: fingerprintMatched: true
  • Mismatch: fingerprintMatched: false with error info (RESOLVED, not rejected)

Only operation failures (invalid input, config missing, network errors, timeout, internal errors) reject the Promise.

| Prop | Type | Description | | ------------------------ | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | actualFingerprint | string | The actual SHA-256 fingerprint of the server certificate. Present in fingerprint and excluded modes. | | fingerprintMatched | boolean | Indicates whether the certificate validation succeeded. - true → Pinning passed - false → Pinning failed | | matchedFingerprint | string | The fingerprint that successfully matched, if any. | | excludedDomain | boolean | Indicates that TLS fingerprint was skipped because the request host matched an excluded domain. | | mode | 'fingerprint' | 'excluded' | Indicates which pinning mode was used. - "fingerprint" - "excluded" | | error | string | Human-readable error message when pinning fails. Present when fingerprintMatched: false. | | errorCode | TLSFingerprintErrorCode | Standardized error code aligned with TLSFingerprintErrorCode. |

TLSFingerprintOptions

Options for checking a single SSL certificate.

| Prop | Type | Description | | ----------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | url | string | HTTPS URL of the server whose SSL certificate must be checked. This value is REQUIRED and cannot be provided via configuration. | | fingerprint | string | Expected SHA-256 fingerprint of the certificate. Resolution order: 1. options.fingerprint (runtime) 2. plugins.TLSFingerprint.fingerprint (config) If neither is provided, the Promise is rejected with TLSFingerprintErrorCode.UNAVAILABLE. |

TLSFingerprintMultiOptions

Options for checking an SSL certificate using multiple allowed fingerprints.

| Prop | Type | Description | | ------------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | url | string | HTTPS URL of the server whose SSL certificate must be checked. This value is REQUIRED and cannot be provided via configuration. | | fingerprints | string[] | Expected SHA-256 fingerprints of the certificate. Resolution order: 1. options.fingerprints (runtime) 2. plugins.TLSFingerprint.fingerprints (config) If neither is provided, the Promise is rejected with TLSFingerprintErrorCode.UNAVAILABLE. |

PluginVersionResult

Result returned by the getPluginVersion method.

| Prop | Type | Description | | ------------- | ------------------- | ---------------------------------------- | | version | string | The native version string of the plugin. |

Enums

TLSFingerprintErrorCode

| Members | Value | Description | | ----------------------- | -------------------------------- | ------------------------------------------------------------------------------ | | UNAVAILABLE | 'UNAVAILABLE' | Required data is missing or the feature is not available. | | CANCELLED | 'CANCELLED' | The user cancelled an interactive flow. | | PERMISSION_DENIED | 'PERMISSION_DENIED' | The user denied a required permission or the feature is disabled. | | INIT_FAILED | 'INIT_FAILED' | The TLS fingerprint operation failed due to a runtime or initialization error. | | INVALID_INPUT | 'INVALID_INPUT' | The input provided to the plugin method is invalid, missing, or malformed. | | UNKNOWN_TYPE | 'UNKNOWN_TYPE' | Invalid or unsupported input was provided. | | NOT_FOUND | 'NOT_FOUND' | The requested resource does not exist. | | CONFLICT | 'CONFLICT' | The operation conflicts with the current state. | | TIMEOUT | 'TIMEOUT' | The operation did not complete within the expected time. | | PINNING_FAILED | 'PINNING_FAILED' | The server certificate fingerprint did not match any expected fingerprint. | | EXCLUDED_DOMAIN | 'EXCLUDED_DOMAIN' | The request host matched an excluded domain. | | NETWORK_ERROR | 'NETWORK_ERROR' | Network connectivity or TLS handshake error. | | SSL_ERROR | 'SSL_ERROR' | SSL/TLS specific error (certificate expired, handshake failure, etc.). |


Security Considerations

This plugin validates fingerprint equality only.

What this means

  • The plugin compares the server's leaf certificate SHA-256 fingerprint against expected values
  • It does NOT replace TLS validation
  • It does NOT override trust evaluation
  • Expired or self-signed certificates will validate if the fingerprint matches

Limitations

  • Fingerprint validation requires active maintenance
  • Certificate rotation requires configuration updates
  • Misconfiguration may result in loss of network connectivity

This plugin is provided as-is, without warranty. Always test thoroughly before production deployment.


Usage Examples

Single fingerprint check

import { TLSFingerprint } from '@cap-kit/tls-fingerprint';

const result = await TLSFingerprint.checkCertificate({
  url: 'https://example.com',
  fingerprint: 'aabbccdd...',
});

if (result.fingerprintMatched) {
  console.log('Certificate is trusted');
} else {
  console.log('Fingerprint mismatch:', result.error);
}

Multiple fingerprints (certificate rotation)

import { TLSFingerprint } from '@cap-kit/tls-fingerprint';

const result = await TLSFingerprint.checkCertificates({
  url: 'https://example.com',
  fingerprints: ['aabbccdd...', '11223344...'],
});

if (result.fingerprintMatched) {
  console.log('Certificate matched:', result.matchedFingerprint);
}

Using static configuration

// capacitor.config.ts
plugins: {
  TLSFingerprint: {
    fingerprint: 'aabbccdd...',
    excludedDomains: ['localhost', 'analytics.example.com']
  }
}

// App code
const result = await TLSFingerprint.checkCertificate({
  url: 'https://example.com',
});

Contributing

Contributions are welcome. Please read the contributing guide before submitting a pull request.


Credits

This plugin is based on prior work from the community and has been refactored for Capacitor v8 and Swift Package Manager compatibility.

Original inspiration:


License

MIT