@digitalshieldfe/react-native-backup-card-sdk 0.1.1 → 0.1.3

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 (90) hide show
  1. package/README.md +17 -25
  2. package/android/build.gradle +49 -4
  3. package/android/consumer-rules.pro +0 -0
  4. package/android/proguard-rules.pro +21 -0
  5. package/android/src/main/AndroidManifest.xml +4 -1
  6. package/android/src/main/java/com/ziancube/backupcardsdk/BackupCardSdk.kt +478 -0
  7. package/android/src/main/java/com/ziancube/backupcardsdk/GPChannelNatives.java +41 -0
  8. package/android/src/main/java/com/ziancube/backupcardsdk/listener/ApiAsyncListener.java +13 -0
  9. package/android/src/main/java/com/ziancube/backupcardsdk/nfc/ApiNfc.java +173 -0
  10. package/android/src/main/java/com/ziancube/backupcardsdk/nfc/ImplNfc.java +39 -0
  11. package/android/src/main/java/com/ziancube/backupcardsdk/nfc/NfcComm.java +115 -0
  12. package/android/src/main/java/com/ziancube/backupcardsdk/utils/ApduParam.java +67 -0
  13. package/android/src/main/java/com/ziancube/backupcardsdk/utils/CommList.java +41 -0
  14. package/android/src/main/java/com/ziancube/backupcardsdk/utils/Utils.java +109 -0
  15. package/android/src/main/jni/CMakeLists.txt +60 -0
  16. package/android/src/main/jni/GPChannel/include/GPChannelSDK.h +306 -0
  17. package/android/src/main/jni/GPChannel/include/context/BaseContext.h +56 -0
  18. package/android/src/main/jni/GPChannel/include/device/ApduBuilder.hpp +72 -0
  19. package/android/src/main/jni/GPChannel/include/utility/Apdu.hpp +166 -0
  20. package/android/src/main/jni/GPChannel/include/utility/Debug.hpp +59 -0
  21. package/android/src/main/jni/GPChannel/include/utility/Singleton.h +34 -0
  22. package/android/src/main/jni/GPChannel/include/utility/mutex.h +24 -0
  23. package/android/src/main/jni/GPChannel/include/utility/trim.hpp +155 -0
  24. package/android/src/main/jni/GPChannel/include/utility/util.h +104 -0
  25. package/android/src/main/jni/GPChannel/include/utility/xFactory.hpp +26 -0
  26. package/android/src/main/jni/GPChannel/include/utility/xManager.hpp +84 -0
  27. package/android/src/main/jni/GPChannel/src/arm64-v8a/libJUB_GPC_APDU_SDK.a +0 -0
  28. package/android/src/main/jni/GPChannel/src/arm64-v8a/libTrezorCrypto.a +0 -0
  29. package/android/src/main/jni/GPChannel/src/armeabi-v7a/libJUB_GPC_APDU_SDK.a +0 -0
  30. package/android/src/main/jni/GPChannel/src/armeabi-v7a/libTrezorCrypto.a +0 -0
  31. package/android/src/main/jni/GPChannel/src/x86/libJUB_GPC_APDU_SDK.a +0 -0
  32. package/android/src/main/jni/GPChannel/src/x86/libTrezorCrypto.a +0 -0
  33. package/android/src/main/jni/src/implJni.cpp +313 -0
  34. package/android/src/main/jni/src/implJni.h +9 -0
  35. package/android/src/main/jni/utils/jsoncpp/AUTHORS +111 -0
  36. package/android/src/main/jni/utils/jsoncpp/CMakeLists.txt +159 -0
  37. package/android/src/main/jni/utils/jsoncpp/LICENSE +55 -0
  38. package/android/src/main/jni/utils/jsoncpp/README.md +135 -0
  39. package/android/src/main/jni/utils/jsoncpp/amalgamate.py +155 -0
  40. package/android/src/main/jni/utils/jsoncpp/appveyor.yml +22 -0
  41. package/android/src/main/jni/utils/jsoncpp/dev.makefile +35 -0
  42. package/android/src/main/jni/utils/jsoncpp/devtools/__init__.py +6 -0
  43. package/android/src/main/jni/utils/jsoncpp/devtools/agent_vmw7.json +33 -0
  44. package/android/src/main/jni/utils/jsoncpp/devtools/agent_vmxp.json +26 -0
  45. package/android/src/main/jni/utils/jsoncpp/devtools/antglob.py +205 -0
  46. package/android/src/main/jni/utils/jsoncpp/devtools/batchbuild.py +278 -0
  47. package/android/src/main/jni/utils/jsoncpp/devtools/fixeol.py +70 -0
  48. package/android/src/main/jni/utils/jsoncpp/devtools/licenseupdater.py +94 -0
  49. package/android/src/main/jni/utils/jsoncpp/devtools/tarball.py +52 -0
  50. package/android/src/main/jni/utils/jsoncpp/doxybuild.py +189 -0
  51. package/android/src/main/jni/utils/jsoncpp/include/CMakeLists.txt +2 -0
  52. package/android/src/main/jni/utils/jsoncpp/include/json/allocator.h +98 -0
  53. package/android/src/main/jni/utils/jsoncpp/include/json/assertions.h +54 -0
  54. package/android/src/main/jni/utils/jsoncpp/include/json/autolink.h +25 -0
  55. package/android/src/main/jni/utils/jsoncpp/include/json/config.h +187 -0
  56. package/android/src/main/jni/utils/jsoncpp/include/json/features.h +61 -0
  57. package/android/src/main/jni/utils/jsoncpp/include/json/forwards.h +37 -0
  58. package/android/src/main/jni/utils/jsoncpp/include/json/json.h +15 -0
  59. package/android/src/main/jni/utils/jsoncpp/include/json/reader.h +411 -0
  60. package/android/src/main/jni/utils/jsoncpp/include/json/value.h +888 -0
  61. package/android/src/main/jni/utils/jsoncpp/include/json/version.h +20 -0
  62. package/android/src/main/jni/utils/jsoncpp/include/json/writer.h +357 -0
  63. package/android/src/main/jni/utils/jsoncpp/makefiles/vs71/jsontest.vcproj +119 -0
  64. package/android/src/main/jni/utils/jsoncpp/makefiles/vs71/lib_json.vcproj +205 -0
  65. package/android/src/main/jni/utils/jsoncpp/makefiles/vs71/test_lib_json.vcproj +130 -0
  66. package/android/src/main/jni/utils/jsoncpp/makerelease.py +390 -0
  67. package/android/src/main/jni/utils/jsoncpp/meson.build +103 -0
  68. package/android/src/main/jni/utils/jsoncpp/pkg-config/jsoncpp.pc.in +9 -0
  69. package/android/src/main/jni/utils/jsoncpp/src/CMakeLists.txt +5 -0
  70. package/android/src/main/jni/utils/jsoncpp/src/jsontestrunner/CMakeLists.txt +25 -0
  71. package/android/src/main/jni/utils/jsoncpp/src/jsontestrunner/main.cpp +333 -0
  72. package/android/src/main/jni/utils/jsoncpp/src/lib_json/CMakeLists.txt +117 -0
  73. package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_reader.cpp +2060 -0
  74. package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_tool.h +114 -0
  75. package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_value.cpp +1661 -0
  76. package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_valueiterator.inl +167 -0
  77. package/android/src/main/jni/utils/jsoncpp/src/lib_json/json_writer.cpp +1233 -0
  78. package/android/src/main/jni/utils/jsoncpp/src/lib_json/version.h.in +20 -0
  79. package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/CMakeLists.txt +38 -0
  80. package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/jsontest.cpp +457 -0
  81. package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/jsontest.h +286 -0
  82. package/android/src/main/jni/utils/jsoncpp/src/test_lib_json/main.cpp +2606 -0
  83. package/android/src/main/jni/utils/jsoncpp/travis.sh +23 -0
  84. package/android/src/main/jni/utils/jsoncpp/version +1 -0
  85. package/android/src/main/jni/utils/jsoncpp/version.in +1 -0
  86. package/android/src/main/jni/utils/logUtils.cpp +108 -0
  87. package/android/src/main/jni/utils/logUtils.h +87 -0
  88. package/android/src/main/jni/utils/mSIGNA/stdutils/uchar_vector.h +614 -0
  89. package/package.json +2 -3
  90. package/android/libs/backupcardsdk-1.0.0.aar +0 -0
