react-native-ssl-manager 1.0.0 → 1.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/README.md +319 -58
- package/android/build.gradle +23 -1
- package/android/src/main/java/com/usesslpinning/SslPinningFactory.kt +94 -0
- package/android/src/main/java/com/usesslpinning/UseSslPinningModuleImpl.kt +34 -0
- package/android/src/newarch/com/usesslpinning/UseSslPinningModule.kt +26 -0
- package/android/src/newarch/com/usesslpinning/UseSslPinningPackage.kt +36 -0
- package/android/src/oldarch/com/usesslpinning/UseSslPinningModule.kt +32 -0
- package/android/src/{main/java → oldarch}/com/usesslpinning/UseSslPinningPackage.kt +0 -1
- package/android/ssl-pinning-setup.gradle +148 -0
- package/app.plugin.js +293 -0
- package/expo-module.config.json +10 -0
- package/ios/SharedLogic.swift +247 -0
- package/ios/UseSslPinning.h +5 -0
- package/ios/{UseSslPinning.mm → UseSslPinningModule.mm} +9 -6
- package/ios/UseSslPinningModule.swift +65 -0
- package/lib/NativeUseSslPinning.d.ts +8 -0
- package/lib/NativeUseSslPinning.d.ts.map +1 -0
- package/lib/NativeUseSslPinning.js +4 -0
- package/lib/UseSslPinning.types.d.ts +17 -0
- package/lib/UseSslPinning.types.d.ts.map +1 -0
- package/lib/UseSslPinning.types.js +2 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +58 -0
- package/package.json +83 -39
- package/react-native-ssl-manager.podspec +87 -38
- package/react-native.config.js +34 -0
- package/scripts/build.sh +52 -0
- package/src/NativeUseSslPinning.ts +9 -0
- package/src/UseSslPinning.types.ts +17 -0
- package/src/index.tsx +53 -33
- package/android/src/main/java/com/usesslpinning/UseSslPinningFactory.kt +0 -50
- package/android/src/main/java/com/usesslpinning/UseSslPinningModule.kt +0 -45
- package/ios/UseSslPinning-Bridging-Header.h +0 -2
- package/ios/UseSslPinning.swift +0 -169
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import TrustKit
|
|
3
|
+
import TrustKit.TSKPinningValidator
|
|
4
|
+
import TrustKit.TSKPinningValidatorCallback
|
|
5
|
+
|
|
6
|
+
enum SSLPinningError: Error {
|
|
7
|
+
case invalidConfiguration
|
|
8
|
+
case invalidPinConfiguration(domain: String)
|
|
9
|
+
|
|
10
|
+
var message: String {
|
|
11
|
+
switch self {
|
|
12
|
+
case .invalidConfiguration:
|
|
13
|
+
return "Invalid SSL pinning configuration format"
|
|
14
|
+
case .invalidPinConfiguration(let domain):
|
|
15
|
+
return "Invalid pin configuration for domain: \(domain)"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Shared logic for SSL pinning functionality
|
|
22
|
+
* Contains common methods used by both CLI and Expo modules
|
|
23
|
+
*/
|
|
24
|
+
@objc class SharedLogic: NSObject {
|
|
25
|
+
static var sharedTrustKit: TrustKit?
|
|
26
|
+
private static let useSSLPinningKey = "useSSLPinning"
|
|
27
|
+
private static let userDefaults = UserDefaults.standard
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Set SSL pinning enabled/disabled state
|
|
31
|
+
* Auto-initialize SSL pinning when enabled
|
|
32
|
+
*/
|
|
33
|
+
@objc static func setUseSSLPinning(_ usePinning: Bool) {
|
|
34
|
+
userDefaults.set(usePinning, forKey: useSSLPinningKey)
|
|
35
|
+
userDefaults.synchronize()
|
|
36
|
+
|
|
37
|
+
// Auto-initialize SSL pinning when enabled
|
|
38
|
+
if usePinning {
|
|
39
|
+
do {
|
|
40
|
+
let _ = try initializeSslPinningFromBundle()
|
|
41
|
+
|
|
42
|
+
} catch {
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get current SSL pinning state
|
|
52
|
+
*/
|
|
53
|
+
@objc static func getUseSSLPinning() -> Bool {
|
|
54
|
+
// Check if key exists, if not return default true
|
|
55
|
+
if userDefaults.object(forKey: useSSLPinningKey) == nil {
|
|
56
|
+
|
|
57
|
+
return true // Default to enabled
|
|
58
|
+
}
|
|
59
|
+
let value = userDefaults.bool(forKey: useSSLPinningKey)
|
|
60
|
+
|
|
61
|
+
return value
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Clean JSON string from various formatting issues
|
|
66
|
+
*/
|
|
67
|
+
static func cleanJsonString(_ jsonString: String) -> String {
|
|
68
|
+
var cleaned = jsonString
|
|
69
|
+
.replacingOccurrences(of: "\n", with: "")
|
|
70
|
+
.replacingOccurrences(of: "| ", with: "")
|
|
71
|
+
.replacingOccurrences(of: "\\ ", with: "")
|
|
72
|
+
.replacingOccurrences(of: "\\\"", with: "\"")
|
|
73
|
+
|
|
74
|
+
// Remove any remaining backslashes before quotes
|
|
75
|
+
cleaned = cleaned.replacingOccurrences(of: "\\(?!\")", with: "")
|
|
76
|
+
|
|
77
|
+
// Clean up any double spaces
|
|
78
|
+
cleaned = cleaned.replacingOccurrences(of: " ", with: " ")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
return cleaned
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Validate and clean pins for a domain
|
|
88
|
+
*/
|
|
89
|
+
static func validateAndCleanPins(_ pins: [String], for domain: String) throws -> [String] {
|
|
90
|
+
guard !pins.isEmpty else {
|
|
91
|
+
|
|
92
|
+
throw SSLPinningError.invalidPinConfiguration(domain: domain)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return try pins.map { pin -> String in
|
|
96
|
+
var cleanPin = pin.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// Verify pin format
|
|
100
|
+
guard cleanPin.starts(with: "sha256/") else {
|
|
101
|
+
|
|
102
|
+
throw SSLPinningError.invalidPinConfiguration(domain: domain)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Remove sha256/ prefix for TrustKit
|
|
106
|
+
cleanPin = cleanPin.replacingOccurrences(of: "sha256/", with: "")
|
|
107
|
+
|
|
108
|
+
// Check base64 format
|
|
109
|
+
guard cleanPin.range(of: "^[A-Za-z0-9+/=]+$", options: .regularExpression) != nil else {
|
|
110
|
+
|
|
111
|
+
throw SSLPinningError.invalidPinConfiguration(domain: domain)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Check length - SHA256 pins should be 44 characters when base64 encoded
|
|
115
|
+
guard cleanPin.count == 44 else {
|
|
116
|
+
|
|
117
|
+
throw SSLPinningError.invalidPinConfiguration(domain: domain)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
return cleanPin
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Initialize SSL pinning from bundle (auto-read ssl_config.json)
|
|
127
|
+
*/
|
|
128
|
+
@objc static func initializeSslPinningFromBundle() throws -> [String: Any] {
|
|
129
|
+
// Try to read ssl_config.json from main bundle (auto-copied by script phase)
|
|
130
|
+
guard let path = Bundle.main.path(forResource: "ssl_config", ofType: "json"),
|
|
131
|
+
let configData = NSData(contentsOfFile: path),
|
|
132
|
+
let configJsonString = String(data: configData as Data, encoding: .utf8) else {
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
throw SSLPinningError.invalidConfiguration
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
return try initializeSslPinning(configJsonString)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Initialize SSL pinning with TrustKit
|
|
145
|
+
* Ported from original working code with minimal modifications
|
|
146
|
+
*/
|
|
147
|
+
static func initializeSslPinning(_ configJsonString: String) throws -> [String: Any] {
|
|
148
|
+
// Check if SSL pinning is enabled
|
|
149
|
+
let isSSLPinningEnabled = getUseSSLPinning()
|
|
150
|
+
|
|
151
|
+
if isSSLPinningEnabled {
|
|
152
|
+
do {
|
|
153
|
+
// Clean JSON first
|
|
154
|
+
let cleanedJson = cleanJsonString(configJsonString)
|
|
155
|
+
|
|
156
|
+
// Parse JSON configuration
|
|
157
|
+
guard let jsonData = cleanedJson.data(using: .utf8),
|
|
158
|
+
let config = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any],
|
|
159
|
+
let sha256Keys = config["sha256Keys"] as? [String: [String]] else {
|
|
160
|
+
throw SSLPinningError.invalidConfiguration
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Build pinned domains configuration
|
|
164
|
+
var pinnedDomains: [String: Any] = [:]
|
|
165
|
+
|
|
166
|
+
// Process each domain and its pins from JSON
|
|
167
|
+
for (domain, pins) in sha256Keys {
|
|
168
|
+
let cleanedPins = try validateAndCleanPins(pins, for: domain)
|
|
169
|
+
|
|
170
|
+
pinnedDomains[domain] = [
|
|
171
|
+
kTSKIncludeSubdomains: true,
|
|
172
|
+
kTSKEnforcePinning: true,
|
|
173
|
+
kTSKDisableDefaultReportUri: true,
|
|
174
|
+
kTSKPublicKeyHashes: cleanedPins
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
let trustKitConfig: [String: Any] = [
|
|
179
|
+
kTSKSwizzleNetworkDelegates: true,
|
|
180
|
+
kTSKPinnedDomains: pinnedDomains
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
// Initialize TrustKit synchronously to catch initialization errors
|
|
186
|
+
do {
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
// Initialize TrustKit with the configuration
|
|
191
|
+
|
|
192
|
+
TrustKit.initSharedInstance(withConfiguration: trustKitConfig)
|
|
193
|
+
SharedLogic.sharedTrustKit = TrustKit.sharedInstance()
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
// Verify TrustKit is properly initialized
|
|
198
|
+
if let trustKit = SharedLogic.sharedTrustKit {
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
// Set up validation callback
|
|
203
|
+
trustKit.pinningValidatorCallback = { result, notedHostname, policy in
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
switch result.finalTrustDecision {
|
|
207
|
+
case .shouldBlockConnection:
|
|
208
|
+
break
|
|
209
|
+
case .shouldAllowConnection:
|
|
210
|
+
break
|
|
211
|
+
default:
|
|
212
|
+
break
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
} else {
|
|
218
|
+
|
|
219
|
+
throw SSLPinningError.invalidConfiguration
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
|
|
223
|
+
throw error
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return [
|
|
227
|
+
"message": "SSL Pinning initialized successfully",
|
|
228
|
+
"domains": Array(pinnedDomains.keys)
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
} catch let error as SSLPinningError {
|
|
232
|
+
|
|
233
|
+
throw error
|
|
234
|
+
} catch {
|
|
235
|
+
|
|
236
|
+
throw error
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
|
|
240
|
+
return [
|
|
241
|
+
"message": "SSL Pinning is disabled",
|
|
242
|
+
"domains": [],
|
|
243
|
+
"isSSLPinningEnabled": isSSLPinningEnabled
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
2
|
|
|
3
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
4
|
+
// New Architecture - TurboModule will be handled by Swift
|
|
5
|
+
#else
|
|
6
|
+
// Legacy Architecture - Bridge exports for Swift module
|
|
3
7
|
@interface RCT_EXTERN_MODULE(UseSslPinning, NSObject)
|
|
4
8
|
|
|
5
|
-
RCT_EXTERN_METHOD(setUseSSLPinning:(BOOL)usePinning
|
|
6
|
-
|
|
7
|
-
RCT_EXTERN_METHOD(getUseSSLPinning:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
RCT_EXTERN_METHOD(setUseSSLPinning:(BOOL)usePinning
|
|
10
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
8
11
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
9
12
|
|
|
10
|
-
RCT_EXTERN_METHOD(
|
|
11
|
-
resolver:(RCTPromiseResolveBlock)resolve
|
|
13
|
+
RCT_EXTERN_METHOD(getUseSSLPinning:(RCTPromiseResolveBlock)resolve
|
|
12
14
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
13
15
|
|
|
14
16
|
+ (BOOL)requiresMainQueueSetup
|
|
15
17
|
{
|
|
16
|
-
|
|
18
|
+
return NO;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
@end
|
|
22
|
+
#endif
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* React Native SSL Pinning module - supports both architectures
|
|
6
|
+
* Uses conditional compilation for New Architecture vs Legacy
|
|
7
|
+
*/
|
|
8
|
+
@objc(UseSslPinning)
|
|
9
|
+
class UseSslPinning: NSObject {
|
|
10
|
+
|
|
11
|
+
override init() {
|
|
12
|
+
super.init()
|
|
13
|
+
|
|
14
|
+
// Early initialization - setup SSL pinning if enabled
|
|
15
|
+
let isEnabled = SharedLogic.getUseSSLPinning()
|
|
16
|
+
if isEnabled {
|
|
17
|
+
do {
|
|
18
|
+
let _ = try SharedLogic.initializeSslPinningFromBundle()
|
|
19
|
+
} catch {
|
|
20
|
+
// SSL config not found or invalid - continue silently
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// MARK: - Shared Implementation Methods
|
|
26
|
+
|
|
27
|
+
private func setUseSSLPinningImpl(_ usePinning: Bool, resolve: @escaping RCTPromiseResolveBlock) {
|
|
28
|
+
SharedLogic.setUseSSLPinning(usePinning)
|
|
29
|
+
resolve(nil)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private func getUseSSLPinningImpl(_ resolve: @escaping RCTPromiseResolveBlock) {
|
|
33
|
+
let usePinning = SharedLogic.getUseSSLPinning()
|
|
34
|
+
resolve(usePinning)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// MARK: - Architecture-specific exports
|
|
38
|
+
|
|
39
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
40
|
+
|
|
41
|
+
// New Architecture (TurboModule) - no @objc needed
|
|
42
|
+
func setUseSSLPinning(_ usePinning: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
43
|
+
setUseSSLPinningImpl(usePinning, resolve: resolve)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func getUseSSLPinning(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
47
|
+
getUseSSLPinningImpl(resolve)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#else
|
|
51
|
+
|
|
52
|
+
// Legacy Architecture (Bridge) - needs @objc
|
|
53
|
+
@objc
|
|
54
|
+
func setUseSSLPinning(_ usePinning: Bool, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
55
|
+
setUseSSLPinningImpl(usePinning, resolve: resolve)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc
|
|
59
|
+
func getUseSSLPinning(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
60
|
+
getUseSSLPinningImpl(resolve)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#endif
|
|
64
|
+
|
|
65
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
export interface Spec extends TurboModule {
|
|
3
|
+
readonly setUseSSLPinning: (usePinning: boolean) => Promise<void>;
|
|
4
|
+
readonly getUseSSLPinning: () => Promise<boolean>;
|
|
5
|
+
}
|
|
6
|
+
declare const _default: Spec;
|
|
7
|
+
export default _default;
|
|
8
|
+
//# sourceMappingURL=NativeUseSslPinning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeUseSslPinning.d.ts","sourceRoot":"","sources":["../src/NativeUseSslPinning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACnD;;AAED,wBAAuE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSL Pinning Configuration Interface
|
|
3
|
+
* Defines the structure for SSL pinning configuration
|
|
4
|
+
*/
|
|
5
|
+
export interface SslPinningConfig {
|
|
6
|
+
sha256Keys: {
|
|
7
|
+
[domain: string]: string[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* SSL Pinning Error Interface
|
|
12
|
+
*/
|
|
13
|
+
export interface SslPinningError extends Error {
|
|
14
|
+
code?: string;
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=UseSslPinning.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UseSslPinning.types.d.ts","sourceRoot":"","sources":["../src/UseSslPinning.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE;QACV,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC5B,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,KAAK;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type { SslPinningConfig, SslPinningError } from './UseSslPinning.types';
|
|
2
|
+
/**
|
|
3
|
+
* Sets whether SSL pinning should be used.
|
|
4
|
+
*
|
|
5
|
+
* @param {boolean} usePinning - Whether to enable SSL pinning
|
|
6
|
+
* @returns {Promise<void>} A promise that resolves when the setting is saved
|
|
7
|
+
*/
|
|
8
|
+
export declare const setUseSSLPinning: (usePinning: boolean) => Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Retrieves the current state of SSL pinning usage.
|
|
11
|
+
*
|
|
12
|
+
* @returns A promise that resolves to a boolean indicating whether SSL pinning is being used.
|
|
13
|
+
*/
|
|
14
|
+
export declare const getUseSSLPinning: () => Promise<boolean>;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAGA,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA0C/E;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,eAAgB,OAAO,KAAG,QAAQ,IAAI,CAElE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAa,QAAQ,OAAO,CAExD,CAAC"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Remove unused Platform import since we no longer check OS
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getUseSSLPinning = exports.setUseSSLPinning = void 0;
|
|
5
|
+
// New Architecture and Legacy Architecture support
|
|
6
|
+
let UseSslPinning;
|
|
7
|
+
try {
|
|
8
|
+
// Try Legacy NativeModules first (more reliable)
|
|
9
|
+
const { NativeModules } = require('react-native');
|
|
10
|
+
// Look for our universal module (works in both CLI and Expo)
|
|
11
|
+
UseSslPinning = NativeModules.UseSslPinning;
|
|
12
|
+
if (UseSslPinning) {
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
// Fallback to TurboModule if available
|
|
16
|
+
try {
|
|
17
|
+
UseSslPinning = require('./NativeUseSslPinning').default;
|
|
18
|
+
}
|
|
19
|
+
catch (turboModuleError) {
|
|
20
|
+
console.log('❌ TurboModule failed:', turboModuleError.message);
|
|
21
|
+
UseSslPinning = null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.log('❌ Overall module loading failed:', error.message);
|
|
27
|
+
UseSslPinning = null;
|
|
28
|
+
}
|
|
29
|
+
// Fallback implementation if native module is not available
|
|
30
|
+
if (!UseSslPinning) {
|
|
31
|
+
UseSslPinning = {
|
|
32
|
+
setUseSSLPinning: (_usePinning) => {
|
|
33
|
+
return Promise.resolve();
|
|
34
|
+
},
|
|
35
|
+
getUseSSLPinning: () => {
|
|
36
|
+
return Promise.resolve(true);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sets whether SSL pinning should be used.
|
|
42
|
+
*
|
|
43
|
+
* @param {boolean} usePinning - Whether to enable SSL pinning
|
|
44
|
+
* @returns {Promise<void>} A promise that resolves when the setting is saved
|
|
45
|
+
*/
|
|
46
|
+
const setUseSSLPinning = (usePinning) => {
|
|
47
|
+
return UseSslPinning.setUseSSLPinning(usePinning);
|
|
48
|
+
};
|
|
49
|
+
exports.setUseSSLPinning = setUseSSLPinning;
|
|
50
|
+
/**
|
|
51
|
+
* Retrieves the current state of SSL pinning usage.
|
|
52
|
+
*
|
|
53
|
+
* @returns A promise that resolves to a boolean indicating whether SSL pinning is being used.
|
|
54
|
+
*/
|
|
55
|
+
const getUseSSLPinning = async () => {
|
|
56
|
+
return await UseSslPinning.getUseSSLPinning();
|
|
57
|
+
};
|
|
58
|
+
exports.getUseSSLPinning = getUseSSLPinning;
|
package/package.json
CHANGED
|
@@ -1,51 +1,89 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-ssl-manager",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "React Native SSL Pinning provides seamless SSL certificate pinning integration for enhanced network security in React Native apps. This module enables developers to easily implement and manage certificate pinning, protecting applications against man-in-the-middle (MITM) attacks. With dynamic configuration options and the ability to toggle SSL pinning, it's particularly useful for development and testing scenarios.",
|
|
5
|
-
"main": "lib/
|
|
6
|
-
"module": "lib/
|
|
7
|
-
"types": "lib/
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"module": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"source": "src/index.tsx",
|
|
9
|
+
"expo": {
|
|
10
|
+
"plugin": "./app.plugin.js"
|
|
11
|
+
},
|
|
8
12
|
"react-native": {
|
|
9
13
|
"android": {
|
|
10
|
-
"
|
|
14
|
+
"sourceDir": "android/src/main/java",
|
|
15
|
+
"packageImportPath": "import com.usesslpinning.UseSslPinningPackage;"
|
|
11
16
|
},
|
|
12
17
|
"ios": {
|
|
13
|
-
"
|
|
18
|
+
"podspecPath": "react-native-ssl-manager.podspec"
|
|
14
19
|
}
|
|
15
20
|
},
|
|
16
|
-
"
|
|
21
|
+
"codegenConfig": {
|
|
22
|
+
"name": "RNUseSslPinningSpec",
|
|
23
|
+
"type": "modules",
|
|
24
|
+
"jsSrcsDir": "src"
|
|
25
|
+
},
|
|
17
26
|
"files": [
|
|
18
|
-
"src",
|
|
19
27
|
"lib",
|
|
20
|
-
"
|
|
21
|
-
"!**/__fixtures__",
|
|
22
|
-
"!**/__mocks__",
|
|
28
|
+
"src",
|
|
23
29
|
"android",
|
|
24
30
|
"ios",
|
|
25
|
-
"
|
|
31
|
+
"plugin",
|
|
32
|
+
"app.plugin.js",
|
|
26
33
|
"*.podspec",
|
|
27
|
-
"
|
|
34
|
+
"react-native-ssl-manager.podspec",
|
|
35
|
+
"expo-module.config.json",
|
|
36
|
+
"react-native.config.js",
|
|
37
|
+
"scripts/build.sh",
|
|
38
|
+
"!**/__tests__",
|
|
39
|
+
"!**/__fixtures__",
|
|
40
|
+
"!**/__mocks__",
|
|
28
41
|
"!ios/build",
|
|
29
42
|
"!android/build",
|
|
43
|
+
"!android/.gradle",
|
|
30
44
|
"!android/gradle",
|
|
31
45
|
"!android/gradlew",
|
|
32
46
|
"!android/gradlew.bat",
|
|
33
47
|
"!android/local.properties",
|
|
48
|
+
"!example",
|
|
49
|
+
"!example-expo",
|
|
34
50
|
"!**/.*"
|
|
35
51
|
],
|
|
36
52
|
"scripts": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"clean": "expo-module clean",
|
|
55
|
+
"lint": "expo-module lint",
|
|
56
|
+
"test": "expo-module test",
|
|
57
|
+
"prepare": "echo 'Skipping prepare script'",
|
|
39
58
|
"typecheck": "tsc --noEmit",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
59
|
+
"release": "release-it",
|
|
60
|
+
"build:all": "./scripts/build.sh",
|
|
61
|
+
"build:examples": "./scripts/build.sh --with-examples",
|
|
62
|
+
"example:install": "cd example && yarn install",
|
|
63
|
+
"postinstall": "node scripts/postinstall.js",
|
|
64
|
+
"postinstall:bun": "bun scripts/bun-postinstall.js",
|
|
65
|
+
"example:ios": "cd example && npx react-native run-ios",
|
|
66
|
+
"example:android": "cd example && npx react-native run-android",
|
|
67
|
+
"example-expo:install": "cd example-expo && yarn install",
|
|
68
|
+
"example-expo:ios": "cd example-expo && npx expo run:ios",
|
|
69
|
+
"example-expo:android": "cd example-expo && npx expo run:android",
|
|
70
|
+
"example-expo:start": "cd example-expo && npx expo start",
|
|
71
|
+
"bun:install": "bun install",
|
|
72
|
+
"bun:build": "bun run build",
|
|
73
|
+
"bun:test": "bun test",
|
|
74
|
+
"bun:example:install": "cd example && bun install",
|
|
75
|
+
"bun:example-expo:install": "cd example-expo && bun install",
|
|
76
|
+
"bun:test-compatibility": "bun scripts/test-bun.js"
|
|
44
77
|
},
|
|
45
78
|
"keywords": [
|
|
46
79
|
"react-native",
|
|
47
80
|
"ios",
|
|
48
|
-
"android"
|
|
81
|
+
"android",
|
|
82
|
+
"expo",
|
|
83
|
+
"bun",
|
|
84
|
+
"ssl-pinning",
|
|
85
|
+
"security",
|
|
86
|
+
"certificate-pinning"
|
|
49
87
|
],
|
|
50
88
|
"repository": {
|
|
51
89
|
"type": "git",
|
|
@@ -63,7 +101,6 @@
|
|
|
63
101
|
},
|
|
64
102
|
"devDependencies": {
|
|
65
103
|
"@commitlint/config-conventional": "^17.0.2",
|
|
66
|
-
"@evilmartians/lefthook": "^1.5.0",
|
|
67
104
|
"@react-native/eslint-config": "^0.73.1",
|
|
68
105
|
"@release-it/conventional-changelog": "^5.0.0",
|
|
69
106
|
"@types/jest": "^29.5.5",
|
|
@@ -73,13 +110,13 @@
|
|
|
73
110
|
"eslint": "^8.51.0",
|
|
74
111
|
"eslint-config-prettier": "^9.0.0",
|
|
75
112
|
"eslint-plugin-prettier": "^5.0.1",
|
|
113
|
+
"expo-module-scripts": "^3.4.0",
|
|
76
114
|
"jest": "^29.7.0",
|
|
77
115
|
"prettier": "^3.0.3",
|
|
78
116
|
"react": "18.2.0",
|
|
79
117
|
"react-native": "0.73.6",
|
|
80
118
|
"react-native-builder-bob": "^0.20.0",
|
|
81
119
|
"release-it": "^15.0.0",
|
|
82
|
-
"turbo": "^1.10.7",
|
|
83
120
|
"typescript": "5.1.x"
|
|
84
121
|
},
|
|
85
122
|
"resolutions": {
|
|
@@ -89,14 +126,27 @@
|
|
|
89
126
|
"react": "*",
|
|
90
127
|
"react-native": "*"
|
|
91
128
|
},
|
|
92
|
-
"workspaces": [
|
|
93
|
-
"example"
|
|
94
|
-
],
|
|
95
129
|
"packageManager": "yarn@3.6.1",
|
|
130
|
+
"engines": {
|
|
131
|
+
"node": ">=16.0.0",
|
|
132
|
+
"bun": ">=1.0.0"
|
|
133
|
+
},
|
|
134
|
+
"overrides": {
|
|
135
|
+
"bun": {
|
|
136
|
+
"react": "*",
|
|
137
|
+
"react-native": "*"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"codegenConfig": {
|
|
141
|
+
"name": "RNUseSslPinningSpec",
|
|
142
|
+
"type": "modules",
|
|
143
|
+
"jsSrcsDir": "src"
|
|
144
|
+
},
|
|
96
145
|
"jest": {
|
|
97
146
|
"preset": "react-native",
|
|
98
147
|
"modulePathIgnorePatterns": [
|
|
99
148
|
"<rootDir>/example/node_modules",
|
|
149
|
+
"<rootDir>/example-expo/node_modules",
|
|
100
150
|
"<rootDir>/lib/"
|
|
101
151
|
]
|
|
102
152
|
},
|
|
@@ -143,7 +193,9 @@
|
|
|
143
193
|
},
|
|
144
194
|
"eslintIgnore": [
|
|
145
195
|
"node_modules/",
|
|
146
|
-
"lib/"
|
|
196
|
+
"lib/",
|
|
197
|
+
"example/",
|
|
198
|
+
"example-expo/"
|
|
147
199
|
],
|
|
148
200
|
"prettier": {
|
|
149
201
|
"quoteProps": "consistent",
|
|
@@ -152,21 +204,13 @@
|
|
|
152
204
|
"trailingComma": "es5",
|
|
153
205
|
"useTabs": false
|
|
154
206
|
},
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"commonjs",
|
|
160
|
-
"module",
|
|
161
|
-
[
|
|
162
|
-
"typescript",
|
|
163
|
-
{
|
|
164
|
-
"project": "tsconfig.build.json"
|
|
165
|
-
}
|
|
166
|
-
]
|
|
167
|
-
]
|
|
207
|
+
"codegenConfig": {
|
|
208
|
+
"name": "RNUseSslPinningSpec",
|
|
209
|
+
"type": "modules",
|
|
210
|
+
"jsSrcsDir": "src"
|
|
168
211
|
},
|
|
169
212
|
"dependencies": {
|
|
213
|
+
"@babel/runtime": "^7.23.0",
|
|
170
214
|
"postinstall": "^0.10.3"
|
|
171
215
|
}
|
|
172
216
|
}
|