@cap-kit/ssl-pinning 8.0.0-next.0 → 8.0.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/Package.swift +1 -1
- package/README.md +232 -372
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningConfig.kt +48 -3
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningError.kt +40 -0
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningImpl.kt +137 -90
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningPlugin.kt +146 -29
- package/android/src/main/java/io/capkit/sslpinning/utils/SSLPinningLogger.kt +30 -38
- package/android/src/main/java/io/capkit/sslpinning/utils/SSLPinningUtils.kt +25 -9
- package/dist/docs.json +29 -204
- package/dist/esm/definitions.d.ts +74 -177
- package/dist/esm/definitions.js +12 -6
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +9 -22
- package/dist/esm/web.js +5 -5
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +17 -11
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +17 -11
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/SSLPinningPlugin/SSLPinningConfig.swift +45 -30
- package/ios/Sources/SSLPinningPlugin/SSLPinningDelegate.swift +83 -26
- package/ios/Sources/SSLPinningPlugin/SSLPinningError.swift +49 -0
- package/ios/Sources/SSLPinningPlugin/SSLPinningImpl.swift +94 -64
- package/ios/Sources/SSLPinningPlugin/SSLPinningPlugin.swift +121 -50
- package/ios/Sources/SSLPinningPlugin/Utils/SSLPinningLogger.swift +28 -16
- package/ios/Sources/SSLPinningPlugin/Utils/SSLPinningUtils.swift +55 -18
- package/ios/Sources/SSLPinningPlugin/Version.swift +2 -2
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -34,18 +34,61 @@
|
|
|
34
34
|
## Overview
|
|
35
35
|
|
|
36
36
|
`@cap-kit/ssl-pinning` is a Capacitor plugin that performs **runtime SSL certificate
|
|
37
|
-
verification**
|
|
37
|
+
fingerprint verification** on **iOS and Android** by validating the
|
|
38
|
+
**SHA-256 fingerprint** of a server certificate during the TLS handshake.
|
|
38
39
|
|
|
39
|
-
The plugin
|
|
40
|
+
The plugin is designed to:
|
|
40
41
|
|
|
41
|
-
- validate a single fingerprint
|
|
42
|
-
- validate multiple fingerprints
|
|
42
|
+
- validate a single fingerprint using `checkCertificate`
|
|
43
|
+
- validate multiple fingerprints using `checkCertificates`
|
|
43
44
|
- support configuration-based defaults via `capacitor.config.ts`
|
|
44
45
|
- keep the JavaScript API platform-agnostic and stable
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
By enforcing explicit trust decisions, SSL pinning helps protect against
|
|
48
|
+
**man-in-the-middle attacks**.
|
|
49
|
+
|
|
50
|
+
This plugin performs **certificate pinning only**.
|
|
51
|
+
It does **not** expose full X.509 certificate inspection APIs at runtime,
|
|
52
|
+
does **not replace TLS**, and does **not guarantee absolute security**.
|
|
53
|
+
|
|
54
|
+
SSL pinning is a **defense-in-depth mechanism** and must be maintained correctly
|
|
55
|
+
over time.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Platform Support
|
|
60
|
+
|
|
61
|
+
| Platform | Supported |
|
|
62
|
+
| -------- | --------- |
|
|
63
|
+
| iOS | ✅ |
|
|
64
|
+
| Android | ✅ |
|
|
65
|
+
| Web | ❌ |
|
|
66
|
+
|
|
67
|
+
On the Web, SSL certificate inspection is not possible due to browser security
|
|
68
|
+
restrictions. All methods will reject with an `Unimplemented` error.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Future Directions (Informational)
|
|
73
|
+
|
|
74
|
+
In addition to runtime fingerprint-based SSL pinning, the long-term vision
|
|
75
|
+
for this plugin includes exploring additional trust models and configuration
|
|
76
|
+
strategies.
|
|
77
|
+
|
|
78
|
+
Potential future enhancements may include:
|
|
79
|
+
|
|
80
|
+
- **Loading trusted certificates from the application bundle**, for example
|
|
81
|
+
from a dedicated `certs/` directory, allowing certificate-based pinning
|
|
82
|
+
without hardcoding fingerprints.
|
|
83
|
+
- **Domain-based exclusions**, enabling developers to explicitly bypass
|
|
84
|
+
SSL pinning for selected hosts (e.g. analytics, third-party services, or
|
|
85
|
+
development environments).
|
|
86
|
+
|
|
87
|
+
These ideas are provided for informational purposes only.
|
|
88
|
+
|
|
89
|
+
They are **not part of the current API**, **not guaranteed to be implemented**,
|
|
90
|
+
and **may change or be discarded** based on platform constraints, security
|
|
91
|
+
considerations, and real-world usage feedback.
|
|
49
92
|
|
|
50
93
|
---
|
|
51
94
|
|
|
@@ -68,8 +111,11 @@ npx cap sync
|
|
|
68
111
|
To use SSL pinning, you must obtain the **SHA-256 fingerprint**
|
|
69
112
|
of the SSL certificate you intend to trust.
|
|
70
113
|
|
|
71
|
-
|
|
72
|
-
|
|
114
|
+
A fingerprint is a cryptographic hash of the server certificate and is used
|
|
115
|
+
to uniquely identify it during the TLS handshake.
|
|
116
|
+
|
|
117
|
+
Fingerprints can be obtained using **standard tools** or via the
|
|
118
|
+
**built-in CLI utility provided by this project**.
|
|
73
119
|
|
|
74
120
|
---
|
|
75
121
|
|
|
@@ -78,14 +124,14 @@ companion CLI utility provided by this project.
|
|
|
78
124
|
1. Open the target website in a modern browser.
|
|
79
125
|
2. View the website certificate details.
|
|
80
126
|
3. Export or copy the certificate (public key).
|
|
81
|
-
4. Use
|
|
127
|
+
4. Use a fingerprint generator, for example:
|
|
82
128
|
https://www.samltool.com/fingerprint.php
|
|
83
129
|
5. Select **SHA-256** as the algorithm.
|
|
84
|
-
6. Copy the resulting fingerprint
|
|
130
|
+
6. Copy the resulting fingerprint.
|
|
85
131
|
|
|
86
132
|
---
|
|
87
133
|
|
|
88
|
-
### Method 2 — Using
|
|
134
|
+
### Method 2 — Using OpenSSL
|
|
89
135
|
|
|
90
136
|
If you have access to the certificate file (`.pem`, `.cer`, `.crt`):
|
|
91
137
|
|
|
@@ -103,12 +149,11 @@ SHA256 Fingerprint=EF:BA:26:D8:C1:CE:37:79:AC:77:63:0A:90:F8:21:63:A3:D6:89:2E:D
|
|
|
103
149
|
|
|
104
150
|
### Method 3 — Using the Built-in CLI Tool
|
|
105
151
|
|
|
106
|
-
This project includes a
|
|
107
|
-
SSL
|
|
152
|
+
This project includes a **command-line utility** that can retrieve
|
|
153
|
+
SSL certificates from remote servers and generate SHA-256 fingerprints.
|
|
108
154
|
|
|
109
|
-
The CLI is intended
|
|
110
|
-
It **does not perform SSL pinning** and does **not
|
|
111
|
-
at runtime.
|
|
155
|
+
The CLI is intended to be used **at development time**.
|
|
156
|
+
It **does not perform SSL pinning** and does **not make trust decisions at runtime**.
|
|
112
157
|
|
|
113
158
|
Its purpose is to:
|
|
114
159
|
|
|
@@ -116,107 +161,62 @@ Its purpose is to:
|
|
|
116
161
|
- extract SHA-256 fingerprints
|
|
117
162
|
- assist in preparing configuration values for the runtime plugin
|
|
118
163
|
|
|
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
|
-
```
|
|
164
|
+
#### Basic usage
|
|
130
165
|
|
|
131
|
-
|
|
166
|
+
> Note
|
|
167
|
+
> The CLI is exposed via the `cap-kit-ssl-pinning` command.
|
|
168
|
+
> Any internal script names shown in the help output (e.g. `fingerprint.js`)
|
|
169
|
+
> are implementation details and should not be invoked directly.
|
|
132
170
|
|
|
133
171
|
```bash
|
|
134
|
-
npx ssl-
|
|
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
|
|
172
|
+
npx cap-kit-ssl-pinning example.com
|
|
145
173
|
```
|
|
146
174
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
#### Usage
|
|
175
|
+
#### Multiple domains
|
|
150
176
|
|
|
151
177
|
```bash
|
|
152
|
-
|
|
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
|
|
178
|
+
npx cap-kit-ssl-pinning example.com api.example.com
|
|
160
179
|
```
|
|
161
180
|
|
|
162
|
-
---
|
|
163
|
-
|
|
164
181
|
#### Modes
|
|
165
182
|
|
|
166
|
-
The `--mode` flag controls how fingerprints are
|
|
183
|
+
The `--mode` flag controls how fingerprints are grouped:
|
|
167
184
|
|
|
168
|
-
-
|
|
185
|
+
- `single`
|
|
169
186
|
Generates a single `fingerprint` value.
|
|
170
187
|
|
|
171
|
-
-
|
|
188
|
+
- `multi`
|
|
172
189
|
Generates a `fingerprints[]` array (useful for certificate rotation).
|
|
173
190
|
|
|
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
191
|
```bash
|
|
185
|
-
ssl-
|
|
186
|
-
ssl-fingerprint example.com example.org example.net --out certs.json
|
|
192
|
+
npx cap-kit-ssl-pinning example.com api.example.com --mode multi
|
|
187
193
|
```
|
|
188
194
|
|
|
189
|
-
|
|
195
|
+
> ⚠️ Note
|
|
196
|
+
>
|
|
197
|
+
> When using `--mode multi` with multiple domains, each domain is processed independently.
|
|
198
|
+
>
|
|
199
|
+
> If a certificate cannot be retrieved for a specific domain (e.g. DNS error or TLS failure),
|
|
200
|
+
> the error is reported in the output, but the CLI continues processing the remaining domains.
|
|
201
|
+
>
|
|
202
|
+
> The resulting `fingerprints` array will include **only successfully retrieved certificates**.
|
|
190
203
|
|
|
191
|
-
|
|
192
|
-
ssl-fingerprint example.com --out fingerprints.ts --format fingerprints
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
#### Formats
|
|
204
|
+
#### Output formats
|
|
198
205
|
|
|
199
206
|
The `--format` flag controls the output structure:
|
|
200
207
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
|
208
|
+
| Format | Description |
|
|
209
|
+
| ------------------ | ---------------------------------------------- |
|
|
210
|
+
| `json` | Full certificate information (default) |
|
|
211
|
+
| `fingerprints` | JavaScript array of fingerprints |
|
|
212
|
+
| `capacitor` | Full `plugins` block for `capacitor.config.ts` |
|
|
213
|
+
| `capacitor-plugin` | `SSLPinning` config block only |
|
|
214
|
+
| `capacitor-json` | JSON-compatible Capacitor configuration |
|
|
215
215
|
|
|
216
216
|
Example:
|
|
217
217
|
|
|
218
218
|
```bash
|
|
219
|
-
npx ssl-
|
|
219
|
+
npx cap-kit-ssl-pinning example.com \
|
|
220
220
|
--mode multi \
|
|
221
221
|
--format capacitor
|
|
222
222
|
```
|
|
@@ -231,13 +231,40 @@ plugins: {
|
|
|
231
231
|
}
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
+
Example (plugin block only):
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
npx cap-kit-ssl-pinning example.com api.example.com \
|
|
238
|
+
--mode multi \
|
|
239
|
+
--format capacitor-plugin
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Output:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
SSLPinning: {
|
|
246
|
+
fingerprints: ['AA:BB:CC:DD:...', '11:22:33:44:...'];
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Insecure mode
|
|
251
|
+
|
|
252
|
+
By default, the CLI allows retrieving certificates even if the TLS
|
|
253
|
+
chain is invalid.
|
|
254
|
+
|
|
255
|
+
To enforce certificate validation:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
npx cap-kit-ssl-pinning example.com --insecure=false
|
|
259
|
+
```
|
|
260
|
+
|
|
234
261
|
---
|
|
235
262
|
|
|
236
|
-
|
|
263
|
+
### Notes
|
|
237
264
|
|
|
238
265
|
- Fingerprints are normalized internally by the runtime plugin.
|
|
239
266
|
- Uppercase/lowercase differences are ignored.
|
|
240
|
-
-
|
|
267
|
+
- Colon separators (`:`) are optional.
|
|
241
268
|
|
|
242
269
|
The CLI **generates configuration**.
|
|
243
270
|
The runtime plugin **consumes it**.
|
|
@@ -258,19 +285,25 @@ to production.
|
|
|
258
285
|
|
|
259
286
|
## Configuration
|
|
260
287
|
|
|
261
|
-
|
|
262
|
-
|
|
288
|
+
Static configuration can be provided in `capacitor.config.ts` under
|
|
289
|
+
`plugins.SSLPinning`.
|
|
290
|
+
|
|
291
|
+
These values are:
|
|
292
|
+
|
|
293
|
+
- read natively at build/runtime
|
|
294
|
+
- not accessible from JavaScript at runtime
|
|
295
|
+
- treated as read-only fallback configuration
|
|
263
296
|
|
|
264
297
|
<docgen-config>
|
|
265
298
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
266
299
|
|
|
267
300
|
Configuration options for the SSLPinning plugin.
|
|
268
301
|
|
|
269
|
-
| Prop | Type | Description
|
|
270
|
-
| -------------------- | --------------------- |
|
|
271
|
-
| **`verboseLogging`** | <code>boolean</code> | Enables
|
|
272
|
-
| **`fingerprint`** | <code>string</code> | Default fingerprint used by checkCertificate()
|
|
273
|
-
| **`fingerprints`** | <code>string[]</code> | Default fingerprints used by checkCertificates()
|
|
302
|
+
| Prop | Type | Description | Default | Since |
|
|
303
|
+
| -------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------ | ------ |
|
|
304
|
+
| **`verboseLogging`** | <code>boolean</code> | Enables verbose native logging (Logcat / Xcode console). | <code>false</code> | 0.0.15 |
|
|
305
|
+
| **`fingerprint`** | <code>string</code> | Default fingerprint used by `checkCertificate()` when `options.fingerprint` is not provided at runtime. | | 0.0.14 |
|
|
306
|
+
| **`fingerprints`** | <code>string[]</code> | Default fingerprints used by `checkCertificates()` when `options.fingerprints` is not provided at runtime. | | 0.0.15 |
|
|
274
307
|
|
|
275
308
|
### Examples
|
|
276
309
|
|
|
@@ -280,7 +313,7 @@ In `capacitor.config.json`:
|
|
|
280
313
|
{
|
|
281
314
|
"plugins": {
|
|
282
315
|
"SSLPinning": {
|
|
283
|
-
"verboseLogging":
|
|
316
|
+
"verboseLogging": false,
|
|
284
317
|
"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
318
|
"fingerprints": [
|
|
286
319
|
"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"
|
|
@@ -300,7 +333,7 @@ import { CapacitorConfig } from '@capacitor/cli';
|
|
|
300
333
|
const config: CapacitorConfig = {
|
|
301
334
|
plugins: {
|
|
302
335
|
SSLPinning: {
|
|
303
|
-
verboseLogging:
|
|
336
|
+
verboseLogging: false,
|
|
304
337
|
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
338
|
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
339
|
},
|
|
@@ -312,140 +345,14 @@ export default config;
|
|
|
312
345
|
|
|
313
346
|
</docgen-config>
|
|
314
347
|
|
|
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)
|
|
348
|
+
### Configuration precedence
|
|
329
349
|
|
|
330
|
-
|
|
350
|
+
For each method call, fingerprint resolution follows this order:
|
|
331
351
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
### Supported pinning modes
|
|
352
|
+
1. Runtime options passed from JavaScript
|
|
353
|
+
2. Static configuration from `capacitor.config.ts`
|
|
335
354
|
|
|
336
|
-
|
|
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.
|
|
355
|
+
If no fingerprint is available from either source, the call will fail.
|
|
449
356
|
|
|
450
357
|
---
|
|
451
358
|
|
|
@@ -453,9 +360,7 @@ These codes are intended for **programmatic handling**, not for user-facing mess
|
|
|
453
360
|
|
|
454
361
|
<docgen-index>
|
|
455
362
|
|
|
456
|
-
* [`checkCertificate()`](#checkcertificate)
|
|
457
363
|
* [`checkCertificate(...)`](#checkcertificate)
|
|
458
|
-
* [`checkCertificates()`](#checkcertificates)
|
|
459
364
|
* [`checkCertificates(...)`](#checkcertificates)
|
|
460
365
|
* [`getPluginVersion()`](#getpluginversion)
|
|
461
366
|
* [Interfaces](#interfaces)
|
|
@@ -465,38 +370,7 @@ These codes are intended for **programmatic handling**, not for user-facing mess
|
|
|
465
370
|
<docgen-api>
|
|
466
371
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
467
372
|
|
|
468
|
-
|
|
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
|
-
|
|
373
|
+
SSL Pinning Capacitor Plugin interface.
|
|
500
374
|
|
|
501
375
|
### checkCertificate(...)
|
|
502
376
|
|
|
@@ -504,96 +378,35 @@ console.log('SSL Pinning Result:', result);
|
|
|
504
378
|
checkCertificate(options: SSLPinningOptions) => Promise<SSLPinningResult>
|
|
505
379
|
```
|
|
506
380
|
|
|
507
|
-
|
|
381
|
+
Checks the SSL certificate of a server using a single fingerprint.
|
|
508
382
|
|
|
509
|
-
| Param | Type |
|
|
510
|
-
| ------------- | --------------------------------------------------------------- |
|
|
511
|
-
| **`options`** | <code><a href="#sslpinningoptions">SSLPinningOptions</a></code> |
|
|
383
|
+
| Param | Type |
|
|
384
|
+
| ------------- | --------------------------------------------------------------- |
|
|
385
|
+
| **`options`** | <code><a href="#sslpinningoptions">SSLPinningOptions</a></code> |
|
|
512
386
|
|
|
513
387
|
**Returns:** <code>Promise<<a href="#sslpinningresult">SSLPinningResult</a>></code>
|
|
514
388
|
|
|
515
389
|
**Since:** 0.0.14
|
|
516
390
|
|
|
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
391
|
--------------------
|
|
558
392
|
|
|
559
393
|
|
|
560
394
|
### checkCertificates(...)
|
|
561
395
|
|
|
562
396
|
```typescript
|
|
563
|
-
checkCertificates(options: SSLPinningMultiOptions
|
|
397
|
+
checkCertificates(options: SSLPinningMultiOptions) => Promise<SSLPinningResult>
|
|
564
398
|
```
|
|
565
399
|
|
|
566
|
-
|
|
400
|
+
Checks the SSL certificate of a server using multiple allowed fingerprints.
|
|
567
401
|
|
|
568
|
-
| Param | Type
|
|
569
|
-
| ------------- |
|
|
570
|
-
| **`options`** | <code>SSLPinningMultiOptions
|
|
402
|
+
| Param | Type |
|
|
403
|
+
| ------------- | ------------------------------------------------------------------------- |
|
|
404
|
+
| **`options`** | <code><a href="#sslpinningmultioptions">SSLPinningMultiOptions</a></code> |
|
|
571
405
|
|
|
572
|
-
**Returns:** <code>Promise<
|
|
406
|
+
**Returns:** <code>Promise<<a href="#sslpinningresult">SSLPinningResult</a>></code>
|
|
573
407
|
|
|
574
408
|
**Since:** 0.0.15
|
|
575
409
|
|
|
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
410
|
--------------------
|
|
598
411
|
|
|
599
412
|
|
|
@@ -626,43 +439,36 @@ const { version } = await SSLPinning.getPluginVersion();
|
|
|
626
439
|
|
|
627
440
|
#### SSLPinningResult
|
|
628
441
|
|
|
629
|
-
Result returned by
|
|
442
|
+
Result returned by a successful SSL certificate check.
|
|
630
443
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
as part of the resolved result object rather than
|
|
634
|
-
Promise rejections.
|
|
444
|
+
This object is returned ONLY on success.
|
|
445
|
+
Failures are delivered via Promise rejection.
|
|
635
446
|
|
|
636
|
-
| Prop
|
|
637
|
-
|
|
|
638
|
-
| **`
|
|
639
|
-
| **`
|
|
640
|
-
| **`
|
|
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. |
|
|
447
|
+
| Prop | Type | Description |
|
|
448
|
+
| ------------------------ | -------------------- | ------------------------------------------------------ |
|
|
449
|
+
| **`actualFingerprint`** | <code>string</code> | Actual SHA-256 fingerprint of the server certificate. |
|
|
450
|
+
| **`fingerprintMatched`** | <code>boolean</code> | Indicates whether the certificate fingerprint matched. |
|
|
451
|
+
| **`matchedFingerprint`** | <code>string</code> | The fingerprint that successfully matched, if any. |
|
|
646
452
|
|
|
647
453
|
|
|
648
454
|
#### SSLPinningOptions
|
|
649
455
|
|
|
650
456
|
Options for checking a single SSL certificate.
|
|
651
457
|
|
|
652
|
-
| Prop | Type | Description
|
|
653
|
-
| ----------------- | ------------------- |
|
|
654
|
-
| **`url`** | <code>string</code> |
|
|
655
|
-
| **`fingerprint`** | <code>string</code> |
|
|
458
|
+
| Prop | Type | Description |
|
|
459
|
+
| ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
460
|
+
| **`url`** | <code>string</code> | HTTPS URL of the server whose SSL certificate must be checked. This value is REQUIRED and cannot be provided via configuration. |
|
|
461
|
+
| **`fingerprint`** | <code>string</code> | Expected SHA-256 fingerprint of the certificate. Resolution order: 1. `options.fingerprint` (runtime) 2. `plugins.SSLPinning.fingerprint` (config) If neither is provided, the Promise is rejected with `SSLPinningErrorCode.UNAVAILABLE`. |
|
|
656
462
|
|
|
657
463
|
|
|
658
464
|
#### SSLPinningMultiOptions
|
|
659
465
|
|
|
660
|
-
Options for checking
|
|
466
|
+
Options for checking an SSL certificate using multiple allowed fingerprints.
|
|
661
467
|
|
|
662
|
-
| Prop | Type | Description
|
|
663
|
-
| ------------------ | --------------------- |
|
|
664
|
-
| **`url`** | <code>string</code> |
|
|
665
|
-
| **`fingerprints`** | <code>string[]</code> |
|
|
468
|
+
| Prop | Type | Description |
|
|
469
|
+
| ------------------ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
470
|
+
| **`url`** | <code>string</code> | HTTPS URL of the server whose SSL certificate must be checked. This value is REQUIRED and cannot be provided via configuration. |
|
|
471
|
+
| **`fingerprints`** | <code>string[]</code> | Expected SHA-256 fingerprints of the certificate. Resolution order: 1. `options.fingerprints` (runtime) 2. `plugins.SSLPinning.fingerprints` (config) If neither is provided, the Promise is rejected with `SSLPinningErrorCode.UNAVAILABLE`. |
|
|
666
472
|
|
|
667
473
|
|
|
668
474
|
#### PluginVersionResult
|
|
@@ -679,7 +485,7 @@ Result returned by the getPluginVersion method.
|
|
|
679
485
|
|
|
680
486
|
## Usage
|
|
681
487
|
|
|
682
|
-
### Single fingerprint
|
|
488
|
+
### Single fingerprint check
|
|
683
489
|
|
|
684
490
|
```ts
|
|
685
491
|
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
@@ -690,34 +496,88 @@ const result = await SSLPinning.checkCertificate({
|
|
|
690
496
|
});
|
|
691
497
|
|
|
692
498
|
if (result.fingerprintMatched) {
|
|
693
|
-
|
|
499
|
+
console.log('Certificate is trusted');
|
|
694
500
|
}
|
|
695
501
|
```
|
|
696
502
|
|
|
697
|
-
### Multiple
|
|
503
|
+
### Multiple fingerprint check
|
|
698
504
|
|
|
699
505
|
```ts
|
|
506
|
+
import { SSLPinning } from '@cap-kit/ssl-pinning';
|
|
507
|
+
|
|
700
508
|
const result = await SSLPinning.checkCertificates({
|
|
701
509
|
url: 'https://example.com',
|
|
702
510
|
fingerprints: ['AA:BB:CC:DD:...', '11:22:33:44:...'],
|
|
703
511
|
});
|
|
704
512
|
|
|
705
513
|
if (result.fingerprintMatched) {
|
|
706
|
-
|
|
514
|
+
console.log('Certificate matched:', result.matchedFingerprint);
|
|
707
515
|
}
|
|
708
516
|
```
|
|
709
517
|
|
|
710
|
-
|
|
711
|
-
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## Result Object
|
|
521
|
+
|
|
522
|
+
On success, the Promise resolves with the following object:
|
|
523
|
+
|
|
524
|
+
```ts
|
|
525
|
+
interface SSLPinningResult {
|
|
526
|
+
actualFingerprint: string;
|
|
527
|
+
fingerprintMatched: boolean;
|
|
528
|
+
matchedFingerprint?: string;
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## Error Handling Model (Important)
|
|
535
|
+
|
|
536
|
+
This plugin uses a **Promise rejection–based error model**.
|
|
537
|
+
|
|
538
|
+
- Successful calls always resolve with `SSLPinningResult`
|
|
539
|
+
- Failures always reject with `CapacitorException`
|
|
540
|
+
- Error codes are exposed via `err.code`
|
|
541
|
+
|
|
542
|
+
### Example
|
|
543
|
+
|
|
544
|
+
```ts
|
|
545
|
+
import { SSLPinning, SSLPinningErrorCode } from '@cap-kit/ssl-pinning';
|
|
546
|
+
|
|
547
|
+
try {
|
|
548
|
+
await SSLPinning.checkCertificate({
|
|
549
|
+
url: 'https://example.com',
|
|
550
|
+
});
|
|
551
|
+
} catch (err: any) {
|
|
552
|
+
if (err.code === SSLPinningErrorCode.UNAVAILABLE) {
|
|
553
|
+
console.error('No fingerprint provided');
|
|
554
|
+
} else {
|
|
555
|
+
console.error('SSL pinning failed', err);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Error codes
|
|
561
|
+
|
|
562
|
+
| Code | Description |
|
|
563
|
+
| ------------------- | ------------------------------------------- |
|
|
564
|
+
| `UNAVAILABLE` | No fingerprint provided (runtime or config) |
|
|
565
|
+
| `PERMISSION_DENIED` | Required permission denied |
|
|
566
|
+
| `INIT_FAILED` | Runtime or initialization failure |
|
|
567
|
+
| `UNKNOWN_TYPE` | Invalid or unsupported input |
|
|
712
568
|
|
|
713
569
|
---
|
|
714
570
|
|
|
715
571
|
## Security Notes
|
|
716
572
|
|
|
717
|
-
-
|
|
718
|
-
|
|
719
|
-
-
|
|
720
|
-
|
|
573
|
+
- Only HTTPS URLs are accepted.
|
|
574
|
+
- The system trust chain is **not** evaluated.
|
|
575
|
+
- Certificate acceptance is based **solely on fingerprint matching**.
|
|
576
|
+
|
|
577
|
+
- SSL pinning **requires ongoing maintenance**.
|
|
578
|
+
Certificates that expire or are rotated **must be updated** before they become invalid.
|
|
579
|
+
- Incorrect configuration may result in **loss of network connectivity**.
|
|
580
|
+
- SSL pinning can interfere with debugging tools and HTTPS traffic inspection.
|
|
721
581
|
- This plugin is provided **as-is**, without warranty.
|
|
722
582
|
|
|
723
583
|
Always test thoroughly in your target environment.
|