@pagopa/io-react-native-cie 1.0.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.
Files changed (48) hide show
  1. package/IoReactNativeCie.podspec +28 -0
  2. package/LICENSE +201 -0
  3. package/README.md +406 -0
  4. package/android/build.gradle +83 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +3 -0
  7. package/android/src/main/AndroidManifestNew.xml +2 -0
  8. package/android/src/main/java/com/pagopa/ioreactnativecie/IoReactNativeCieModule.kt +302 -0
  9. package/android/src/main/java/com/pagopa/ioreactnativecie/IoReactNativeCiePackage.kt +17 -0
  10. package/android/src/main/java/com/pagopa/ioreactnativecie/cie/Atr.kt +39 -0
  11. package/android/src/main/java/com/pagopa/ioreactnativecie/cie/CieType.kt +157 -0
  12. package/ios/CIEType.swift +81 -0
  13. package/ios/IoReactNativeCie-Bridging-Header.h +2 -0
  14. package/ios/IoReactNativeCie.mm +43 -0
  15. package/ios/IoReactNativeCie.swift +227 -0
  16. package/lib/module/errors.js +2 -0
  17. package/lib/module/errors.js.map +1 -0
  18. package/lib/module/index.js +6 -0
  19. package/lib/module/index.js.map +1 -0
  20. package/lib/module/manager/index.js +149 -0
  21. package/lib/module/manager/index.js.map +1 -0
  22. package/lib/module/manager/types.js +50 -0
  23. package/lib/module/manager/types.js.map +1 -0
  24. package/lib/module/native.js +13 -0
  25. package/lib/module/native.js.map +1 -0
  26. package/lib/module/package.json +1 -0
  27. package/lib/module/utils/index.js +45 -0
  28. package/lib/module/utils/index.js.map +1 -0
  29. package/lib/typescript/package.json +1 -0
  30. package/lib/typescript/src/errors.d.ts +24 -0
  31. package/lib/typescript/src/errors.d.ts.map +1 -0
  32. package/lib/typescript/src/index.d.ts +6 -0
  33. package/lib/typescript/src/index.d.ts.map +1 -0
  34. package/lib/typescript/src/manager/index.d.ts +113 -0
  35. package/lib/typescript/src/manager/index.d.ts.map +1 -0
  36. package/lib/typescript/src/manager/types.d.ts +83 -0
  37. package/lib/typescript/src/manager/types.d.ts.map +1 -0
  38. package/lib/typescript/src/native.d.ts +2 -0
  39. package/lib/typescript/src/native.d.ts.map +1 -0
  40. package/lib/typescript/src/utils/index.d.ts +30 -0
  41. package/lib/typescript/src/utils/index.d.ts.map +1 -0
  42. package/package.json +158 -0
  43. package/src/errors.ts +32 -0
  44. package/src/index.ts +14 -0
  45. package/src/manager/index.ts +167 -0
  46. package/src/manager/types.ts +94 -0
  47. package/src/native.ts +18 -0
  48. package/src/utils/index.ts +42 -0