package/README.md CHANGED
@@ -1,45 +1,37 @@
1
- # @digitalshieldfe/react-native-backup-card-sdk
1
+ # react-native-backup-card-sdk
2
2
 
3
- Digital Shield backup card SDK for React Native (Turbo Module).
3
+ ds react-native backup-card sdk
4
4
 
5
5
  ## Installation
6
6
 
7
+
7
8
  ```sh
8
- yarn add @digitalshieldfe/react-native-backup-card-sdk
9
- # or
10
- npm install @digitalshieldfe/react-native-backup-card-sdk
9
+ npm install react-native-backup-card-sdk
11
10
  ```
12
11
 
13
- Android native code (`backupcardsdk` AAR) is **bundled inside this npm package**. Host apps do **not** need `mavenLocal()` or `com.ziancube:backupcardsdk` from Maven Central.
14
12
 
15
13
  ## Usage
16
14
 
17
- ```js
18
- import BackupCardSdk from '@digitalshieldfe/react-native-backup-card-sdk';
19
15
 
20
- const info = await BackupCardSdk.getCardInfo();
21
- ```
22
-
23
- ## Android
16
+ ```js
17
+ import { multiply } from 'react-native-backup-card-sdk';
24
18
 
25
- - AAR path: `android/libs/backupcardsdk-1.0.0.aar`
26
- - Autolinking via React Native / Expo as usual
27
- - NFC permissions and intent filters must be configured in the host app
19
+ // ...
28
20
 
29
- ## Maintainers: update bundled AAR
21
+ const result = multiply(3, 7);
22
+ ```
30
23
 
