@networkinternational/ni-card-management-sdk 2.0.1 → 2.1.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/README.md
CHANGED
|
@@ -698,6 +698,54 @@ A NICardManagement wrapper is used to integrate the Network International SDK in
|
|
|
698
698
|
|
|
699
699
|
- the android NICardManagement wrapper can be find inside the __./android/src/main/java/com/nicardmanagement__ folder.
|
|
700
700
|
|
|
701
|
+
### Code shrinking and obfuscation (ProGuard / R8 / DexGuard)
|
|
702
|
+
|
|
703
|
+
The Android card-management flows generate an in-memory, self-signed X.509 certificate with BouncyCastle and use its key pair for encryption and decryption. `BouncyCastleProvider` resolves every algorithm reflectively by class name (for example `org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings`). If those classes are renamed, removed or encrypted by a shrinker, the lookup fails and every SDK operation reports:
|
|
704
|
+
|
|
705
|
+
```
|
|
706
|
+
No provider succeeded to generate a self-signed certificate. See debug log for the root cause.
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
The real cause is only visible via `adb logcat -s SelfSignedCertificate:D`.
|
|
710
|
+
|
|
711
|
+
#### R8 and ProGuard
|
|
712
|
+
|
|
713
|
+
No action is required. Native Android SDK `2.3.0` and later declare the necessary keep rules through `consumerProguardFiles`, and they are merged into your application's shrinker configuration automatically, including under R8 full mode. Do not add `-dontobfuscate` workarounds or remove those rules.
|
|
714
|
+
|
|
715
|
+
If you are pinned to an older SDK release that predates those rules, add them to your own `proguard-rules.pro`:
|
|
716
|
+
|
|
717
|
+
```
|
|
718
|
+
-keep class org.bouncycastle.** { *; }
|
|
719
|
+
-dontwarn org.bouncycastle.**
|
|
720
|
+
-keepclassmembers class * extends java.security.Provider { <init>(...); }
|
|
721
|
+
-keep class ae.network.nicardmanagementsdk.** { *; }
|
|
722
|
+
-keepclassmembers class ae.network.nicardmanagementsdk.** { *; }
|
|
723
|
+
-keepattributes Exceptions, InnerClasses, Signature, EnclosingMethod, *Annotation*
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
#### DexGuard
|
|
727
|
+
|
|
728
|
+
DexGuard applies the packaged consumer rules as well, but its additional protections are not covered by keep rules. Exclude the cryptography classes from name obfuscation, class encryption, string encryption and reflection obfuscation in your DexGuard configuration:
|
|
729
|
+
|
|
730
|
+
```
|
|
731
|
+
-keep,allowoptimization class org.bouncycastle.** { *; }
|
|
732
|
+
-keep,allowoptimization class ae.network.nicardmanagementsdk.** { *; }
|
|
733
|
+
|
|
734
|
+
# Do not apply DexGuard encryption or reflection obfuscation to these packages.
|
|
735
|
+
-keepresourcefiles META-INF/services/**
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
In addition, make sure `org.bouncycastle.**` and `ae.network.nicardmanagementsdk.**` are not listed in any `-encryptclasses`, `-encryptstrings` or `-obfuscatereflection` directive, and that `META-INF/services` entries are retained when repackaging.
|
|
739
|
+
|
|
740
|
+
#### Verifying a protected build
|
|
741
|
+
|
|
742
|
+
1. Build a minified release: `yarn workspace react-native-ni-card-management-example build:android:release`.
|
|
743
|
+
2. Confirm BouncyCastle survived: `grep org.bouncycastle example/android/app/build/outputs/mapping/release/mapping.txt` should list unrenamed classes.
|
|
744
|
+
3. Confirm a single BouncyCastle version is on the classpath: `cd example/android && ./gradlew :app:dependencies --configuration releaseRuntimeClasspath | grep -i bouncy`.
|
|
745
|
+
4. Run Card Details, Set PIN, Verify PIN, Change PIN and View PIN against the release build.
|
|
746
|
+
|
|
747
|
+
The example application keeps `minifyEnabled` and R8 full mode enabled for release builds, with an intentionally empty `example/android/app/proguard-rules.pro`, so it acts as a regression guard for the keep rules shipped by the native SDK.
|
|
748
|
+
|
|
701
749
|
### Inspecting network traffic
|
|
702
750
|
|
|
703
751
|
Card-management operations cross the React Native bridge and execute inside the native `NICardManagementSDK`. They are not JavaScript `fetch` or `XMLHttpRequest` calls, so use the native platform inspector when investigating Card Details, Set PIN, Verify PIN, Change PIN, or View PIN traffic.
|
|
@@ -747,7 +795,7 @@ Inspect only test or UAT traffic. Requests can contain authentication tokens, ca
|
|
|
747
795
|
- CocoaPods source tags use `v{version}` format and are resolved from `repository` metadata (fallback to `homepage`).
|
|
748
796
|
- Android native SDK version is centralized in `android/gradle.properties` via `NiCardManagement_nativeSdkVersion`.
|
|
749
797
|
- iOS native SDK version is pinned in `react-native-ni-card-management.podspec` via `s.dependency "NICardManagementSDK", '...'`; keep this aligned with `NiCardManagement_nativeSdkVersion`.
|
|
750
|
-
- Current validated native pins are Android `2.
|
|
798
|
+
- Current validated native pins are Android `2.3.0` (`NiCardManagement_nativeSdkVersion`) and iOS `2.1.7` (`NICardManagementSDK` pod dependency).
|
|
751
799
|
- Android library-side New Architecture is opt-in via `NiCardManagement_newArchEnabled`; keep it disabled by default so app-level `newArchEnabled=true` does not make the SDK module run React codegen for third-party dependency specs (which can cause duplicate generated classes such as `RNCSafeAreaProviderManagerDelegate`).
|
|
752
800
|
- Flipper was a desktop debugging platform for inspecting network traffic, logs, React components, layouts, and databases. React Native no longer includes the generated Flipper integration in current templates, so the obsolete, release-only `ReactNativeFlipper.java` no-op scaffold was removed. It did not initialize Flipper or import Flipper libraries, and no Flipper dependency remains in the JavaScript, Android, or iOS dependency graphs. Use React Native DevTools for the supported debugging workflow; removing the scaffold does not affect application runtime behavior.
|
|
753
801
|
- Jetifier rewrites dependencies from the legacy Android Support Library (`android.support.*`) to AndroidX (`androidx.*`). It is disabled because the current dependency graph is AndroidX-native, avoiding unnecessary transformation during builds. Restore `android.enableJetifier=true` only if a future dependency still contains legacy support-library references and fails to build without rewriting.
|
package/android/build.gradle
CHANGED
|
@@ -2,5 +2,5 @@ NiCardManagement_kotlinVersion=1.7.0
|
|
|
2
2
|
NiCardManagement_minSdkVersion=21
|
|
3
3
|
NiCardManagement_targetSdkVersion=31
|
|
4
4
|
NiCardManagement_compileSdkVersion=31
|
|
5
|
-
NiCardManagement_nativeSdkVersion=2.
|
|
5
|
+
NiCardManagement_nativeSdkVersion=2.3.0
|
|
6
6
|
NiCardManagement_ndkversion=21.4.7075529
|
|
@@ -21,6 +21,18 @@ class NiCardManagementModule(reactContext: ReactApplicationContext) :
|
|
|
21
21
|
return NAME
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// The native SDK can wrap root causes (e.g. a stripped BouncyCastle provider) in generic
|
|
25
|
+
// messages, so the whole chain is reported when there is one.
|
|
26
|
+
private fun describe(throwable: Throwable): String {
|
|
27
|
+
val chain = generateSequence(throwable) { it.cause }.toList()
|
|
28
|
+
if (chain.size == 1) {
|
|
29
|
+
return throwable.message ?: throwable::class.java.simpleName
|
|
30
|
+
}
|
|
31
|
+
return chain.joinToString(" | caused by ") {
|
|
32
|
+
"${it::class.java.simpleName}: ${it.message ?: "no message"}"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
@ReactMethod
|
|
25
37
|
fun getCardDetails(inputJsonString: String, cb: Callback) {
|
|
26
38
|
val scope = CoroutineScope(Dispatchers.Main)
|
|
@@ -47,7 +59,7 @@ class NiCardManagementModule(reactContext: ReactApplicationContext) :
|
|
|
47
59
|
cb.invoke("Error parsing input JSON", null)
|
|
48
60
|
}
|
|
49
61
|
} catch (e: Exception) {
|
|
50
|
-
cb.invoke(e
|
|
62
|
+
cb.invoke(describe(e), null)
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
65
|
}
|
|
@@ -74,7 +86,7 @@ class NiCardManagementModule(reactContext: ReactApplicationContext) :
|
|
|
74
86
|
cb.invoke("Error parsing input JSON", null)
|
|
75
87
|
}
|
|
76
88
|
} catch (e: Exception) {
|
|
77
|
-
cb.invoke(e
|
|
89
|
+
cb.invoke(describe(e), null)
|
|
78
90
|
}
|
|
79
91
|
}
|
|
80
92
|
}
|
|
@@ -100,7 +112,7 @@ class NiCardManagementModule(reactContext: ReactApplicationContext) :
|
|
|
100
112
|
cb.invoke("Error parsing input JSON", null)
|
|
101
113
|
}
|
|
102
114
|
} catch (e: Exception) {
|
|
103
|
-
cb.invoke(e
|
|
115
|
+
cb.invoke(describe(e), null)
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
}
|
|
@@ -126,7 +138,7 @@ class NiCardManagementModule(reactContext: ReactApplicationContext) :
|
|
|
126
138
|
cb.invoke("Error parsing input JSON", null)
|
|
127
139
|
}
|
|
128
140
|
} catch (e: Exception) {
|
|
129
|
-
cb.invoke(e
|
|
141
|
+
cb.invoke(describe(e), null)
|
|
130
142
|
}
|
|
131
143
|
}
|
|
132
144
|
}
|
|
@@ -152,7 +164,7 @@ class NiCardManagementModule(reactContext: ReactApplicationContext) :
|
|
|
152
164
|
cb.invoke("Error parsing input JSON", null)
|
|
153
165
|
}
|
|
154
166
|
} catch (e: Exception) {
|
|
155
|
-
cb.invoke(e
|
|
167
|
+
cb.invoke(describe(e), null)
|
|
156
168
|
}
|
|
157
169
|
}
|
|
158
170
|
}
|
package/package.json
CHANGED