@cap-kit/ssl-pinning 8.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapKitSSLPinning.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +25 -0
- package/README.md +750 -0
- package/android/build.gradle +103 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningConfig.kt +22 -0
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningImpl.kt +188 -0
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningPlugin.kt +82 -0
- package/android/src/main/java/io/capkit/sslpinning/utils/SSLPinningLogger.kt +85 -0
- package/android/src/main/java/io/capkit/sslpinning/utils/SSLPinningUtils.kt +44 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/cli/fingerprint.js +163 -0
- package/dist/cli/fingerprint.js.map +1 -0
- package/dist/docs.json +430 -0
- package/dist/esm/cli/fingerprint.d.ts +1 -0
- package/dist/esm/cli/fingerprint.js +161 -0
- package/dist/esm/cli/fingerprint.js.map +1 -0
- package/dist/esm/definitions.d.ts +285 -0
- package/dist/esm/definitions.js +18 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +58 -0
- package/dist/esm/web.js +54 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +95 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +98 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/SSLPinningPlugin/SSLPinningConfig.swift +79 -0
- package/ios/Sources/SSLPinningPlugin/SSLPinningDelegate.swift +81 -0
- package/ios/Sources/SSLPinningPlugin/SSLPinningImpl.swift +111 -0
- package/ios/Sources/SSLPinningPlugin/SSLPinningPlugin.swift +116 -0
- package/ios/Sources/SSLPinningPlugin/Utils/SSLPinningLogger.swift +57 -0
- package/ios/Sources/SSLPinningPlugin/Utils/SSLPinningUtils.swift +47 -0
- package/ios/Sources/SSLPinningPlugin/Version.swift +16 -0
- package/ios/Tests/SSLPinningPluginTests/SSLPinningPluginTests.swift +5 -0
- package/package.json +117 -0
- package/scripts/chmod.js +34 -0
- package/scripts/sync-version.js +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img
|
|
3
|
+
src="https://raw.githubusercontent.com/cap-kit/capacitor-plugins/main/assets/logo.png"
|
|
4
|
+
alt="CapKit Logo"
|
|
5
|
+
width="128"
|
|
6
|
+
/>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<h3 align="center">SSL Pinning</h3>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<strong>
|
|
13
|
+
<code>@cap-kit/ssl-pinning</code>
|
|
14
|
+
</strong>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">Runtime SSL certificate verification for Capacitor applications.</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://www.npmjs.com/package/@cap-kit/ssl-pinning">
|
|
21
|
+
<img src="https://img.shields.io/npm/v/@cap-kit/ssl-pinning?style=flat-square" />
|
|
22
|
+
</a>
|
|
23
|
+
<a href="https://www.npmjs.com/package/@cap-kit/ssl-pinning">
|
|
24
|
+
<img src="https://img.shields.io/npm/dm/@cap-kit/ssl-pinning?style=flat-square" />
|
|
25
|
+
</a>
|
|
26
|
+
<a href="https://www.npmjs.com/package/@cap-kit/ssl-pinning">
|
|
27
|
+
<img src="https://img.shields.io/npm/l/@cap-kit/ssl-pinning?style=flat-square" />
|
|
28
|
+
</a>
|
|
29
|
+
<img src="https://img.shields.io/maintenance/yes/2026?style=flat-square" />
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<br />
|
|
33
|
+
|
|
34
|
+
## Overview
|
|
35
|
+
|
|
36
|
+
`@cap-kit/ssl-pinning` is a Capacitor plugin that performs **runtime SSL certificate
|
|
37
|
+
verification** by validating the **SHA-256 fingerprint** of a server certificate.
|
|
38
|
+
|
|
39
|
+
The plugin works on **iOS and Android** and is designed to:
|
|
40
|
+
|
|
41
|
+
- validate a single fingerprint (`checkCertificate`)
|
|
42
|
+
- validate multiple fingerprints (`checkCertificates`)
|
|
43
|
+
- support configuration-based defaults via `capacitor.config.ts`
|
|
44
|
+
- keep the JavaScript API platform-agnostic and stable
|
|
45
|
+
|
|
46
|
+
This plugin **does not replace TLS** and **does not guarantee absolute security**.
|
|
47
|
+
It enforces explicit trust decisions on top of standard TLS.
|
|
48
|
+
It is a defense-in-depth mechanism that must be maintained correctly.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm add @cap-kit/ssl-pinning
|
|
56
|
+
# or
|
|
57
|
+
npm install @cap-kit/ssl-pinning
|
|
58
|
+
# or
|
|
59
|
+
yarn add @cap-kit/ssl-pinning
|
|
60
|
+
# then run:
|
|
61
|
+
npx cap sync
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 🔑 Obtaining SSL Certificate Fingerprints
|
|
67
|
+
|
|
68
|
+
To use SSL pinning, you must obtain the **SHA-256 fingerprint**
|
|
69
|
+
of the SSL certificate you intend to trust.
|
|
70
|
+
|
|
71
|
+
Fingerprints can be generated using standard tools or via the
|
|
72
|
+
companion CLI utility provided by this project.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### Method 1 — Using a Web Browser
|
|
77
|
+
|
|
78
|
+
1. Open the target website in a modern browser.
|
|
79
|
+
2. View the website certificate details.
|
|
80
|
+
3. Export or copy the certificate (public key).
|
|
81
|
+
4. Use an online fingerprint generator, for example:
|
|
82
|
+
https://www.samltool.com/fingerprint.php
|
|
83
|
+
5. Select **SHA-256** as the algorithm.
|
|
84
|
+
6. Copy the resulting fingerprint (colon-separated format is acceptable).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Method 2 — Using the Command Line (OpenSSL)
|
|
89
|
+
|
|
90
|
+
If you have access to the certificate file (`.pem`, `.cer`, `.crt`):
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
openssl x509 -noout -fingerprint -sha256 -inform pem -in /path/to/cert.pem
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Example output:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
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
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### Method 3 — Using the Built-in CLI Tool
|
|
105
|
+
|
|
106
|
+
This project includes a CLI utility that can retrieve and display
|
|
107
|
+
SSL certificate information for one or more domains.
|
|
108
|
+
|
|
109
|
+
The CLI is intended as a **development and configuration helper**.
|
|
110
|
+
It **does not perform SSL pinning** and does **not enforce trust decisions**
|
|
111
|
+
at runtime.
|
|
112
|
+
|
|
113
|
+
Its purpose is to:
|
|
114
|
+
|
|
115
|
+
- inspect server certificates
|
|
116
|
+
- extract SHA-256 fingerprints
|
|
117
|
+
- assist in preparing configuration values for the runtime plugin
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
#### Installation & Usage
|
|
122
|
+
|
|
123
|
+
You don't need to install the tool globally. You can run it directly using your package manager if the plugin is installed in your project.
|
|
124
|
+
|
|
125
|
+
**Using pnpm (Recommended):**
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pnpm exec ssl-fingerprint example.com
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Using npx:**
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npx ssl-fingerprint example.com
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
If you prefer a global installation:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm install -g @cap-kit/ssl-pinning
|
|
141
|
+
# or
|
|
142
|
+
yarn global add @cap-kit/ssl-pinning
|
|
143
|
+
# then run:
|
|
144
|
+
ssl-fingerprint example.com
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
#### Usage
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Using npx
|
|
153
|
+
npx ssl-fingerprint example.com
|
|
154
|
+
|
|
155
|
+
# Multiple domains
|
|
156
|
+
npx ssl-fingerprint example.com example.org example.net
|
|
157
|
+
|
|
158
|
+
# If installed globally
|
|
159
|
+
ssl-fingerprint example.com
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
#### Modes
|
|
165
|
+
|
|
166
|
+
The `--mode` flag controls how fingerprints are organized:
|
|
167
|
+
|
|
168
|
+
- `--mode single`
|
|
169
|
+
Generates a single `fingerprint` value.
|
|
170
|
+
|
|
171
|
+
- `--mode multi`
|
|
172
|
+
Generates a `fingerprints[]` array (useful for certificate rotation).
|
|
173
|
+
|
|
174
|
+
Example:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx ssl-fingerprint example.com api.example.com --mode multi
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
You can also save the output to a file:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
ssl-fingerprint example.com --out certs.json
|
|
186
|
+
ssl-fingerprint example.com example.org example.net --out certs.json
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Generate output in TypeScript format (useful for configuration files):
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
ssl-fingerprint example.com --out fingerprints.ts --format fingerprints
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
#### Formats
|
|
198
|
+
|
|
199
|
+
The `--format` flag controls the output structure:
|
|
200
|
+
|
|
201
|
+
- `json`
|
|
202
|
+
Raw certificate information (default)
|
|
203
|
+
|
|
204
|
+
- `fingerprints`
|
|
205
|
+
TypeScript array of fingerprints
|
|
206
|
+
|
|
207
|
+
- `capacitor`
|
|
208
|
+
Full `plugins` block for `capacitor.config.ts`
|
|
209
|
+
|
|
210
|
+
- `capacitor-plugin`
|
|
211
|
+
Only the `SSLPinning` plugin block
|
|
212
|
+
|
|
213
|
+
- `capacitor-json`
|
|
214
|
+
JSON equivalent of the Capacitor configuration
|
|
215
|
+
|
|
216
|
+
Example:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
npx ssl-fingerprint example.com \
|
|
220
|
+
--mode multi \
|
|
221
|
+
--format capacitor
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Output:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
plugins: {
|
|
228
|
+
SSLPinning: {
|
|
229
|
+
fingerprints: ['AA:BB:CC:DD:...', '11:22:33:44:...'];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
#### Notes
|
|
237
|
+
|
|
238
|
+
- Fingerprints are normalized internally by the runtime plugin.
|
|
239
|
+
- Uppercase/lowercase differences are ignored.
|
|
240
|
+
- Colons (`:`) are optional.
|
|
241
|
+
|
|
242
|
+
The CLI **generates configuration**.
|
|
243
|
+
The runtime plugin **consumes it**.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### Important
|
|
248
|
+
|
|
249
|
+
SSL pinning requires **active maintenance**.
|
|
250
|
+
|
|
251
|
+
If a certificate expires or is rotated and the fingerprint is not updated,
|
|
252
|
+
network requests will fail until the configuration is corrected.
|
|
253
|
+
|
|
254
|
+
Always verify fingerprints in a controlled environment before releasing
|
|
255
|
+
to production.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Configuration
|
|
260
|
+
|
|
261
|
+
The plugin supports static configuration via `capacitor.config.ts`.
|
|
262
|
+
Configuration values are read **natively at runtime** and are not accessed from JavaScript.
|
|
263
|
+
|
|
264
|
+
<docgen-config>
|
|
265
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
266
|
+
|
|
267
|
+
Configuration options for the SSLPinning plugin.
|
|
268
|
+
|
|
269
|
+
| Prop | Type | Description | Default | Since |
|
|
270
|
+
| -------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ------ |
|
|
271
|
+
| **`verboseLogging`** | <code>boolean</code> | Enables detailed logging in the native console (Logcat/Xcode). Useful for debugging sensor data flow and lifecycle events. | <code>false</code> | 0.0.15 |
|
|
272
|
+
| **`fingerprint`** | <code>string</code> | Default fingerprint used by checkCertificate() if no arguments are provided. | <code>undefined</code> | 0.0.14 |
|
|
273
|
+
| **`fingerprints`** | <code>string[]</code> | Default fingerprints used by checkCertificates() if no arguments are provided. | <code>undefined</code> | 0.0.15 |
|
|
274
|
+
|
|
275
|
+
### Examples
|
|
276
|
+
|
|
277
|
+
In `capacitor.config.json`:
|
|
278
|
+
|
|
279
|
+
```json
|
|
280
|
+
{
|
|
281
|
+
"plugins": {
|
|
282
|
+
"SSLPinning": {
|
|
283
|
+
"verboseLogging": true,
|
|
284
|
+
"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",
|
|
285
|
+
"fingerprints": [
|
|
286
|
+
"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"
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
In `capacitor.config.ts`:
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
/// <reference types="@cap-kit/ssl-pinning" />
|
|
297
|
+
|
|
298
|
+
import { CapacitorConfig } from '@capacitor/cli';
|
|
299
|
+
|
|
300
|
+
const config: CapacitorConfig = {
|
|
301
|
+
plugins: {
|
|
302
|
+
SSLPinning: {
|
|
303
|
+
verboseLogging: true,
|
|
304
|
+
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',
|
|
305
|
+
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"],
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
export default config;
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
</docgen-config>
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 🔐 Pinning Mode (Runtime Behavior)
|
|
318
|
+
|
|
319
|
+
This version of the plugin supports **fingerprint-based SSL pinning only**.
|
|
320
|
+
|
|
321
|
+
### How it works
|
|
322
|
+
|
|
323
|
+
At runtime, the plugin:
|
|
324
|
+
|
|
325
|
+
1. Opens a TLS connection to the target HTTPS endpoint
|
|
326
|
+
2. Extracts the **leaf SSL certificate** presented by the server
|
|
327
|
+
3. Computes its **SHA-256 fingerprint**
|
|
328
|
+
4. Compares it against the expected fingerprint(s)
|
|
329
|
+
|
|
330
|
+
The certificate is considered trusted if **any fingerprint matches**.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### Supported pinning modes
|
|
335
|
+
|
|
336
|
+
| Mode | Supported |
|
|
337
|
+
| ------------------- | --------- |
|
|
338
|
+
| Fingerprint pinning | ✅ Yes |
|
|
339
|
+
| Certificate pinning | ❌ No |
|
|
340
|
+
| Excluded domains | ❌ No |
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## 🛡️ Security Model
|
|
345
|
+
|
|
346
|
+
This plugin mitigates **man-in-the-middle (MITM) attacks**
|
|
347
|
+
by enforcing explicit trust decisions at the TLS layer
|
|
348
|
+
using certificate fingerprint validation.
|
|
349
|
+
|
|
350
|
+
### Security guarantees
|
|
351
|
+
|
|
352
|
+
When correctly configured:
|
|
353
|
+
|
|
354
|
+
- The connection is accepted **only if** the server certificate
|
|
355
|
+
fingerprint matches one of the expected values.
|
|
356
|
+
- Trust decisions are performed **natively at runtime**,
|
|
357
|
+
outside of JavaScript control.
|
|
358
|
+
- Certificate validation fails **closed** by default.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### Limitations
|
|
363
|
+
|
|
364
|
+
This plugin intentionally:
|
|
365
|
+
|
|
366
|
+
- Validates **only the leaf certificate**
|
|
367
|
+
- Does **not** evaluate the full trust chain
|
|
368
|
+
- Does **not** check certificate revocation (CRL / OCSP)
|
|
369
|
+
- Does **not** protect against compromised application binaries
|
|
370
|
+
|
|
371
|
+
It is a **defense-in-depth control** and must be combined
|
|
372
|
+
with proper TLS configuration and backend security practices.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### Operational requirements
|
|
377
|
+
|
|
378
|
+
Applications using this plugin must:
|
|
379
|
+
|
|
380
|
+
- Monitor certificate expiration dates
|
|
381
|
+
- Update fingerprints **before certificate rotation**
|
|
382
|
+
- Test pinning behavior before production releases
|
|
383
|
+
|
|
384
|
+
Incorrect configuration may result in **loss of connectivity** by design.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### Priority rules
|
|
389
|
+
|
|
390
|
+
Fingerprint values are selected in the following order:
|
|
391
|
+
|
|
392
|
+
1. Fingerprints passed at runtime (`checkCertificate` / `checkCertificates`)
|
|
393
|
+
2. Fingerprints defined in `capacitor.config.ts`
|
|
394
|
+
|
|
395
|
+
If no fingerprints are available, the operation fails.
|
|
396
|
+
|
|
397
|
+
There is **no automatic fallback**.
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 🔧 Error Handling Model (Important)
|
|
402
|
+
|
|
403
|
+
> ⚠️ **Read this before using `checkCertificate()` or `checkCertificates()`**
|
|
404
|
+
|
|
405
|
+
This plugin uses a **state-based error model**, not exception-based errors.
|
|
406
|
+
|
|
407
|
+
### Why?
|
|
408
|
+
|
|
409
|
+
- On **iOS (Capacitor 8 + Swift Package Manager)**, native Promise rejection
|
|
410
|
+
is not reliably available.
|
|
411
|
+
- To guarantee **cross-platform consistency**, the plugin always
|
|
412
|
+
**resolves Promises** and returns an explicit result object.
|
|
413
|
+
|
|
414
|
+
### What this means
|
|
415
|
+
|
|
416
|
+
- Promises are **never rejected** by the plugin.
|
|
417
|
+
This behavior applies to **all platforms** to ensure API consistency.
|
|
418
|
+
- Errors are reported as part of the resolved result.
|
|
419
|
+
- Consumers must **always inspect the returned object**, not rely on `catch()`.
|
|
420
|
+
|
|
421
|
+
### Error fields
|
|
422
|
+
|
|
423
|
+
When an error occurs, the result object may include:
|
|
424
|
+
|
|
425
|
+
- `fingerprintMatched: false`
|
|
426
|
+
- `error`: a human-readable diagnostic message
|
|
427
|
+
- `errorCode`: a standardized error identifier
|
|
428
|
+
|
|
429
|
+
Example:
|
|
430
|
+
|
|
431
|
+
```ts
|
|
432
|
+
const result = await SSLPinning.checkCertificate();
|
|
433
|
+
|
|
434
|
+
if (!result.fingerprintMatched) {
|
|
435
|
+
console.error(result.error, result.errorCode);
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Standardized error codes
|
|
440
|
+
|
|
441
|
+
The `errorCode` field (when present) is one of the following:
|
|
442
|
+
|
|
443
|
+
- `UNAVAILABLE` – the feature is not available at runtime
|
|
444
|
+
- `PERMISSION_DENIED` – access was denied by the system or configuration
|
|
445
|
+
- `INIT_FAILED` – initialization or runtime failure occurred
|
|
446
|
+
- `UNKNOWN_TYPE` – unsupported or invalid pinning configuration
|
|
447
|
+
|
|
448
|
+
These codes are intended for **programmatic handling**, not for user-facing messages.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## API
|
|
453
|
+
|
|
454
|
+
<docgen-index>
|
|
455
|
+
|
|
456
|
+
* [`checkCertificate()`](#checkcertificate)
|
|
457
|
+
* [`checkCertificate(...)`](#checkcertificate)
|
|
458
|
+
* [`checkCertificates()`](#checkcertificates)
|
|
459
|
+
* [`checkCertificates(...)`](#checkcertificates)
|
|
460
|
+
* [`getPluginVersion()`](#getpluginversion)
|
|
461
|
+
* [Interfaces](#interfaces)
|
|
462
|
+
|
|
463
|
+
</docgen-index>
|
|
464
|
+
|
|
465
|
+
<docgen-api>
|
|
466
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
467
|
+
|
|
468
|
+
Interface defining the structure of an SSL Certificate Checker Plugin.
|
|
469
|
+
|
|
470
|
+
Implementations of this interface should provide the logic for checking
|
|
471
|
+
the status and details of an SSL certificate based on the provided options.
|
|
472
|
+
|
|
473
|
+
### checkCertificate()
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
checkCertificate() => Promise<SSLPinningResult>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
Check the SSL certificate of a server.
|
|
480
|
+
|
|
481
|
+
**Returns:** <code>Promise<<a href="#sslpinningresult">SSLPinningResult</a>></code>
|
|
482
|
+
|
|
483
|
+
**Since:** 0.0.14
|
|
484
|
+
|
|
485
|
+
#### Example
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
489
|
+
|
|
490
|
+
const result = await SSLPinning.checkCertificate({
|
|
491
|
+
url: 'https://example.com',
|
|
492
|
+
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'
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
console.log('SSL Pinning Result:', result);
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
--------------------
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
### checkCertificate(...)
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
checkCertificate(options: SSLPinningOptions) => Promise<SSLPinningResult>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
Check the SSL certificate of a server.
|
|
508
|
+
|
|
509
|
+
| Param | Type | Description |
|
|
510
|
+
| ------------- | --------------------------------------------------------------- | ------------------------------------------- |
|
|
511
|
+
| **`options`** | <code><a href="#sslpinningoptions">SSLPinningOptions</a></code> | - Options for checking the SSL certificate. |
|
|
512
|
+
|
|
513
|
+
**Returns:** <code>Promise<<a href="#sslpinningresult">SSLPinningResult</a>></code>
|
|
514
|
+
|
|
515
|
+
**Since:** 0.0.14
|
|
516
|
+
|
|
517
|
+
#### Example
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
521
|
+
|
|
522
|
+
const result = await SSLPinning.checkCertificate({
|
|
523
|
+
url: 'https://example.com',
|
|
524
|
+
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'
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
console.log('SSL Pinning Result:', result);
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
--------------------
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
### checkCertificates()
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
checkCertificates() => Promise<SSLPinningResult[]>
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Check the SSL certificates of multiple servers.
|
|
540
|
+
|
|
541
|
+
**Returns:** <code>Promise<SSLPinningResult[]></code>
|
|
542
|
+
|
|
543
|
+
**Since:** 0.0.15
|
|
544
|
+
|
|
545
|
+
#### Example
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
549
|
+
|
|
550
|
+
const results = await SSLPinning.checkCertificates();
|
|
551
|
+
|
|
552
|
+
results.forEach(result => {
|
|
553
|
+
console.log('SSL Pinning Result:', result);
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
--------------------
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
### checkCertificates(...)
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
checkCertificates(options: SSLPinningMultiOptions[]) => Promise<SSLPinningResult[]>
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
Check the SSL certificates of multiple servers.
|
|
567
|
+
|
|
568
|
+
| Param | Type | Description |
|
|
569
|
+
| ------------- | ------------------------------------- | -------------------------------------------- |
|
|
570
|
+
| **`options`** | <code>SSLPinningMultiOptions[]</code> | - Options for checking the SSL certificates. |
|
|
571
|
+
|
|
572
|
+
**Returns:** <code>Promise<SSLPinningResult[]></code>
|
|
573
|
+
|
|
574
|
+
**Since:** 0.0.15
|
|
575
|
+
|
|
576
|
+
#### Example
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
580
|
+
|
|
581
|
+
const results = await SSLPinning.checkCertificates([
|
|
582
|
+
{
|
|
583
|
+
url: 'https://example.com',
|
|
584
|
+
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']
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
url: 'https://another-example.com',
|
|
588
|
+
fingerprints: ['AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90']
|
|
589
|
+
}
|
|
590
|
+
]);
|
|
591
|
+
|
|
592
|
+
results.forEach(result => {
|
|
593
|
+
console.log('SSL Pinning Result:', result);
|
|
594
|
+
});
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
--------------------
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
### getPluginVersion()
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
getPluginVersion() => Promise<PluginVersionResult>
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
Returns the native plugin version.
|
|
607
|
+
|
|
608
|
+
The returned version corresponds to the native implementation
|
|
609
|
+
bundled with the application.
|
|
610
|
+
|
|
611
|
+
**Returns:** <code>Promise<<a href="#pluginversionresult">PluginVersionResult</a>></code>
|
|
612
|
+
|
|
613
|
+
**Since:** 0.0.15
|
|
614
|
+
|
|
615
|
+
#### Example
|
|
616
|
+
|
|
617
|
+
```ts
|
|
618
|
+
const { version } = await SSLPinning.getPluginVersion();
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
--------------------
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
### Interfaces
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
#### SSLPinningResult
|
|
628
|
+
|
|
629
|
+
Result returned by the SSL certificate check.
|
|
630
|
+
|
|
631
|
+
NOTE:
|
|
632
|
+
On iOS (Swift Package Manager), errors are returned
|
|
633
|
+
as part of the resolved result object rather than
|
|
634
|
+
Promise rejections.
|
|
635
|
+
|
|
636
|
+
| Prop | Type | Description |
|
|
637
|
+
| ------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
638
|
+
| **`subject`** | <code>string</code> | The subject of the certificate, representing the entity the certificate is issued to. |
|
|
639
|
+
| **`issuer`** | <code>string</code> | The issuer of the certificate, indicating the certificate authority that issued it. Results may vary slightly between iOS and Android platforms. |
|
|
640
|
+
| **`validFrom`** | <code>string</code> | The start date from which the certificate is valid. Format: ISO 8601 string or platform-specific date representation. |
|
|
641
|
+
| **`validTo`** | <code>string</code> | The end date until which the certificate is valid. Format: ISO 8601 string or platform-specific date representation. |
|
|
642
|
+
| **`expectedFingerprint`** | <code>string</code> | The fingerprint that is expected to match the certificate's actual fingerprint. This is typically provided in the <a href="#sslpinningoptions">SSLPinningOptions</a>. |
|
|
643
|
+
| **`actualFingerprint`** | <code>string</code> | The actual fingerprint of the SSL certificate retrieved from the server. |
|
|
644
|
+
| **`fingerprintMatched`** | <code>boolean</code> | Indicates whether the actual fingerprint matches the expected fingerprint. `true` if they match, `false` otherwise. |
|
|
645
|
+
| **`error`** | <code>string</code> | A descriptive error message if an issue occurred during the SSL certificate check. |
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
#### SSLPinningOptions
|
|
649
|
+
|
|
650
|
+
Options for checking a single SSL certificate.
|
|
651
|
+
|
|
652
|
+
| Prop | Type | Description |
|
|
653
|
+
| ----------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
654
|
+
| **`url`** | <code>string</code> | The URL of the server whose SSL certificate needs to be checked. |
|
|
655
|
+
| **`fingerprint`** | <code>string</code> | The expected fingerprint of the SSL certificate to validate against. This is typically a hash string such as SHA-256. |
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
#### SSLPinningMultiOptions
|
|
659
|
+
|
|
660
|
+
Options for checking multiple SSL certificates.
|
|
661
|
+
|
|
662
|
+
| Prop | Type | Description |
|
|
663
|
+
| ------------------ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
664
|
+
| **`url`** | <code>string</code> | The URL of the server whose SSL certificate needs to be checked. |
|
|
665
|
+
| **`fingerprints`** | <code>string[]</code> | The expected fingerprints of the SSL certificate to validate against. This is typically an array of hash strings such as SHA-256. |
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
#### PluginVersionResult
|
|
669
|
+
|
|
670
|
+
Result returned by the getPluginVersion method.
|
|
671
|
+
|
|
672
|
+
| Prop | Type | Description |
|
|
673
|
+
| ------------- | ------------------- | ---------------------------------------- |
|
|
674
|
+
| **`version`** | <code>string</code> | The native version string of the plugin. |
|
|
675
|
+
|
|
676
|
+
</docgen-api>
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
## Usage
|
|
681
|
+
|
|
682
|
+
### Single fingerprint
|
|
683
|
+
|
|
684
|
+
```ts
|
|
685
|
+
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
686
|
+
|
|
687
|
+
const result = await SSLPinning.checkCertificate({
|
|
688
|
+
url: 'https://example.com',
|
|
689
|
+
fingerprint: 'AA:BB:CC:DD:...',
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
if (result.fingerprintMatched) {
|
|
693
|
+
// Certificate is trusted
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
### Multiple fingerprints
|
|
698
|
+
|
|
699
|
+
```ts
|
|
700
|
+
const result = await SSLPinning.checkCertificates({
|
|
701
|
+
url: 'https://example.com',
|
|
702
|
+
fingerprints: ['AA:BB:CC:DD:...', '11:22:33:44:...'],
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
if (result.fingerprintMatched) {
|
|
706
|
+
// At least one fingerprint matched
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
When no fingerprints are passed at runtime, the plugin will use the values
|
|
711
|
+
defined in `capacitor.config.ts`.
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## Security Notes
|
|
716
|
+
|
|
717
|
+
- SSL pinning **requires maintenance**. Expired or rotated certificates
|
|
718
|
+
must be updated before they become invalid.
|
|
719
|
+
- Incorrect configuration can result in **loss of connectivity**.
|
|
720
|
+
- SSL pinning may interfere with debugging tools and traffic inspection.
|
|
721
|
+
- This plugin is provided **as-is**, without warranty.
|
|
722
|
+
|
|
723
|
+
Always test thoroughly in your target environment.
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
## Contributing
|
|
728
|
+
|
|
729
|
+
Contributions are welcome.
|
|
730
|
+
|
|
731
|
+
Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file before submitting
|
|
732
|
+
a pull request.
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## Credits
|
|
737
|
+
|
|
738
|
+
This plugin is based on prior work from the Community and
|
|
739
|
+
has been refactored and modernized for **Capacitor v8** and
|
|
740
|
+
**Swift Package Manager** compatibility.
|
|
741
|
+
|
|
742
|
+
Original inspiration:
|
|
743
|
+
|
|
744
|
+
- [https://github.com/mchl18/Capacitor-SSL-Pinning](https://github.com/mchl18/Capacitor-SSL-Pinning)
|
|
745
|
+
|
|
746
|
+
---
|
|
747
|
+
|
|
748
|
+
## License
|
|
749
|
+
|
|
750
|
+
MIT
|