@cap-kit/ssl-pinning 8.0.0 → 8.0.2
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/android/build.gradle +8 -10
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningConfig.kt +5 -2
- package/android/src/main/java/io/capkit/sslpinning/SSLPinningError.kt +12 -8
- package/android/src/main/java/io/capkit/sslpinning/utils/SSLPinningUtils.kt +6 -7
- package/ios/Sources/SSLPinningPlugin/SSLPinningImpl.swift +11 -5
- package/ios/Sources/SSLPinningPlugin/SSLPinningPlugin.swift +1 -0
- package/ios/Sources/SSLPinningPlugin/Version.swift +2 -2
- package/package.json +24 -10
- package/scripts/{sync-version.js → sync-version.mjs} +6 -0
- /package/scripts/{chmod.js → chmod.mjs} +0 -0
package/Package.swift
CHANGED
|
@@ -10,7 +10,7 @@ let package = Package(
|
|
|
10
10
|
targets: ["SslPinningPlugin"])
|
|
11
11
|
],
|
|
12
12
|
dependencies: [
|
|
13
|
-
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.1.0")
|
|
14
14
|
],
|
|
15
15
|
targets: [
|
|
16
16
|
.target(
|
package/android/build.gradle
CHANGED
|
@@ -5,13 +5,13 @@ buildscript {
|
|
|
5
5
|
mavenCentral()
|
|
6
6
|
}
|
|
7
7
|
dependencies {
|
|
8
|
-
classpath 'com.android.tools.build:gradle:8.13.
|
|
8
|
+
classpath 'com.android.tools.build:gradle:8.13.2'
|
|
9
9
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
plugins {
|
|
14
|
-
id "org.jlleitschuh.gradle.ktlint" version "
|
|
14
|
+
id "org.jlleitschuh.gradle.ktlint" version "14.0.1" apply false
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
ext {
|
|
@@ -38,8 +38,9 @@ def getPluginVersion() {
|
|
|
38
38
|
}
|
|
39
39
|
} catch (Exception e) {
|
|
40
40
|
// Ignore errors and fallback
|
|
41
|
+
logger.info("Exception", e)
|
|
41
42
|
}
|
|
42
|
-
return "0.0
|
|
43
|
+
return "8.0.0"
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
def pluginVersion = getPluginVersion()
|
|
@@ -48,16 +49,16 @@ android {
|
|
|
48
49
|
namespace = "io.capkit.sslpinning"
|
|
49
50
|
compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion as Integer : 36
|
|
50
51
|
|
|
51
|
-
// AGP 8.0+ disables BuildConfig by default for libraries.
|
|
52
|
+
// AGP 8.0+ disables BuildConfig by default for libraries.
|
|
52
53
|
// We need to enable it to inject the plugin version.
|
|
53
54
|
buildFeatures {
|
|
54
55
|
buildConfig = true
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
defaultConfig {
|
|
58
|
-
minSdkVersion
|
|
59
|
-
targetSdkVersion
|
|
60
|
-
versionCode
|
|
59
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion as Integer : 24
|
|
60
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion as Integer : 36
|
|
61
|
+
versionCode 1
|
|
61
62
|
|
|
62
63
|
// Dynamic versioning (feature enabled)
|
|
63
64
|
versionName = pluginVersion
|
|
@@ -80,9 +81,6 @@ android {
|
|
|
80
81
|
sourceCompatibility = JavaVersion.VERSION_21
|
|
81
82
|
targetCompatibility = JavaVersion.VERSION_21
|
|
82
83
|
}
|
|
83
|
-
kotlinOptions {
|
|
84
|
-
jvmTarget = JavaVersion.VERSION_21
|
|
85
|
-
}
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
repositories {
|
|
@@ -15,7 +15,9 @@ import com.getcapacitor.Plugin
|
|
|
15
15
|
* - Treated as immutable runtime input
|
|
16
16
|
* - Accessible only from native code
|
|
17
17
|
*/
|
|
18
|
-
class SSLPinningConfig(
|
|
18
|
+
class SSLPinningConfig(
|
|
19
|
+
plugin: Plugin,
|
|
20
|
+
) {
|
|
19
21
|
/**
|
|
20
22
|
* Android application context.
|
|
21
23
|
* Exposed for native components that may require it.
|
|
@@ -58,7 +60,8 @@ class SSLPinningConfig(plugin: Plugin) {
|
|
|
58
60
|
|
|
59
61
|
// Multiple fingerprints (optional)
|
|
60
62
|
fingerprints =
|
|
61
|
-
config
|
|
63
|
+
config
|
|
64
|
+
.getArray("fingerprints")
|
|
62
65
|
?.toList()
|
|
63
66
|
?.mapNotNull { it as? String }
|
|
64
67
|
?.filter { it.isNotBlank() }
|
|
@@ -16,25 +16,29 @@ sealed class SSLPinningError(
|
|
|
16
16
|
* Feature or capability is not available
|
|
17
17
|
* due to device or configuration limitations.
|
|
18
18
|
*/
|
|
19
|
-
class Unavailable(
|
|
20
|
-
|
|
19
|
+
class Unavailable(
|
|
20
|
+
message: String,
|
|
21
|
+
) : SSLPinningError(message)
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Required permission was denied or not granted.
|
|
24
25
|
*/
|
|
25
|
-
class PermissionDenied(
|
|
26
|
-
|
|
26
|
+
class PermissionDenied(
|
|
27
|
+
message: String,
|
|
28
|
+
) : SSLPinningError(message)
|
|
27
29
|
|
|
28
30
|
/**
|
|
29
31
|
* Plugin failed to initialize or perform
|
|
30
32
|
* a required operation.
|
|
31
33
|
*/
|
|
32
|
-
class InitFailed(
|
|
33
|
-
|
|
34
|
+
class InitFailed(
|
|
35
|
+
message: String,
|
|
36
|
+
) : SSLPinningError(message)
|
|
34
37
|
|
|
35
38
|
/**
|
|
36
39
|
* Invalid or unsupported input was provided.
|
|
37
40
|
*/
|
|
38
|
-
class UnknownType(
|
|
39
|
-
|
|
41
|
+
class UnknownType(
|
|
42
|
+
message: String,
|
|
43
|
+
) : SSLPinningError(message)
|
|
40
44
|
}
|
|
@@ -19,14 +19,13 @@ object SSLPinningUtils {
|
|
|
19
19
|
* Non-HTTPS URLs are explicitly rejected
|
|
20
20
|
* to prevent insecure usage.
|
|
21
21
|
*/
|
|
22
|
-
fun httpsUrl(value: String): URL?
|
|
23
|
-
|
|
22
|
+
fun httpsUrl(value: String): URL? =
|
|
23
|
+
try {
|
|
24
24
|
val url = URL(value)
|
|
25
25
|
if (url.protocol == "https") url else null
|
|
26
26
|
} catch (_: Exception) {
|
|
27
27
|
null
|
|
28
28
|
}
|
|
29
|
-
}
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* Normalizes a fingerprint string by:
|
|
@@ -36,11 +35,10 @@ object SSLPinningUtils {
|
|
|
36
35
|
* Example:
|
|
37
36
|
* "AA:BB:CC" → "aabbcc"
|
|
38
37
|
*/
|
|
39
|
-
fun normalizeFingerprint(value: String): String
|
|
40
|
-
|
|
38
|
+
fun normalizeFingerprint(value: String): String =
|
|
39
|
+
value
|
|
41
40
|
.replace(":", "")
|
|
42
41
|
.lowercase()
|
|
43
|
-
}
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
44
|
* Computes the SHA-256 fingerprint of an X.509 certificate.
|
|
@@ -50,7 +48,8 @@ object SSLPinningUtils {
|
|
|
50
48
|
*/
|
|
51
49
|
fun sha256Fingerprint(cert: Certificate): String {
|
|
52
50
|
val digest =
|
|
53
|
-
MessageDigest
|
|
51
|
+
MessageDigest
|
|
52
|
+
.getInstance("SHA-256")
|
|
54
53
|
.digest(cert.encoded)
|
|
55
54
|
|
|
56
55
|
return digest.joinToString(separator = ":") {
|
|
@@ -19,10 +19,7 @@ public final class SSLPinningImpl: NSObject {
|
|
|
19
19
|
|
|
20
20
|
// MARK: - Properties
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
Immutable plugin configuration.
|
|
24
|
-
Injected once during plugin initialization.
|
|
25
|
-
*/
|
|
22
|
+
// Properties
|
|
26
23
|
private var config: SSLPinningConfig?
|
|
27
24
|
|
|
28
25
|
// MARK: - Configuration
|
|
@@ -34,9 +31,18 @@ public final class SSLPinningImpl: NSObject {
|
|
|
34
31
|
from the Plugin layer during `load()`.
|
|
35
32
|
*/
|
|
36
33
|
func applyConfig(_ config: SSLPinningConfig) {
|
|
34
|
+
precondition(
|
|
35
|
+
self.config == nil,
|
|
36
|
+
"SSLPinningImpl.applyConfig(_:) must be called exactly once"
|
|
37
|
+
)
|
|
38
|
+
|
|
37
39
|
self.config = config
|
|
38
40
|
SSLPinningLogger.verbose = config.verboseLogging
|
|
39
|
-
|
|
41
|
+
|
|
42
|
+
SSLPinningLogger.debug(
|
|
43
|
+
"Configuration applied. Verbose logging:",
|
|
44
|
+
config.verboseLogging
|
|
45
|
+
)
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
// MARK: - Single fingerprint
|
|
@@ -10,7 +10,7 @@ import Foundation
|
|
|
10
10
|
public enum PluginVersion {
|
|
11
11
|
/**
|
|
12
12
|
The semantic version string of the plugin.
|
|
13
|
-
Value synchronized from package.json: "8.0.
|
|
13
|
+
Value synchronized from package.json: "8.0.2"
|
|
14
14
|
*/
|
|
15
|
-
public static let number = "8.0.
|
|
15
|
+
public static let number = "8.0.2"
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-kit/ssl-pinning",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.2",
|
|
4
4
|
"description": "Capacitor plugin for runtime SSL certificate fingerprint pinning on iOS and Android",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
|
+
"sideEffects": false,
|
|
7
8
|
"engines": {
|
|
8
9
|
"node": ">=24.0.0",
|
|
9
10
|
"pnpm": ">=10.0.0"
|
|
@@ -12,6 +13,14 @@
|
|
|
12
13
|
"module": "dist/esm/index.js",
|
|
13
14
|
"types": "dist/esm/index.d.ts",
|
|
14
15
|
"unpkg": "dist/plugin.js",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/esm/index.d.ts",
|
|
19
|
+
"import": "./dist/esm/index.js",
|
|
20
|
+
"require": "./dist/plugin.cjs.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
15
24
|
"files": [
|
|
16
25
|
"android/src/main/",
|
|
17
26
|
"android/build.gradle",
|
|
@@ -21,10 +30,15 @@
|
|
|
21
30
|
"Package.swift",
|
|
22
31
|
"CapKitSSLPinning.podspec",
|
|
23
32
|
"LICENSE",
|
|
33
|
+
"README.md",
|
|
24
34
|
"bin/",
|
|
25
35
|
"scripts/"
|
|
26
36
|
],
|
|
27
37
|
"author": "CapKit Team",
|
|
38
|
+
"funding": {
|
|
39
|
+
"type": "github",
|
|
40
|
+
"url": "https://github.com/sponsors/cap-kit"
|
|
41
|
+
},
|
|
28
42
|
"license": "MIT",
|
|
29
43
|
"repository": {
|
|
30
44
|
"type": "git",
|
|
@@ -61,16 +75,16 @@
|
|
|
61
75
|
"yargs": "^18.0.0"
|
|
62
76
|
},
|
|
63
77
|
"devDependencies": {
|
|
64
|
-
"@capacitor/android": "^8.0
|
|
65
|
-
"@capacitor/cli": "^8.0
|
|
66
|
-
"@capacitor/core": "^8.0
|
|
78
|
+
"@capacitor/android": "^8.1.0",
|
|
79
|
+
"@capacitor/cli": "^8.1.0",
|
|
80
|
+
"@capacitor/core": "^8.1.0",
|
|
67
81
|
"@capacitor/docgen": "^0.3.1",
|
|
68
|
-
"@capacitor/ios": "^8.0
|
|
82
|
+
"@capacitor/ios": "^8.1.0",
|
|
69
83
|
"@eslint/eslintrc": "^3.3.3",
|
|
70
84
|
"@eslint/js": "^9.39.2",
|
|
71
85
|
"eslint": "^9.39.2",
|
|
72
86
|
"eslint-plugin-import": "^2.32.0",
|
|
73
|
-
"@types/node": "^25.2.
|
|
87
|
+
"@types/node": "^25.2.3",
|
|
74
88
|
"@types/yargs": "^17.0.35",
|
|
75
89
|
"globals": "^17.3.0",
|
|
76
90
|
"prettier": "^3.8.1",
|
|
@@ -79,10 +93,10 @@
|
|
|
79
93
|
"rollup": "^4.57.1",
|
|
80
94
|
"swiftlint": "^2.0.0",
|
|
81
95
|
"typescript": "~5.9.3",
|
|
82
|
-
"typescript-eslint": "^8.
|
|
96
|
+
"typescript-eslint": "^8.55.0"
|
|
83
97
|
},
|
|
84
98
|
"peerDependencies": {
|
|
85
|
-
"@capacitor/core": "^8.0
|
|
99
|
+
"@capacitor/core": "^8.1.0"
|
|
86
100
|
},
|
|
87
101
|
"capacitor": {
|
|
88
102
|
"ios": {
|
|
@@ -94,7 +108,7 @@
|
|
|
94
108
|
},
|
|
95
109
|
"scripts": {
|
|
96
110
|
"verify": "pnpm run verify:ios && pnpm run verify:android && pnpm run verify:web",
|
|
97
|
-
"verify:ios": "node ./scripts/sync-version.
|
|
111
|
+
"verify:ios": "node ./scripts/sync-version.mjs && xcodebuild -scheme CapKitSslPinning -destination generic/platform=iOS",
|
|
98
112
|
"verify:android": "cd android && ./gradlew clean build && cd ..",
|
|
99
113
|
"verify:web": "pnpm run build",
|
|
100
114
|
"lint:android": "cd android && ./gradlew ktlintCheck",
|
|
@@ -106,7 +120,7 @@
|
|
|
106
120
|
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
107
121
|
"swiftlint": "node-swiftlint lint ios/Sources",
|
|
108
122
|
"docgen": "docgen --api SSLPinningPlugin --output-readme README.md --output-json dist/docs.json",
|
|
109
|
-
"build": "node ./scripts/sync-version.
|
|
123
|
+
"build": "node ./scripts/sync-version.mjs && pnpm run clean && pnpm run docgen && tsc && rollup -c rollup.config.mjs && node scripts/chmod.mjs",
|
|
110
124
|
"clean": "rimraf ./dist",
|
|
111
125
|
"watch": "tsc --watch",
|
|
112
126
|
"test": "pnpm run verify",
|
|
@@ -13,6 +13,12 @@ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
|
13
13
|
// 3. Automatically find the iOS source directory
|
|
14
14
|
// Capacitor standard structure: ios/Sources/<PluginName>
|
|
15
15
|
const sourcesDir = path.join(__dirname, '../ios/Sources');
|
|
16
|
+
|
|
17
|
+
if (!fs.existsSync(sourcesDir)) {
|
|
18
|
+
console.warn('⚠️ [CapKit] ios/Sources directory not found. Skipping Version.swift generation.');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
const pluginFolderName = fs.readdirSync(sourcesDir).find((f) => fs.statSync(path.join(sourcesDir, f)).isDirectory());
|
|
17
23
|
|
|
18
24
|
if (!pluginFolderName) {
|
|
File without changes
|