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.
Files changed (35) hide show
  1. package/README.md +319 -58
  2. package/android/build.gradle +23 -1
  3. package/android/src/main/java/com/usesslpinning/SslPinningFactory.kt +94 -0
  4. package/android/src/main/java/com/usesslpinning/UseSslPinningModuleImpl.kt +34 -0
  5. package/android/src/newarch/com/usesslpinning/UseSslPinningModule.kt +26 -0
  6. package/android/src/newarch/com/usesslpinning/UseSslPinningPackage.kt +36 -0
  7. package/android/src/oldarch/com/usesslpinning/UseSslPinningModule.kt +32 -0
  8. package/android/src/{main/java → oldarch}/com/usesslpinning/UseSslPinningPackage.kt +0 -1
  9. package/android/ssl-pinning-setup.gradle +148 -0
  10. package/app.plugin.js +293 -0
  11. package/expo-module.config.json +10 -0
  12. package/ios/SharedLogic.swift +247 -0
  13. package/ios/UseSslPinning.h +5 -0
  14. package/ios/{UseSslPinning.mm → UseSslPinningModule.mm} +9 -6
  15. package/ios/UseSslPinningModule.swift +65 -0
  16. package/lib/NativeUseSslPinning.d.ts +8 -0
  17. package/lib/NativeUseSslPinning.d.ts.map +1 -0
  18. package/lib/NativeUseSslPinning.js +4 -0
  19. package/lib/UseSslPinning.types.d.ts +17 -0
  20. package/lib/UseSslPinning.types.d.ts.map +1 -0
  21. package/lib/UseSslPinning.types.js +2 -0
  22. package/lib/index.d.ts +15 -0
  23. package/lib/index.d.ts.map +1 -0
  24. package/lib/index.js +58 -0
  25. package/package.json +83 -39
  26. package/react-native-ssl-manager.podspec +87 -38
  27. package/react-native.config.js +34 -0
  28. package/scripts/build.sh +52 -0
  29. package/src/NativeUseSslPinning.ts +9 -0
  30. package/src/UseSslPinning.types.ts +17 -0
  31. package/src/index.tsx +53 -33
  32. package/android/src/main/java/com/usesslpinning/UseSslPinningFactory.kt +0 -50
  33. package/android/src/main/java/com/usesslpinning/UseSslPinningModule.kt +0 -45
  34. package/ios/UseSslPinning-Bridging-Header.h +0 -2
  35. package/ios/UseSslPinning.swift +0 -169
@@ -1,43 +1,92 @@
1
- require "json"
2
-
3
- package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
- folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
5
-
6
1
  Pod::Spec.new do |s|
7
- s.name = "react-native-ssl-manager"
8
- s.version = package["version"]
9
- s.summary = package["description"]
10
- s.homepage = package["homepage"]
11
- s.license = package["license"]
12
- s.authors = package["author"]
13
-
14
- s.platforms = { :ios => min_ios_version_supported }
15
- s.source = { :git => "https://github.com/huytdps13400/react-native-ssl-manager.git", :tag => "#{s.version}" }
2
+ s.name = 'react-native-ssl-manager'
3
+ s.version = '1.0.1'
4
+ s.summary = 'SSL Pinning Module for React Native and Expo'
5
+ s.author = 'Huy Tran'
6
+ s.homepage = 'https://github.com/huytdps13400/react-native-ssl-manager'
7
+ s.platforms = { :ios => '13.0' }
8
+ s.source = { :git => 'https://github.com/huytdps13400/react-native-ssl-manager', :tag => s.version.to_s }
9
+
16
10
 
11
+
12
+ # RNBootSplash pattern - single implementation for all architectures
17
13
  s.source_files = "ios/**/*.{h,m,mm,swift}"