@@ -0,0 +1,83 @@
1
+ buildscript {
2
+ ext.getExtOrDefault = {name ->
3
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['IoReactNativeCie_' + name]
4
+ }
5
+
6
+ repositories {
7
+ google()
8
+ mavenCentral()
9
+ }
10
+
11
+ dependencies {
12
+ classpath "com.android.tools.build:gradle:8.7.2"
13
+ // noinspection DifferentKotlinGradleVersion
14
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
15
+ }
16
+ }
17
+
18
+
19
+ apply plugin: "com.android.library"
20
+ apply plugin: "kotlin-android"
21
+
22
+
23
+ def getExtOrIntegerDefault(name) {
24
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["IoReactNativeCie_" + name]).toInteger()
25
+ }
26
+
27
+ def supportsNamespace() {
28
+ def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
29
+ def major = parsed[0].toInteger()
30
+ def minor = parsed[1].toInteger()
31
+
32
+ // Namespace support was added in 7.3.0
33
+ return (major == 7 && minor >= 3) || major >= 8
34
+ }
35
+
36
+ android {
37
+ if (supportsNamespace()) {
38
+ namespace "com.pagopa.ioreactnativecie"
39
+
40
+ sourceSets {
41
+ main {
42
+ manifest.srcFile "src/main/AndroidManifestNew.xml"
43
+ }
44
+ }
45
+ }
46
+
47
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
48
+
49
+ defaultConfig {
50
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
51
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
52
+ }
53
+
54
+ buildTypes {
55
+ release {
56
+ minifyEnabled false
57
+ }
58
+ }
59
+
60
+ lintOptions {
61
+ disable "GradleCompatible"
62
+ }
63
+
64
+ compileOptions {
65
+ sourceCompatibility JavaVersion.VERSION_1_8
66
+ targetCompatibility JavaVersion.VERSION_1_8
67
+ }
68
+ }
69
+
70
+ repositories {
71
+ mavenCentral()
72
+ google()
73
+ }
74
+
75
+ def kotlin_version = getExtOrDefault("kotlinVersion")
76
+
77
+ dependencies {
78
+ implementation "com.facebook.react:react-android"
79
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
80
+ // CIE SDK
81
+ implementation "it.pagopa.io.app.cie:cie:0.1.4"
82
+ }
83
+
@@ -0,0 +1,5 @@
1
+ IoReactNativeCie_kotlinVersion=2.0.21
2
+ IoReactNativeCie_minSdkVersion=24
3
+ IoReactNativeCie_targetSdkVersion=34
4
+ IoReactNativeCie_compileSdkVersion=35
5
+ IoReactNativeCie_ndkVersion=27.1.12297006
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.pagopa.ioreactnativecie">
3
+ </manifest>
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,302 @@
1
+ package com.pagopa.ioreactnativecie
2
+
3
+ import android.util.Base64
4
+ import com.facebook.react.bridge.Promise
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.WritableMap
9
+ import com.facebook.react.bridge.WritableNativeMap
10
+ import com.facebook.react.modules.core.DeviceEventManagerModule
11
+ import com.pagopa.ioreactnativecie.cie.Atr
12
+ import it.pagopa.io.app.cie.CieLogger
13
+ import it.pagopa.io.app.cie.CieSDK
14
+ import it.pagopa.io.app.cie.cie.CieAtrCallback
15
+ import it.pagopa.io.app.cie.cie.NfcError
16
+ import it.pagopa.io.app.cie.cie.NfcEvent
17
+ import it.pagopa.io.app.cie.network.NetworkCallback
18
+ import it.pagopa.io.app.cie.network.NetworkError
19
+ import it.pagopa.io.app.cie.nfc.NfcEvents
20
+ import java.net.URL
21
+
22
+ typealias ME = IoReactNativeCieModule.Companion.ModuleException
23
+
24
+ class IoReactNativeCieModule(reactContext: ReactApplicationContext) :
25
+ ReactContextBaseJavaModule(reactContext) {
26
+
27
+ init {
28
+ CieLogger.enabled = BuildConfig.DEBUG
29
+ }
30
+
31
+ override fun getName(): String {
32
+ return NAME
33
+ }
34
+
35
+ /**
36
+ * Lazy value ensures it is initialized with a valid activity when first used.
37
+ */
38
+ val cieSdk: CieSDK by lazy {
39
+ CieSDK.withContext(currentActivity)
40
+ };
41
+
42
+ @ReactMethod
43
+ fun addListener(eventName: String) {
44
+ }
45
+
46
+ @ReactMethod
47
+ fun removeListeners(count: Int) {
48
+ }
49
+
50
+ @ReactMethod
51
+ fun hasNfcFeature(promise: Promise) {
52
+ try {
53
+ cieSdk.hasNfcFeature().let {
54
+ promise.resolve(it)
55
+ }
56
+ } catch (e: Exception) {
57
+ ME.UNKNOWN_EXCEPTION.reject(
58
+ promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
59
+ )
60
+ }
61
+ }
62
+
63
+ @ReactMethod
64
+ fun isNfcEnabled(promise: Promise) {
65
+ try {
66
+ cieSdk.isNfcAvailable().let {
67
+ promise.resolve(it)
68
+ }
69
+ } catch (e: Exception) {
70
+ ME.UNKNOWN_EXCEPTION.reject(
71
+ promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
72
+ )
73
+ }
74
+ }
75
+
76
+ @ReactMethod
77
+ fun isCieAuthenticationSupported(promise: Promise) {
78
+ cieSdk.isCieAuthenticationSupported().apply {
79
+ promise.resolve(this)
80
+ }
81
+ }
82
+
83
+ @ReactMethod
84
+ fun openNfcSettings(promise: Promise) {
85
+ try {
86
+ cieSdk.openNfcSettings()
87
+ promise.resolve(null)
88
+ } catch (e: Exception) {
89
+ ME.UNKNOWN_EXCEPTION.reject(
90
+ promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
91
+ )
92
+ }
93
+ }
94
+
95
+ @ReactMethod
96
+ fun setAlertMessage(key: String, value: String, promise: Promise) {
97
+ // Android does not support alert messages for NFC reading
98
+ promise.resolve(null)
99
+ }
100
+
101
+ @ReactMethod
102
+ fun setCurrentAlertMessage(value: String, promise: Promise) {
103
+ // Android does not support alert messages for NFC reading
104
+ promise.resolve(null)
105
+ }
106
+
107
+ @ReactMethod
108
+ fun setCustomIdpUrl(url: String) {
109
+ cieSdk.withCustomIdpUrl(url)
110
+ }
111
+
112
+ @ReactMethod
113
+ fun startReadingAttributes(
114
+ timeout: Int = 10000,
115
+ promise: Promise,
116
+ ) {
117
+ try {
118
+ cieSdk.startReadingCieAtr(timeout, object : NfcEvents {
119
+ override fun event(event: NfcEvent) {
120
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
121
+ .emit(EventType.EVENT.value, WritableNativeMap().apply {
122
+ putString("name", event.name)
123
+ putDouble(
124
+ "progress",
125
+ (event.numeratorForKindOf.toDouble() / NfcEvent.totalKindOfNumeratorEvent.toDouble())
126
+ )
127
+ })
128
+ }
129
+
130
+ override fun error(error: NfcError) {
131
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
132
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
133
+ putString("name", mapNfcError(error).name)
134
+ error.msg?.let { putString("message", it) }
135
+ })
136
+
137
+ }
138
+ }, object : CieAtrCallback {
139
+ override fun onSuccess(atr: ByteArray) {
140
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
141
+ .emit(EventType.ATTRIBUTES_SUCCESS.value, WritableNativeMap().apply {
142
+ putString("base64", Base64.encodeToString(atr, Base64.DEFAULT))
143
+ putString("type", Atr(atr).getCieType().name)
144
+ })
145
+ }
146
+
147
+ override fun onError(error: NfcError) {
148
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
149
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
150
+ putString("name", mapNfcError(error).name)
151
+ error.msg?.let { putString("message", it) }
152
+ })
153
+ }
154
+ })
155
+ promise.resolve(null)
156
+ } catch (e: Exception) {
157
+ ME.UNKNOWN_EXCEPTION.reject(
158
+ promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
159
+ )
160
+ }
161
+ }
162
+
163
+ @ReactMethod
164
+ fun startReading(
165
+ pin: String,
166
+ authenticationUrl: String,
167
+ timeout: Int = 10000,
168
+ promise: Promise,
169
+ ) {
170
+ try {
171
+ cieSdk.setPin(pin)
172
+ } catch (e: Exception) {
173
+ ME.PIN_REGEX_NOT_VALID.reject(
174
+ promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
175
+ )
176
+ return;
177
+ }
178
+
179
+ try {
180
+ cieSdk.withUrl(URL(authenticationUrl).toString())
181
+ } catch (e: Exception) {
182
+ ME.INVALID_AUTH_URL.reject(promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty()))
183
+ return
184
+ }
185
+
186
+ try {
187
+ cieSdk.startReading(timeout, object : NfcEvents {
188
+ override fun event(event: NfcEvent) {
189
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
190
+ .emit(EventType.EVENT.value, WritableNativeMap().apply {
191
+ putString("name", event.name)
192
+ putDouble(
193
+ "progress", (event.numerator.toDouble() / NfcEvent.totalNumeratorEvent.toDouble())
194
+ )
195
+ })
196
+ }
197
+
198
+ override fun error(error: NfcError) {
199
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
200
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
201
+ putString("name", mapNfcError(error).name)
202
+ error.msg?.let { putString("msg", it) }
203
+ error.numberOfAttempts?.let { putInt("attempts", it) }
204
+ })
205
+
206
+ }
207
+ }, object : NetworkCallback {
208
+ override fun onSuccess(url: String) {
209
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
210
+ .emit(EventType.SUCCESS.value, url)
211
+ }
212
+
213
+ override fun onError(networkError: NetworkError) {
214
+ this@IoReactNativeCieModule.reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
215
+ .emit(EventType.ERROR.value, WritableNativeMap().apply {
216
+ putString("name", mapNetworkError(networkError).name)
217
+ networkError.msg?.let { putString("message", it) }
218
+ })
219
+ }
220
+ })
221
+ promise.resolve(null)
222
+ } catch (e: Exception) {
223
+ ME.UNKNOWN_EXCEPTION.reject(
224
+ promise, Pair(ERROR_USER_INFO_KEY, e.message.orEmpty())
225
+ )
226
+ }
227
+ }
228
+
229
+ @ReactMethod
230
+ fun stopReading() {
231
+ cieSdk.stopNFCListening()
232
+ }
233
+
234
+ fun mapNfcError(error: NfcError): ErrorType {
235
+ return when (error) {
236
+ NfcError.NOT_A_CIE -> ErrorType.NOT_A_CIE
237
+ NfcError.TAG_LOST -> ErrorType.TAG_LOST
238
+ NfcError.APDU_ERROR -> ErrorType.APDU_ERROR
239
+ NfcError.EXTENDED_APDU_NOT_SUPPORTED -> ErrorType.APDU_ERROR
240
+ NfcError.WRONG_PIN -> ErrorType.WRONG_PIN
241
+ NfcError.PIN_BLOCKED -> ErrorType.CARD_BLOCKED
242
+ else -> ErrorType.GENERIC_ERROR
243
+ }
244
+ }
245
+
246
+ fun mapNetworkError(error: NetworkError): ErrorType {
247
+ return when (error) {
248
+ NetworkError.NO_INTERNET_CONNECTION -> ErrorType.NO_INTERNET_CONNECTION
249
+ NetworkError.CERTIFICATE_EXPIRED -> ErrorType.CERTIFICATE_EXPIRED
250
+ NetworkError.CERTIFICATE_REVOKED -> ErrorType.CERTIFICATE_REVOKED
251
+ NetworkError.AUTHENTICATION_ERROR -> ErrorType.AUTHENTICATION_ERROR
252
+ else -> ErrorType.GENERIC_ERROR
253
+ }
254
+ }
255
+
256
+ companion object {
257
+ const val NAME = "IoReactNativeCie"
258
+ const val ERROR_USER_INFO_KEY = "error"
259
+
260
+ enum class EventType(val value: String) {
261
+ EVENT("onEvent"),
262
+ ERROR("onError"),
263
+ ATTRIBUTES_SUCCESS("onAttributesSuccess"),
264
+ SUCCESS("onSuccess")
265
+ }
266
+
267
+ enum class ErrorType {
268
+ NOT_A_CIE,
269
+ TAG_LOST,
270
+ APDU_ERROR,
271
+ WRONG_PIN,
272
+ CARD_BLOCKED,
273
+ NO_INTERNET_CONNECTION,
274
+ CERTIFICATE_EXPIRED,
275
+ CERTIFICATE_REVOKED,
276
+ AUTHENTICATION_ERROR,
277
+ GENERIC_ERROR,
278
+ }
279
+
280
+ enum class ModuleException(
281
+ val ex: Exception
282
+ ) {
283
+ PIN_REGEX_NOT_VALID(Exception("PIN_REGEX_NOT_VALID")),
284
+ INVALID_AUTH_URL(Exception("INVALID_AUTH_URL")),
285
+ UNKNOWN_EXCEPTION(Exception("UNKNOWN_EXCEPTION"));
286
+
287
+ fun reject(
288
+ promise: Promise, vararg args: Pair<String, String>
289
+ ) {
290
+ exMap(*args).let {
291
+ promise.reject(it.first, ex.message, it.second)
292
+ }
293
+ }
294
+
295
+ private fun exMap(vararg args: Pair<String, String>): Pair<String, WritableMap> {
296
+ val writableMap = WritableNativeMap()
297
+ args.forEach { writableMap.putString(it.first, it.second) }
298
+ return Pair(this.ex.message ?: "UNKNOWN", writableMap)
299
+ }
300
+ }
301
+ }
302
+ }
@@ -0,0 +1,17 @@
1
+ package com.pagopa.ioreactnativecie
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+
9
+ class IoReactNativeCiePackage : ReactPackage {
10
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
+ return listOf(IoReactNativeCieModule(reactContext))
12
+ }
13
+
14
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
+ return emptyList()
16
+ }
17
+ }
@@ -0,0 +1,39 @@
1
+ package com.pagopa.ioreactnativecie.cie
2
+
3
+ import it.pagopa.io.app.cie.CieLogger
4
+
5
+ class Atr(private val atr: ByteArray) {
6
+ fun getCieType(): CieType {
7
+ CieLogger.i("ATR_MAIN:", this.atr.toHexString())
8
+ CieType.entries.forEach {
9
+ CieLogger.i("ATR_OTHE:", it.atr.toHexString())
10
+ if (it.atr.isSubsetInOrder(this.atr))
11
+ return it
12
+ }
13
+ return CieType.UNKNOWN
14
+ }
15
+
16
+ private fun ByteArray.toHexString(): String {
17
+ return joinToString(separator = " ") { byte ->
18
+ "0x%02X".format(byte)
19
+ }
20
+ }
21
+
22
+ private fun ByteArray.isSubsetInOrder(second: ByteArray): Boolean {
23
+ if (this.size > second.size) return false
24
+ var indexSecond = 0
25
+ for (element in this) {
26
+ // Find the element in the second array starting from the current index
27
+ while (indexSecond < second.size && second[indexSecond] != element) {
28
+ indexSecond++
29
+ }
30
+ // If we reach the end of the second array without finding the element, return false
31
+ if (indexSecond == second.size) {
32
+ return false
33
+ }
34
+ // Increment the index for the next iteration
35
+ indexSecond++
36
+ }
37
+ return true
38
+ }
39
+ }
@@ -0,0 +1,157 @@
1
+ package com.pagopa.ioreactnativecie.cie
2
+
3
+ /**Returns Cie Manufacturer*/
4
+ enum class CieType(val atr: ByteArray) {
5
+ NXP(
6
+ byteArrayOf(
7
+ 0x80.toByte(),
8
+ 0x00,
9
+ 0x43,
10
+ 0x01,
11
+ 0xB8.toByte(),
12
+ 0x46,
13
+ 0x04,
14
+ 0x10,
15
+ 0x10,
16
+ 0x10,
17
+ 0x10,
18
+ 0x47,
19
+ 0x03,
20
+ 0x94.toByte(),
21
+ 0x01,
22
+ 0x80.toByte()
23
+ )
24
+ ),
25
+ GEMALTO(
26
+ byteArrayOf(
27
+ 0x49, 0x61, 0x73, 0x45, 0x63, 0x63, 0x52, 0x6F, 0x6F, 0x74
28
+ )
29
+ ),
30
+ GEMALTO_2(
31
+ byteArrayOf(
32
+ 0x47, 0x03, 0x94.toByte(), 0x41, 0xC0.toByte()
33
+ )
34
+ ),
35
+ ACTALIS(
36
+ byteArrayOf(
37
+ 0x80.toByte(),
38
+ 0x00,
39
+ 0x43,
40
+ 0x01,
41
+ 0xB8.toByte(),
42
+ 0x46,
43
+ 0x04,
44
+ 0x10,
45
+ 0x10,
46
+ 0x10,
47
+ 0x10,
48
+ 0x47,
49
+ 0x03,
50
+ 0x94.toByte(),
51
+ 0x01,
52
+ 0xE0.toByte(),
53
+ 0x7F,
54
+ 0x66,
55
+ 0x08,
56
+ 0x02,
57
+ 0x02,
58
+ 0x04,
59
+ 0xD6.toByte(),
60
+ 0x02,
61
+ 0x02,
62
+ 0x07,
63
+ 0xE3.toByte(),
64
+ 0xE0.toByte(),
65
+ 0x10,
66
+ 0x02,
67
+ 0x02,
68
+ 0x01,
69
+ 0x04,
70
+ 0x02,
71
+ 0x02,
72
+ 0x00,
73
+ 0xE6.toByte(),
74
+ 0x02,
75
+ 0x02,
76
+ 0x00,
77
+ 0xE6.toByte(),
78
+ 0x02.toByte(),
79
+ 0x02,
80
+ 0x00,
81
+ 0xE6.toByte(),
82
+ 0x78,
83
+ 0x08,
84
+ 0x06,
85
+ 0x06,
86
+ 0x2B,
87
+ 0x81.toByte(),
88
+ 0x22,
89
+ 0xF8.toByte(),
90
+ 0x78,
91
+ 0x02
92
+ )
93
+ ),
94
+ ST(
95
+ byteArrayOf(
96
+ 0x80.toByte(),
97
+ 0x00,
98
+ 0x43,
99
+ 0x01,
100
+ 0xB9.toByte(),
101
+ 0x46,
102
+ 0x04,
103
+ 0x00,
104
+ 0x00,
105
+ 0x00,
106
+ 0x10,
107
+ 0x47,
108
+ 0x03,
109
+ 0x94.toByte(),
110
+ 0x01,
111
+ 0x81.toByte(),
112
+ 0x4F,
113
+ 0x0C,
114
+ 0xA0.toByte(),
115
+ 0x00,
116
+ 0x00,
117
+ 0x00,
118
+ 0x95.toByte(),
119
+ 0x00,
120
+ 0x00,
121
+ 0x00,
122
+ 0x00,
123
+ 0x8A.toByte(),
124
+ 0x00,
125
+ 0x01,
126
+ 0xE0.toByte(),
127
+ 0x10,
128
+ 0x02,
129
+ 0x02,
130
+ 0x00,
131
+ 0xFF.toByte(),
132
+ 0x02,
133
+ 0x02,
134
+ 0x00,
135
+ 0xFF.toByte(),
136
+ 0x02,
137
+ 0x02,
138
+ 0x01,
139
+ 0x00,
140
+ 0x02,
141
+ 0x02,
142
+ 0x01,
143
+ 0x00,
144
+ 0x78,
145
+ 0x08,
146
+ 0x06,
147
+ 0x06,
148
+ 0x2B,
149
+ 0x81.toByte(),
150
+ 0x22,
151
+ 0xF8.toByte(),
152
+ 0x78,
153
+ 0x02
154
+ )
155
+ ),
156
+ UNKNOWN(byteArrayOf())
157
+ }
@@ -0,0 +1,81 @@
1
+ import Foundation
2
+
3
+ enum CIEType: String, Sendable {
4
+ case CIE_Unknown = "UNKNOWN"
5
+ case CIE_Gemalto = "GEMALTO"
6
+ case CIE_Gemalto2 = "GEMALTO_2"
7
+ case CIE_NXP = "NXP"
8
+ case CIE_ST = "ST"
9
+ case CIE_Actalis = "ACTALIS"
10
+
11
+ static func fromATR(_ atr: [UInt8]) -> CIEType {
12
+ let Gemalto_ATR: [UInt8] = [ 0x49, 0x61, 0x73, 0x45, 0x63, 0x63, 0x52, 0x6F, 0x6F, 0x74 ]
13
+ let NXP_ATR: [UInt8] = [0x80, 0x00, 0x43, 0x01, 0xB8, 0x46, 0x04, 0x10, 0x10, 0x10, 0x10, 0x47, 0x03, 0x94 ]
14
+ let Gemalto2_ATR: [UInt8] = [ 0x47, 0x03, 0x94, 0x41, 0xC0 ]
15
+ let ST_ATR: [UInt8] = [ 0x80, 0x00, 0x43, 0x01, 0xB9, 0x46, 0x04, 0x00, 0x00, 0x00, 0x10, 0x47, 0x03, 0x94, 0x01, 0x81, 0x4F, 0x0C, 0xA0, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x01, 0xE0, 0x10, 0x02, 0x02, 0x00, 0xFF, 0x02, 0x02, 0x00, 0xFF, 0x02, 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x00, 0x78, 0x08, 0x06 , 0x06 , 0x2B , 0x81 , 0x22 , 0xF8 , 0x78, 0x02, 0x82, 0x02, 0x90, 0x00 ]
16
+ let Actalis_ATR: [UInt8] = [0x80, 0x00, 0x43, 0x01, 0xB8, 0x46, 0x04, 0x10, 0x10, 0x10, 0x10, 0x47, 0x03, 0x94, 0x01, 0xE0, 0x7F, 0x66, 0x08, 0x02, 0x02, 0x04, 0xD6, 0x02, 0x02, 0x07, 0xE3, 0xE0, 0x10, 0x02, 0x02, 0x01, 0x04, 0x02, 0x02, 0x00, 0xE6, 0x02, 0x02, 0x00, 0xE6, 0x02, 0x02, 0x00, 0xE6, 0x78, 0x08, 0x06, 0x06, 0x2B, 0x81, 0x22, 0xF8, 0x78, 0x02 ]
17
+
18
+ if #available(iOS 16.0, *) {
19
+ if atr.contains(Actalis_ATR) {
20
+ return .CIE_Actalis
21
+ }
22
+ if atr.contains(ST_ATR) {
23
+ return .CIE_ST
24
+ }
25
+ if atr.contains(NXP_ATR) {
26
+ return .CIE_NXP
27
+ }
28
+ if atr.contains(Gemalto2_ATR) {
29
+ return .CIE_Gemalto2
30
+ }
31
+ if atr.contains(Gemalto_ATR) {
32
+ return .CIE_Gemalto
33
+ }
34
+ }
35
+ else {
36
+ let atrStr = atr.hexEncodedString
37
+ if atrStr.contains(Actalis_ATR.hexEncodedString) {
38
+ return .CIE_Actalis
39
+ }
40
+ if atrStr.contains(ST_ATR.hexEncodedString) {
41
+ return .CIE_ST
42
+ }
43
+ if atrStr.contains(NXP_ATR.hexEncodedString) {
44
+ return .CIE_NXP
45
+ }
46
+ if atrStr.contains(Gemalto2_ATR.hexEncodedString) {
47
+ return .CIE_Gemalto
48
+ }
49
+ if atrStr.contains(Gemalto_ATR.hexEncodedString) {
50
+ return .CIE_Gemalto
51
+ }
52
+ }
53
+
54
+ return .CIE_Unknown
55
+ }
56
+ }
57
+
58
+ extension Data {
59
+ struct HexEncodingOptions: OptionSet {
60
+ public let rawValue: Int
61
+
62
+ public init(rawValue: Int) {
63
+ self.rawValue = rawValue
64
+ }
65
+
66
+ public static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
67
+ }
68
+
69
+ func hexEncodedString(options: HexEncodingOptions = []) -> String {
70
+ let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
71
+ return map { String(format: format, $0) }.joined()
72
+ }
73
+ }
74
+
75
+
76
+ extension Array<UInt8> {
77
+
78
+ var hexEncodedString: String {
79
+ return Data(self).hexEncodedString()
80
+ }
81
+ }
@@ -0,0 +1,2 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTViewManager.h>