31
- When `android-sdk/backupcardsdk` changes:
32
24
 
33
- ```sh
34
- cd android-sdk
35
- ./gradlew :backupcardsdk:assembleRelease
25
+ ## Contributing
36
26
 
37
- cd ../rn-sdk
38
- yarn sync:aar
39
- # bump version in package.json, then publish
40
- npm publish --access public
41
- ```
27
+ - [Development workflow](CONTRIBUTING.md#development-workflow)
28
+ - [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
29
+ - [Code of conduct](CODE_OF_CONDUCT.md)
42
30
 
43
31
  ## License
44
32
 
45
33
  MIT
34
+
35
+ ---
36
+
37
+ Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -15,6 +15,7 @@ buildscript {
15
15
  }
16
16
 
17
17
  repositories {
18
+ mavenLocal()
18
19
  google()
19
20
  mavenCentral()
20
21
  }
@@ -40,6 +41,31 @@ android {
40
41
  defaultConfig {
41
42
  minSdkVersion getExtOrDefault("minSdkVersion")
42
43
  targetSdkVersion getExtOrDefault("targetSdkVersion")
44
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
45
+ consumerProguardFiles "consumer-rules.pro"
46
+
47
+ externalNativeBuild {
48
+ cmake {
49
+ cppFlags(
50
+ "",
51
+ "-std=c++11",
52
+ "-frtti",
53
+ "-fexceptions",
54
+ "-DHAVE_ENDIAN_H"
55
+ )
56
+
57
+ arguments(
58
+ "-DANDROID_TOOLCHAIN=clang",
59
+ "-DANDROID_STL=c++_static",
60
+ "-DANDROID_ARM_MODE=arm",
61
+ "-DANDROID_PLATFORM=android-19"
62
+ )
63
+ }
64
+ }
65
+
66
+ ndk {
67
+ abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
68
+ }
43
69
  }
44
70
 
45
71
  buildFeatures {
@@ -49,6 +75,10 @@ android {
49
75
  buildTypes {
50
76
  release {
51
77
  minifyEnabled false
78
+ proguardFiles(
79
+ getDefaultProguardFile("proguard-android-optimize.txt"),
80
+ "proguard-rules.pro"
81
+ )
52
82
  }
53
83
  }
54
84
 
@@ -57,13 +87,28 @@ android {
57
87
  }
58
88
 
59
89
  compileOptions {
60
- sourceCompatibility JavaVersion.VERSION_1_8
61
- targetCompatibility JavaVersion.VERSION_1_8
90
+ sourceCompatibility JavaVersion.VERSION_11
91
+ targetCompatibility JavaVersion.VERSION_11
92
+ }
93
+
94
+ externalNativeBuild {
95
+ cmake {
96
+ path = file("src/main/jni/CMakeLists.txt")
97
+ }
98
+ }
99
+
100
+ publishing {
101
+ singleVariant("release") {
102
+ withSourcesJar()
103
+ }
62
104
  }
63
105
  }
64
106
 
65
107
  dependencies {
66
- // Bundled in npm; update via: yarn sync:aar (after android-sdk release build)
67
- implementation(files("libs/backupcardsdk-1.0.0.aar"))
108
+ implementation("androidx.appcompat:appcompat:1.6.1")
109
+ implementation("com.google.android.material:material:1.12.0")
68
110
  implementation("com.facebook.react:react-android")
111
+ testImplementation("junit:junit:4.13.2")
112
+ androidTestImplementation("androidx.test.ext:junit:1.1.5")
113
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
69
114
  }
File without changes
@@ -0,0 +1,21 @@
1
+ # Add project specific ProGuard rules here.
2
+ # You can control the set of applied configuration files using the
3
+ # proguardFiles setting in build.gradle.
4
+ #
5
+ # For more details, see
6
+ # http://developer.android.com/guide/developing/tools/proguard.html
7
+
8
+ # If your project uses WebView with JS, uncomment the following
9
+ # and specify the fully qualified class name to the JavaScript interface
10
+ # class:
11
+ #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12
+ # public *;
13
+ #}
14
+
15
+ # Uncomment this to preserve the line number information for
16
+ # debugging stack traces.
17
+ #-keepattributes SourceFile,LineNumberTable
18
+
19
+ # If you keep the line number information, uncomment this to
20
+ # hide the original source file name.
21
+ #-renamesourcefileattribute SourceFile
@@ -1,2 +1,5 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
1
2
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
- </manifest>
3
+ <uses-permission android:name="android.permission.NFC" />
4
+ <uses-feature android:name="android.hardware.nfc" android:required="false" />
5
+ </manifest>
@@ -0,0 +1,478 @@
1
+ package com.ziancube.backupcardsdk
2
+
3
+ import android.app.Activity
4
+ import android.app.Application
5
+ import android.text.TextUtils;
6
+ import android.content.Intent
7
+ import android.nfc.NfcAdapter
8
+ import android.os.Bundle
9
+ import androidx.core.util.Consumer
10
+ import com.ziancube.backupcardsdk.listener.ApiAsyncListener
11
+ import com.ziancube.backupcardsdk.nfc.ApiNfc
12
+ import org.json.JSONObject
13
+ import kotlin.coroutines.resume
14
+ import kotlin.coroutines.suspendCoroutine
15
+ import com.ziancube.backupcardsdk.utils.ApduParam
16
+ import com.ziancube.backupcardsdk.utils.Utils
17
+
18
+ interface ApduLogger {
19
+ fun log(message: String, isSent: Boolean, isSuccess: Boolean = true)
20
+ }
21
+
22
+ interface NfcTouchListener {
23
+ fun onTouch(isBackupCard: Boolean)
24
+ }
25
+
26
+ data class ApduResult(val resultCode: Int, val data: String?)
27
+ data class CardInfo(val serialNumber: String?, val pinRetryCount: Int?, val isNewCard: Boolean?)
28
+
29
+ class BackupCardSdk(
30
+ private val activity: Activity,
31
+ private val apduLogger: ApduLogger,
32
+ private val nfcTouchListener: NfcTouchListener
33
+ ) {
34
+ private val apiNfc = ApiNfc.getInstance(activity)
35
+ private val OCE_CRT =
36
+ "7f2181bc93036170704209646576656c6f7065725f2003617070950200805f2504202605265f24042036052653007f4946b041044f07c304cd5ff2d89bfc28771fe08be408563c58108cb8010e8788c6683bf693d70f62fb7c1f9195b18972b6cf6b91f45ba15818ea72533500a06deb55306400f001005f3746304402204cfd10dd22babed4c1a422a4cfadd02df9ac89436c309cf51ea64526c48a2afb022033ca1b474f3915c44739ed40bc30d8f4aa442718c042f2c3054675ed9df61215";
37
+ private val AID = "6469676974736869656c64" // digitalshield
38
+ private var needReconnect = true;
39
+ private val application = activity.application
40
+
41
+ private val lifecycleCallbacks =
42
+ object : Application.ActivityLifecycleCallbacks {
43
+ override fun onActivityResumed(target: Activity) {
44
+ if (target === activity) {
45
+ apiNfc.onResume()
46
+ }
47
+ }
48
+
49
+ override fun onActivityPaused(target: Activity) {
50
+ if (target === activity) {
51
+ apiNfc.onPause()
52
+ }
53
+ }
54
+
55
+ override fun onActivityDestroyed(target: Activity) {
56
+ if (target === activity) {
57
+ apiNfc.onDestroy()
58
+ }
59
+ }
60
+
61
+ override fun onActivityCreated(a: Activity, b: Bundle?) {}
62
+ override fun onActivityStarted(a: Activity) {}
63
+ override fun onActivityStopped(a: Activity) {}
64
+ override fun onActivitySaveInstanceState(a: Activity, b: Bundle) {}
65
+ }
66
+
67
+ init {
68
+ handleIntent(activity.intent)
69
+ application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
70
+ }
71
+
72
+ fun release() {
73
+ application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
74
+ }
75
+
76
+ fun handleIntent(intent: Intent?) {
77
+ if (intent == null || !isNfcIntent(intent)) {
78
+ return
79
+ }
80
+ needReconnect = true
81
+ val re = apiNfc.setCardTag(intent)
82
+ if (re == 0) {
83
+ nfcTouchListener.onTouch(true)
84
+ } else {
85
+ nfcTouchListener.onTouch(false)
86
+ }
87
+ }
88
+
89
+ private fun isNfcIntent(intent: Intent): Boolean {
90
+ return intent.action == NfcAdapter.ACTION_TAG_DISCOVERED ||
91
+ intent.action == NfcAdapter.ACTION_NDEF_DISCOVERED ||
92
+ intent.action == NfcAdapter.ACTION_TECH_DISCOVERED
93
+ }
94
+
95
+ private fun buildApdu(cla: Long,ins: Long,p1: Long,p2: Long,data: String,isSecureChannel: Boolean): ByteArray? {
96
+ if (isSecureChannel) {
97
+ val safeApdu = GPChannelNatives.nativeGPCBuildSafeAPDU(cla, ins, p1, p2, data)
98
+ apduLogger.log(safeApdu, true)
99
+ return Utils.hexString2Bytes(safeApdu)
100
+ }
101
+
102
+ val apdu = GPChannelNatives.nativeGPCBuildAPDU(cla, ins, p1, p2, data)
103
+ apduLogger.log(apdu, true)
104
+ return Utils.hexString2Bytes(apdu)
105
+ }
106
+
107
+ private fun parseResponse(resp: String, isSecureChannel: Boolean): ApduResult? {
108
+ val res = if (isSecureChannel) {
109
+ GPChannelNatives.nativeGPCParseSafeAPDUResponse(resp)
110
+ } else {
111
+ GPChannelNatives.nativeGPCParseAPDUResponse(resp)
112
+ }
113
+ val apdu_result = toApduResult(res, -1)
114
+ apduLogger.log(resp, false, apdu_result.resultCode == 0x9000)
115
+ return apdu_result
116
+ }
117
+
118
+ private fun toApduResult(parsedResponse: String?, fallbackCode: Int): ApduResult {
119
+ if (parsedResponse.isNullOrBlank()) {
120
+ return ApduResult(fallbackCode, null)
121
+ }
122
+
123
+ return runCatching {
124
+ val json = JSONObject(parsedResponse)
125
+ val response = json.optString("response").takeIf { it.isNotEmpty() }
126
+ val wRet = json.optInt("wRet", fallbackCode)
127
+ ApduResult(wRet, response)
128
+ }.getOrElse {
129
+ ApduResult(fallbackCode, parsedResponse)
130
+ }
131
+ }
132
+
133
+ suspend private fun sendApdu(apduParam: ApduParam): ApduResult {
134
+ val apdu_bytes = buildApdu(
135
+ apduParam.cla,
136
+ apduParam.ins,
137
+ apduParam.p1,
138
+ apduParam.p2,
139
+ apduParam.data,
140
+ apduParam.isSecureChannel
141
+ ) ?: run {
142
+ apduLogger.log("Failed to build APDU", false)
143
+ return ApduResult(-1, null)
144
+ }
145
+
146
+ return suspendCoroutine { continuation ->
147
+ apiNfc.transInstructions(
148
+ apdu_bytes,
149
+ object : ApiAsyncListener<String> {
150
+ override fun onUiChange() {}
151
+
152
+ override fun onResult(resultCode: Int, result: String?) {
153
+ if (resultCode == 0 && result != null) {
154
+ var apdu_result = parseResponse(result, apduParam.isSecureChannel)
155
+ if (apdu_result != null) {
156
+ continuation.resume(apdu_result)
157
+ } else {
158
+ needReconnect = true
159
+ continuation.resume(ApduResult(-1, null))
160
+ }
161
+ } else {
162
+ needReconnect = true
163
+ continuation.resume(ApduResult(resultCode, null))
164
+ }
165
+ }
166
+ }
167
+ )
168
+ }
169
+ }
170
+
171
+ suspend private fun selectApplet(): Boolean {
172
+ val apduSelectMf = ApduParam(0x00, 0xa4, 0x04, 0x00, "", false)
173
+ var result = sendApdu(apduSelectMf)
174
+ if(result.resultCode !=0x9000) {
175
+ return false
176
+ }
177
+ val apduSelectApplet = ApduParam(0x00, 0xa4, 0x04, 0x00, AID, false)
178
+ result = sendApdu(apduSelectApplet)
179
+ return result.resultCode == 0x9000
180
+ }
181
+
182
+ suspend private fun openSecureChannel(): Boolean {
183
+ val apdu1 = ApduParam(0x80, 0xCA, 0xBF, 0x21, "A60483021518", false)
184
+ var result = sendApdu(apdu1)
185
+ if (result.resultCode != 0x9000 || result.data == null) {
186
+ return false
187
+ }
188
+ runCatching {
189
+ val cert = GPChannelNatives.nativeGPCTLVDecode(result.data)
190
+ if (!TextUtils.isEmpty(cert)) {
191
+ val certJson = JSONObject(cert)
192
+ val subject = GPChannelNatives.nativeGPCParseCertificate(certJson.getString("value"))
193
+ if (!TextUtils.isEmpty(subject)) {
194
+ val subjectJson = JSONObject(subject)
195
+ val conf = JSONObject().apply {
196
+ put("scpID", 0x1107)
197
+ put("keyUsage", 0x3C)
198
+ put("keyType", 0x88)
199
+ put("keyLength", 16)
200
+ put("hostID", "8080808080808080")
201
+ put("cardGroupID", subjectJson.getString("subjectID"))
202
+ }
203
+ val initResult = GPChannelNatives.nativeGPCInitialize(conf.toString())
204
+ if (initResult !=0) {
205
+ return false
206
+ }
207
+ } else {
208
+ return false
209
+ }
210
+ } else {
211
+ return false
212
+ }
213
+ }.onFailure {
214
+ return false
215
+ }
216
+
217
+ var apdu2 = ApduParam(0x80, 0x2A, 0x18, 0x10, "", false)
218
+ apdu2.setData(OCE_CRT)
219
+ result = sendApdu(apdu2)
220
+ if (result.resultCode != 0x9000) {
221
+ return false
222
+ }
223
+ val authData = GPChannelNatives.nativeGPCBuildMutualAuthData()
224
+
225
+ var aupd3 = ApduParam(0x80, 0x82, 0x18, 0x15, "", false)
226
+ aupd3.setData(authData)
227
+ result = sendApdu(aupd3)
228
+ if (result.resultCode != 0x9000) {
229
+ return false
230
+ }
231
+
232
+ val open_ret = GPChannelNatives.nativeGPCOpenSecureChannel(result.data);
233
+ if (open_ret != 0) {
234
+ return false
235
+ }
236
+
237
+ return true
238
+ }
239
+
240
+ suspend private fun getSerialNumber(): String? {
241
+
242
+ val apduGetSn = ApduParam(0x80, 0xCB, 0x80, 0x00, "DFFF028101", true)
243
+ val result = sendApdu(apduGetSn)
244
+ if (result.resultCode != 0x9000 || result.data == null) {
245
+ return null
246
+ }
247
+ val serialBytes = Utils.hexString2Bytes(result.data) ?: return null
248
+ return String(serialBytes, Charsets.UTF_8)
249
+ }
250
+
251
+ suspend private fun getPinRetryCount(): Int? {
252
+
253
+ val apduGetPin = ApduParam(0x80, 0xCB, 0x80, 0x00, "DFFF028102", true)
254
+ val result = sendApdu(apduGetPin)
255
+ if (result.resultCode != 0x9000 || result.data == null) {
256
+ return null
257
+ }
258
+ val pinBytes = Utils.hexString2Bytes(result.data) ?: return null
259
+ if (pinBytes.isEmpty()) {
260
+ return null
261
+ }
262
+ return pinBytes[0].toInt() and 0xFF
263
+ }
264
+
265
+ suspend private fun getPinStatus(): Boolean? {
266
+ val apduGetStatus = ApduParam(0x80, 0xCB, 0x80, 0x00, "DFFF028105", true)
267
+ val result = sendApdu(apduGetStatus)
268
+ if (result.resultCode != 0x9000 || result.data == null) {
269
+ return null
270
+ }
271
+ val statusBytes = Utils.hexString2Bytes(result.data) ?: return null
272
+ if (statusBytes.isEmpty()) {
273
+ return null
274
+ }
275
+ return statusBytes[0].toInt() == 0x02
276
+ }
277
+
278
+ suspend fun getCardInfo(): CardInfo? {
279
+ if(needReconnect) {
280
+ GPChannelNatives.nativeGPCFinalize()
281
+ if (!selectApplet()) return null
282
+ if (!openSecureChannel()) return null
283
+ needReconnect = false
284
+ }
285
+
286
+ val serialNumber = getSerialNumber()
287
+ val pinRetryCount = getPinRetryCount()
288
+ val isNewCard = getPinStatus()
289
+ return CardInfo(serialNumber, pinRetryCount, isNewCard)
290
+ }
291
+
292
+ suspend fun resetCard():Boolean{
293
+ if(needReconnect){
294
+ GPChannelNatives.nativeGPCFinalize()
295
+ if (!selectApplet()) return false
296
+ if (!openSecureChannel()) return false
297
+ needReconnect = false
298
+ }
299
+ var apduReset = ApduParam(0x80, 0xCB, 0x80, 0x00, "DFFE028205", true);
300
+ val result = sendApdu(apduReset)
301
+ if (result.resultCode != 0x9000) {
302
+ return false
303
+ }
304
+ needReconnect = true
305
+ return true
306
+ }
307
+
308
+ suspend fun activateCard(pwd:String):Boolean{
309
+ if(needReconnect){
310
+ GPChannelNatives.nativeGPCFinalize()
311
+ if (!selectApplet()) return false
312
+ if (!openSecureChannel()) return false
313
+ needReconnect = false
314
+ }
315
+ val pinTLV = "00" + Utils.buildTLV(null, Utils.stringToHexString(pwd))
316
+ val dataTLV = Utils.buildTLV("8204", pinTLV)
317
+ val apduTLV = Utils.buildTLV("DFFE", dataTLV)
318
+ var apduActivate = ApduParam(0x80, 0xCB, 0x80, 0x00, apduTLV, true);
319
+ val result = sendApdu(apduActivate)
320
+ if (result.resultCode != 0x9000) {
321
+ return false
322
+ }
323
+ return true
324
+ }
325
+
326
+ suspend fun changePin(oldPin: String, newPin: String): Boolean {
327
+ if(needReconnect){
328
+ GPChannelNatives.nativeGPCFinalize()
329
+ if (!selectApplet()) return false
330
+ if (!openSecureChannel()) return false
331
+ needReconnect = false
332
+ }
333
+ val oldPinTLV = Utils.buildTLV(null, Utils.stringToHexString(oldPin))
334
+ val newPinTLV = Utils.buildTLV(null, Utils.stringToHexString(newPin))
335
+ val dataTLV = Utils.buildTLV("8204", oldPinTLV + newPinTLV)
336
+ val apduTLV = Utils.buildTLV("DFFE", dataTLV)
337
+ var apduChangePin = ApduParam(0x80, 0xCB, 0x80, 0x00, apduTLV, true);
338
+ val result = sendApdu(apduChangePin)
339
+ if (result.resultCode != 0x9000) {
340
+ return false
341
+ }
342
+ return true
343
+ }
344
+
345
+ suspend private fun verifyPin(pin: String): Boolean {
346
+ if(needReconnect){
347
+ GPChannelNatives.nativeGPCFinalize()
348
+ if (!selectApplet()) return false
349
+ if (!openSecureChannel()) return false
350
+ needReconnect = false
351
+ }
352
+ val pinTLV = Utils.buildTLV(null, Utils.stringToHexString(pin))
353
+ var apduVerifyPin = ApduParam(0x80, 0x20, 0x00, 0x00, pinTLV, true);
354
+ val result = sendApdu(apduVerifyPin)
355
+ if (result.resultCode != 0x9000) {
356
+ return false
357
+ }
358
+ return true
359
+ }
360
+
361
+ suspend private fun logout(): Boolean {
362
+ if(needReconnect){
363
+ GPChannelNatives.nativeGPCFinalize()
364
+ if (!selectApplet()) return false
365
+ if (!openSecureChannel()) return false
366
+ needReconnect = false
367
+ }
368
+ var apduLogout = ApduParam(0x80, 0x21, 0x00, 0x00, "", true);
369
+ val result = sendApdu(apduLogout)
370
+ if (result.resultCode != 0x9000) {
371
+ return false
372
+ }
373
+ return true
374
+ }
375
+
376
+ suspend fun checkSlotEmpty(slotIndex: Int, pwd: String): Boolean? {
377
+ if (slotIndex !in 0..39) {
378
+ return null
379
+ }
380
+ if(needReconnect){
381
+ GPChannelNatives.nativeGPCFinalize()
382
+ if (!selectApplet()) return null
383
+ if (!openSecureChannel()) return null
384
+ needReconnect = false
385
+ }
386
+ if (!verifyPin(pwd)) {
387
+ return null
388
+ }
389
+ val apduCheck = ApduParam(0x80, 0x6A, 0x00, 0x00, "", true);
390
+ val result = sendApdu(apduCheck)
391
+ if (result.resultCode != 0x9000 || result.data == null) {
392
+ return null
393
+ }
394
+ val checkBytes = Utils.hexString2Bytes(result.data) ?: return null
395
+ if (checkBytes.size < 5) {
396
+ return null
397
+ }
398
+ val byteIndex = slotIndex / 8
399
+ val bitIndex = slotIndex % 8
400
+ val value = checkBytes[byteIndex].toInt() and 0xFF
401
+ return ((value ushr bitIndex) and 0x01) == 0x00
402
+ }
403
+
404
+ suspend fun writeSlot(slotIndex: Int, data: ByteArray,pwd: String): Boolean {
405
+ if (slotIndex !in 0..39) {
406
+ return false
407
+ }
408
+ if (data.size > 231) {
409
+ return false
410
+ }
411
+
412
+ if(needReconnect){
413
+ GPChannelNatives.nativeGPCFinalize()
414
+ if (!selectApplet()) return false
415
+ if (!openSecureChannel()) return false
416
+ needReconnect = false
417
+ }
418
+
419
+ return try {
420
+ if(!verifyPin(pwd)) {
421
+ return false
422
+ }
423
+
424
+ var apduWrite = ApduParam(0x80, 0x3B, 0x00, slotIndex.toLong(), Utils.bytesToHexString(data), true);
425
+ val result = sendApdu(apduWrite)
426
+ if (result.resultCode != 0x9000) {
427
+ return false
428
+ }
429
+ true
430
+ } catch (e: Exception) {
431
+ false
432
+ } finally {
433
+ runCatching { logout() }
434
+ }
435
+ }
436
+
437
+ suspend fun readSlot(slotIndex: Int, pwd: String): ByteArray? {
438
+ if (slotIndex !in 0..39) {
439
+ return null
440
+ }
441
+ if (needReconnect) {
442
+ GPChannelNatives.nativeGPCFinalize()
443
+ if (!selectApplet()) return null
444
+ if (!openSecureChannel()) return null
445
+ needReconnect = false
446
+ }
447
+
448
+ return try {
449
+ if (!verifyPin(pwd)) {
450
+ null
451
+ } else {
452
+ val apduRead = ApduParam(0x80, 0x4B, 0x00, slotIndex.toLong(), "", true)
453
+ val result = sendApdu(apduRead)
454
+ if (result.resultCode != 0x9000 || result.data == null) {
455
+ null
456
+ } else {
457
+ Utils.hexString2Bytes(result.data)
458
+ }
459
+ }
460
+ } catch (e: Exception) {
461
+ null
462
+ } finally {
463
+ runCatching { logout() }
464
+ }
465
+ }
466
+ fun onActivityResumed(){
467
+ apiNfc.onResume()
468
+ }
469
+
470
+ fun onActivityPaused(){
471
+ apiNfc.onPause()
472
+ }
473
+
474
+ fun onActivityDestroyed(){
475
+ apiNfc.onDestroy()
476
+ }
477
+
478
+ }
@@ -0,0 +1,41 @@
1
+ package com.ziancube.backupcardsdk;
2
+
3
+ /**
4
+ * @Date 2020-07-09 16:29
5
+ * @Author ZJF
6
+ * @Version 1.0
7
+ */
8
+ public class GPChannelNatives {
9
+
10
+ static {
11
+ System.loadLibrary("gpchannelNDK");
12
+ }
13
+
14
+ /**
15
+ * 当native接口的返回值不是int时,需要调用该接口获取错误码
16
+ *
17
+ * @return
18
+ */
19
+ public static native int nativeGetErrorCode();
20
+
21
+ public static native int nativeGPCInitialize(String json);
22
+
23
+ public static native int nativeGPCFinalize();
24
+
25
+ public static native String nativeGPCBuildMutualAuthData();
26
+
27
+ public static native int nativeGPCOpenSecureChannel(String response);
28
+
29
+ public static native String nativeGPCBuildAPDU(long cla, long ins, long p1, long p2, String data);
30
+
31
+ public static native String nativeGPCBuildSafeAPDU(long cla, long ins, long p1, long p2, String data);
32
+
33
+ public static native String nativeGPCParseSafeAPDUResponse(String response);
34
+
35
+ public static native String nativeGPCParseAPDUResponse(String response);
36
+
37
+ public static native String nativeGPCTLVDecode(String apdu);
38
+
39
+ public static native String nativeGPCParseCertificate(String cert);
40
+
41
+ }