18
-
19
- # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
20
- # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
21
- if respond_to?(:install_modules_dependencies, true)
22
- install_modules_dependencies(s)
23
- else
24
- s.dependency "React-Core"
25
-
26
- # Don't install the dependencies when we run `pod install` in the old architecture.
14
+
15
+ s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" }
16
+
27
17
  if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
28
- s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
29
- s.pod_target_xcconfig = {
30
- "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
31
- "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
32
- "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
18
+ # New Architecture dependencies would go here if needed
19
+ s.dependency "React-Core"
20
+ else
21
+ s.dependency "React-Core"
22
+ end
23
+
24
+ # Use script phase to copy ssl_config.json during app build
25
+ s.script_phases = [
26
+ {
27
+ :name => 'Copy SSL Config to App Bundle',
28
+ :script => '
29
+ echo "🔧 SSL Manager: Copying ssl_config.json to app bundle..."
30
+
31
+ # Look for ssl_config.json in parent directories of SRCROOT
32
+ SSL_CONFIG_SOURCE=""
33
+
34
+ # Check common locations and verify content is not empty
35
+ if [ -f "${SRCROOT}/../ssl_config.json" ]; then
36
+ CONTENT=$(cat "${SRCROOT}/../ssl_config.json" | tr -d " \\n\\r")
37
+ if [ "$CONTENT" != "{}" ]; then
38
+ SSL_CONFIG_SOURCE="${SRCROOT}/../ssl_config.json"
39
+ echo "📄 Found ssl_config.json at: $SSL_CONFIG_SOURCE"
40
+ fi
41
+ fi
42
+
43
+ if [ -z "$SSL_CONFIG_SOURCE" ] && [ -f "${SRCROOT}/../../ssl_config.json" ]; then
44
+ CONTENT=$(cat "${SRCROOT}/../../ssl_config.json" | tr -d " \\n\\r")
45
+ if [ "$CONTENT" != "{}" ]; then
46
+ SSL_CONFIG_SOURCE="${SRCROOT}/../../ssl_config.json"
47
+ echo "📄 Found ssl_config.json at: $SSL_CONFIG_SOURCE"
48
+ fi
49
+ fi
50
+
51
+ if [ -z "$SSL_CONFIG_SOURCE" ] && [ -f "${SRCROOT}/../../../ssl_config.json" ]; then
52
+ CONTENT=$(cat "${SRCROOT}/../../../ssl_config.json" | tr -d " \\n\\r")
53
+ if [ "$CONTENT" != "{}" ]; then
54
+ SSL_CONFIG_SOURCE="${SRCROOT}/../../../ssl_config.json"
55
+ echo "📄 Found ssl_config.json at: $SSL_CONFIG_SOURCE"
56
+ fi
57
+ fi
58
+
59
+ if [ -n "$SSL_CONFIG_SOURCE" ]; then
60
+ # Copy to app bundle resources
61
+ cp "$SSL_CONFIG_SOURCE" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/"
62
+ echo "✅ SSL config copied to app bundle"
63
+ else
64
+ echo "⚠️ ssl_config.json not found in common locations"
65
+ echo "🔍 Searching for ssl_config.json with content..."
66
+
67
+ # Search for any ssl_config.json with content
68
+ for path in $(find "${SRCROOT}/../.." -name "ssl_config.json" -type f 2>/dev/null); do
69
+ CONTENT=$(cat "$path" | tr -d " \\n\\r")
70
+ if [ "$CONTENT" != "{}" ]; then
71
+ SSL_CONFIG_SOURCE="$path"
72
+ echo "📄 Found ssl_config.json with content at: $SSL_CONFIG_SOURCE"
73
+ cp "$SSL_CONFIG_SOURCE" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/"
74
+ echo "✅ SSL config copied to app bundle"
75
+ break
76
+ fi
77
+ done
78
+
79
+ if [ -z "$SSL_CONFIG_SOURCE" ]; then
80
+ echo "💡 SRCROOT: $SRCROOT"
81
+ echo "💡 Create ssl_config.json at project root for SSL pinning to work"
82
+ exit 0
83
+ fi
84
+ fi
85
+ ',
86
+ :execution_position => :before_compile
33
87
  }
34
- s.dependency "React-Codegen"
35
- s.dependency "RCT-Folly"
36
- s.dependency "RCTRequired"
37
- s.dependency "RCTTypeSafety"
38
- s.dependency "ReactCommon/turbomodule/core"
39
- end
40
- end
41
-
42
- s.dependency "TrustKit"
43
- end
88
+ ]
89
+
90
+ s.dependency 'TrustKit'
91
+ s.dependency 'React-Core'
92
+ end
@@ -0,0 +1,34 @@
1
+ // React Native SSL Manager Auto-linking Configuration
2
+
3
+ module.exports = {
4
+ dependencies: {
5
+ 'react-native-ssl-manager': {
6
+ platforms: {
7
+ android: {
8
+ sourceDir: '../android',
9
+ packageImportPath: 'import com.usesslpinning.UseSslPinningPackage;',
10
+ packageInstance: 'new UseSslPinningPackage()',
11
+ // Auto-setup SSL config copy script
12
+ buildTypes: [],
13
+ componentDescriptors: [],
14
+ cmakeListsPath: null,
15
+ },
16
+ ios: {
17
+ podspecPath: '../react-native-ssl-manager.podspec',
18
+ },
19
+ },
20
+ hooks: {
21
+ postlink: () => {
22
+ console.log('🔗 React Native SSL Manager linked successfully');
23
+ console.log('📋 SSL config auto-copy script is now available');
24
+ console.log(
25
+ '💡 Android: Run "cd android && ./gradlew checkSslConfig" to verify setup'
26
+ );
27
+ console.log(
28
+ '💡 iOS: ssl_config.json will be auto-copied during build'
29
+ );
30
+ },
31
+ },
32
+ },
33
+ },
34
+ };
@@ -0,0 +1,52 @@
1
+ #!/bin/bash
2
+
3
+ # Build script for react-native-ssl-manager
4
+ # This script helps build and test the library
5
+
6
+ set -e
7
+
8
+ echo "🚀 Building react-native-ssl-manager..."
9
+
10
+ # Clean previous builds
11
+ echo "🧹 Cleaning previous builds..."
12
+ rm -rf lib/
13
+ rm -rf build/
14
+
15
+ # Install dependencies
16
+ echo "📦 Installing dependencies..."
17
+ yarn install
18
+
19
+ # Type check
20
+ echo "🔍 Running type check..."
21
+ yarn typecheck
22
+
23
+ # Build TypeScript
24
+ echo "🔨 Building TypeScript..."
25
+ yarn build
26
+
27
+ # Run tests
28
+ echo "🧪 Running tests..."
29
+ yarn test
30
+
31
+ echo "✅ Build completed successfully!"
32
+
33
+ # Optional: Build examples
34
+ if [ "$1" = "--with-examples" ]; then
35
+ echo "📱 Building examples..."
36
+
37
+ # Build React Native CLI example
38
+ echo "Building React Native CLI example..."
39
+ cd example
40
+ yarn install
41
+ cd ..
42
+
43
+ # Build Expo example
44
+ echo "Building Expo example..."
45
+ cd example-expo
46
+ yarn install
47
+ cd ..
48
+
49
+ echo "✅ Examples built successfully!"
50
+ fi
51
+
52
+ echo "🎉 All done! The library is ready for use."
@@ -0,0 +1,9 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export interface Spec extends TurboModule {
5
+ readonly setUseSSLPinning: (usePinning: boolean) => Promise<void>;
6
+ readonly getUseSSLPinning: () => Promise<boolean>;
7
+ }
8
+
9
+ export default TurboModuleRegistry.getEnforcing<Spec>('UseSslPinning');
@@ -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
+ /**
12
+ * SSL Pinning Error Interface
13
+ */
14
+ export interface SslPinningError extends Error {
15
+ code?: string;
16
+ message: string;
17
+ }
package/src/index.tsx CHANGED
@@ -1,43 +1,63 @@
1
- import { NativeModules, Platform } from 'react-native';
2
-
3
- const LINKING_ERROR =
4
- `The package 'react-native-ssl-manager' doesn't seem to be linked. Make sure: \n\n` +
5
- Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6
- '- You rebuilt the app after installing the package\n' +
7
- '- You are not using Expo Go\n';
8
-
9
- const UseSslPinning = NativeModules.UseSslPinning
10
- ? NativeModules.UseSslPinning
11
- : new Proxy(
12
- {},
13
- {
14
- get() {
15
- throw new Error(LINKING_ERROR);
16
- },
17
- }
18
- );
19
-
20
- export const setUseSSLPinning = (usePinning: boolean): void => {
21
- UseSslPinning.setUseSSLPinning(usePinning);
22
- };
1
+ // Remove unused Platform import since we no longer check OS
2
+
3
+ // Export types from the library
4
+ export type { SslPinningConfig, SslPinningError } from './UseSslPinning.types';
5
+
6
+ // New Architecture and Legacy Architecture support
7
+ let UseSslPinning: any;
8
+
9
+ try {
10
+ // Try Legacy NativeModules first (more reliable)
11
+ const { NativeModules } = require('react-native');
12
+
13
+ // Look for our universal module (works in both CLI and Expo)
14
+ UseSslPinning = NativeModules.UseSslPinning;
15
+
16
+ if (UseSslPinning) {
17
+ } else {
18
+ // Fallback to TurboModule if available
19
+ try {
20
+ UseSslPinning = require('./NativeUseSslPinning').default;
21
+ } catch (turboModuleError) {
22
+ console.log(
23
+ '❌ TurboModule failed:',
24
+ (turboModuleError as Error).message
25
+ );
26
+ UseSslPinning = null;
27
+ }
28
+ }
29
+ } catch (error) {
30
+ console.log('❌ Overall module loading failed:', (error as Error).message);
31
+ UseSslPinning = null;
32
+ }
33
+
34
+ // Fallback implementation if native module is not available
35
+ if (!UseSslPinning) {
36
+ UseSslPinning = {
37
+ setUseSSLPinning: (_usePinning: boolean) => {
38
+ return Promise.resolve();
39
+ },
40
+ getUseSSLPinning: () => {
41
+ return Promise.resolve(true);
42
+ },
43
+ };
44
+ }
23
45
 
24
46
  /**
25
- * Retrieves the current state of SSL pinning usage.
47
+ * Sets whether SSL pinning should be used.
26
48
  *
27
- * @returns A promise that resolves to a boolean indicating whether SSL pinning is being used.
49
+ * @param {boolean} usePinning - Whether to enable SSL pinning
50
+ * @returns {Promise<void>} A promise that resolves when the setting is saved
28
51
  */
29
- export const getUseSSLPinning = async (): Promise<boolean> => {
30
- return await UseSslPinning.getUseSSLPinning();
52
+ export const setUseSSLPinning = (usePinning: boolean): Promise<void> => {
53
+ return UseSslPinning.setUseSSLPinning(usePinning);
31
54
  };
32
55
 
33
56
  /**
34
- * Initializes SSL pinning with the provided configuration.
57
+ * Retrieves the current state of SSL pinning usage.
35
58
  *
36
- * @param {string} configJsonString - The JSON string containing the SSL pinning configuration.
37
- * @returns {Promise<any>} A promise that resolves when the SSL pinning is initialized.
59
+ * @returns A promise that resolves to a boolean indicating whether SSL pinning is being used.
38
60
  */
39
- export const initializeSslPinning = async (
40
- configJsonString: string
41
- ): Promise<any> => {
42
- return await UseSslPinning.initializeSslPinning(configJsonString);
61
+ export const getUseSSLPinning = async (): Promise<boolean> => {
62
+ return await UseSslPinning.getUseSSLPinning();
43
63
  };
@@ -1,50 +0,0 @@
1
- package com.usesslpinning
2
-
3
- import android.content.Context
4
- import android.util.Log
5
- import com.facebook.react.modules.network.OkHttpClientFactory
6
- import com.facebook.react.modules.network.ReactCookieJarContainer
7
- import okhttp3.CertificatePinner
8
- import okhttp3.OkHttpClient
9
- import org.json.JSONObject
10
-
11
- class UseSslPinningFactory(
12
- private val context: Context,
13
- private val configJsonString: String
14
- ) : OkHttpClientFactory {
15
-
16
- override fun createNewNetworkModuleClient(): OkHttpClient {
17
- val sharedPreferences = context.getSharedPreferences("AppSettings", Context.MODE_PRIVATE)
18
- val useSSLPinning = sharedPreferences.getBoolean("useSSLPinning", true)
19
-
20
- val clientBuilder = OkHttpClient.Builder().cookieJar(ReactCookieJarContainer()).apply {
21
- if (useSSLPinning) {
22
- val certificatePinnerBuilder = CertificatePinner.Builder()
23
-
24
- try {
25
- val configJson = JSONObject(configJsonString)
26
- addCertificatesToPinner(certificatePinnerBuilder, configJson)
27
- val certificatePinner = certificatePinnerBuilder.build()
28
- certificatePinner(certificatePinner)
29
- } catch (e: Exception) {
30
- e.printStackTrace()
31
- }
32
- }
33
- }.cache(null).build()
34
-
35
- return clientBuilder
36
- }
37
- private fun addCertificatesToPinner(certificatePinnerBuilder: CertificatePinner.Builder, configJson: JSONObject) {
38
- val sha256Keys = configJson.getJSONObject("sha256Keys")
39
- val hostnames = sha256Keys.keys()
40
- while (hostnames.hasNext()) {
41
- val hostname = hostnames.next()
42
- val keysArray = sha256Keys.getJSONArray(hostname)
43
- for (i in 0 until keysArray.length()) {
44
- val sha256Key = keysArray.getString(i)
45
- certificatePinnerBuilder.add(hostname, sha256Key)
46
- }
47
- }
48
- }
49
- }
50
-
@@ -1,45 +0,0 @@
1
- package com.usesslpinning
2
-
3
- import android.content.Context // Thêm dòng này
4
- import android.util.Log
5
- import com.facebook.react.bridge.ReactApplicationContext
6
- import com.facebook.react.bridge.ReactContextBaseJavaModule
7
- import com.facebook.react.bridge.ReactMethod
8
- import com.facebook.react.bridge.Promise
9
- import com.facebook.react.modules.network.OkHttpClientProvider
10
-
11
- class UseSslPinningModule(reactContext: ReactApplicationContext) :
12
- ReactContextBaseJavaModule(reactContext) {
13
-
14
- override fun getName(): String {
15
- return NAME
16
- }
17
-
18
- @ReactMethod
19
- fun setUseSSLPinning(usePinning: Boolean) {
20
- val sharedPreferences = reactApplicationContext.getSharedPreferences("AppSettings", Context.MODE_PRIVATE)
21
- sharedPreferences.edit().putBoolean("useSSLPinning", usePinning).apply()
22
- }
23
-
24
- @ReactMethod
25
- fun getUseSSLPinning(promise: Promise) {
26
- val sharedPreferences = reactApplicationContext.getSharedPreferences("AppSettings", Context.MODE_PRIVATE)
27
- val usePinning = sharedPreferences.getBoolean("useSSLPinning", true)
28
- promise.resolve(usePinning)
29
- }
30
-
31
- @ReactMethod
32
- fun initializeSslPinning(configJsonString: String, promise: Promise) {
33
- try {
34
- OkHttpClientProvider.setOkHttpClientFactory(UseSslPinningFactory(reactApplicationContext, configJsonString))
35
- Log.d("MyLibrary", "SSL Pinning initialized successfully")
36
- promise.resolve("SSL Pinning initialized successfully")
37
- } catch (e: Exception) {
38
- promise.reject("SSL_PINNING_ERROR", "Failed to initialize SSL Pinning", e)
39
- }
40
- }
41
-
42
- companion object {
43
- const val NAME = "UseSslPinning"
44
- }
45
- }
@@ -1,2 +0,0 @@
1
- #import <React/RCTBridgeModule.h>
2
- #import <React/RCTViewManager.h>
@@ -1,169 +0,0 @@
1
- import Foundation
2
- import TrustKit
3
- import TrustKit.TSKPinningValidator
4
- import TrustKit.TSKPinningValidatorCallback
5
-
6
- // Add SSLPinningError enum definition
7
- enum SSLPinningError: Error {
8
- case invalidConfiguration
9
- case invalidPinConfiguration(domain: String)
10
-
11
- var message: String {
12
- switch self {
13
- case .invalidConfiguration:
14
- return "Invalid SSL pinning configuration format"
15
- case .invalidPinConfiguration(let domain):
16
- return "Invalid pin configuration for domain: \(domain)"
17
- }
18
- }
19
- }
20
-
21
- @objc(UseSslPinning)
22
- class UseSslPinning: NSObject {
23
- private static var sharedTrustKit: TrustKit?
24
- private let userDefaults = UserDefaults.standard
25
- private let useSSLPinningKey = "useSSLPinning"
26
-
27
- private func cleanJsonString(_ jsonString: String) -> String {
28
- var cleaned = jsonString
29
- .replacingOccurrences(of: "\n", with: "")
30
- .replacingOccurrences(of: "| ", with: "")
31
- .replacingOccurrences(of: "\\ ", with: "")
32
- .replacingOccurrences(of: "\\\"", with: "\"")
33
-
34
- // Remove any remaining backslashes before quotes
35
- cleaned = cleaned.replacingOccurrences(of: "\\(?!\")", with: "")
36
-
37
- // Clean up any double spaces
38
- cleaned = cleaned.replacingOccurrences(of: " ", with: " ")
39
-
40
- NSLog("Original JSON: %@", jsonString)
41
- NSLog("Cleaned JSON: %@", cleaned)
42
-
43
- return cleaned
44
- }
45
-
46
- private func validateAndCleanPins(_ pins: [String], for domain: String) throws -> [String] {
47
- return try pins.map { pin -> String in
48
- var cleanPin = pin.trimmingCharacters(in: .whitespacesAndNewlines)
49
-
50
- // Verify pin format
51
- guard cleanPin.starts(with: "sha256/") else {
52
- NSLog("Invalid pin format (missing sha256/): %@", cleanPin)
53
- throw SSLPinningError.invalidPinConfiguration(domain: domain)
54
- }
55
-
56
- // Remove sha256/ prefix for TrustKit
57
- cleanPin = cleanPin.replacingOccurrences(of: "sha256/", with: "")
58
-
59
- // Verify base64 format
60
- guard cleanPin.range(of: "^[A-Za-z0-9+/=]+$", options: .regularExpression) != nil else {
61
- NSLog("Invalid pin format (not base64): %@", cleanPin)
62
- throw SSLPinningError.invalidPinConfiguration(domain: domain)
63
- }
64
-
65
- return cleanPin
66
- }
67
- }
68
-
69
- @objc
70
- func initializeSslPinning(_ configJsonString: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
71
- // Check if SSL pinning is enabled
72
- let isSSLPinningEnabled = userDefaults.bool(forKey: useSSLPinningKey)
73
-
74
- if isSSLPinningEnabled {
75
- do {
76
- // Parse JSON configuration
77
- guard let jsonData = configJsonString.data(using: .utf8),
78
- let config = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any],
79
- let sha256Keys = config["sha256Keys"] as? [String: [String]] else {
80
- throw SSLPinningError.invalidConfiguration
81
- }
82
-
83
- // Build pinned domains configuration
84
- var pinnedDomains: [String: Any] = [:]
85
-
86
- // Process each domain and its pins from JSON
87
- for (domain, pins) in sha256Keys {
88
- let cleanedPins = try pins.map { pin -> String in
89
- // Validate and clean the pin
90
- var cleanPin = pin.trimmingCharacters(in: .whitespacesAndNewlines)
91
-
92
- // Verify pin format
93
- guard cleanPin.starts(with: "sha256/") else {
94
- NSLog("Invalid pin format for domain %@: %@", domain, cleanPin)
95
- throw SSLPinningError.invalidPinConfiguration(domain: domain)
96
- }
97
-
98
- // Remove sha256/ prefix for TrustKit
99
- cleanPin = cleanPin.replacingOccurrences(of: "sha256/", with: "")
100
-
101
- return cleanPin
102
- }
103
-
104
- pinnedDomains[domain] = [
105
- kTSKIncludeSubdomains: true,
106
- kTSKEnforcePinning: true,
107
- kTSKDisableDefaultReportUri: true,
108
- kTSKPublicKeyHashes: cleanedPins
109
- ]
110
- }
111
-
112
- let trustKitConfig: [String: Any] = [
113
- kTSKSwizzleNetworkDelegates: true,
114
- kTSKPinnedDomains: pinnedDomains
115
- ]
116
-
117
- DispatchQueue.main.async {
118
- // Initialize TrustKit with the configuration
119
- TrustKit.initSharedInstance(withConfiguration: trustKitConfig)
120
-
121
- // Set up validation callback
122
- TrustKit.sharedInstance().pinningValidatorCallback = { result, notedHostname, policy in
123
- switch result.finalTrustDecision {
124
- case .shouldBlockConnection:
125
- NSLog("⛔️ SSL Pinning failed for domain: %@", notedHostname)
126
- NSLog("Policy details: %@", policy)
127
- case .shouldAllowConnection:
128
- NSLog("✅ SSL Pinning succeeded for domain: %@", notedHostname)
129
- default:
130
- NSLog("⚠️ Unexpected SSL Pinning result for domain: %@", notedHostname)
131
- }
132
- }
133
-
134
- NSLog("✅ TrustKit initialized with config: %@", trustKitConfig)
135
- resolve([
136
- "message": "SSL Pinning initialized successfully",
137
- "domains": Array(pinnedDomains.keys)
138
- ])
139
- }
140
-
141
- } catch let error as SSLPinningError {
142
- NSLog("❌ SSL Pinning Error: %@", error.message)
143
- reject("SSL_PINNING_ERROR", error.message, error)
144
- } catch {
145
- NSLog("❌ Unexpected Error: %@", error.localizedDescription)
146
- reject("SSL_PINNING_ERROR", "Unexpected error during SSL pinning initialization", error)
147
- }
148
- } else {
149
- NSLog("⚠️ SSL Pinning is disabled",isSSLPinningEnabled)
150
- resolve([
151
- "message": "SSL Pinning is disabled",
152
- "domains": [],
153
- "isSSLPinningEnabled": isSSLPinningEnabled
154
- ])
155
- }
156
- }
157
-
158
- @objc
159
- func setUseSSLPinning(_ usePinning: Bool) {
160
- userDefaults.set(usePinning, forKey: useSSLPinningKey)
161
- userDefaults.synchronize()
162
- }
163
-
164
- @objc
165
- func getUseSSLPinning(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
166
- let usePinning = userDefaults.bool(forKey: useSSLPinningKey)
167
- resolve(usePinning)
168
- }
169
- }