@animo-id/expo-mdoc-data-transfer 0.1.3 → 0.1.5
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/MdocDataTransfer.podspec +12 -6
- package/android/build.gradle +13 -2
- package/android/src/main/java/id/animo/mdocdatatransfer/MdocDataTransfer.kt +11 -15
- package/android/src/main/java/id/animo/mdocdatatransfer/MdocDataTransferManager.kt +20 -11
- package/android/src/main/java/id/animo/mdocdatatransfer/MdocDataTransferModule.kt +1 -3
- package/build/MdocDataTransfer.d.ts +2 -2
- package/build/MdocDataTransfer.d.ts.map +1 -1
- package/build/MdocDataTransfer.js +4 -4
- package/build/MdocDataTransfer.js.map +1 -1
- package/build/specs/NativeMdocDataTransfer.d.ts +3 -5
- package/build/specs/NativeMdocDataTransfer.d.ts.map +1 -1
- package/build/specs/NativeMdocDataTransfer.js +1 -2
- package/build/specs/NativeMdocDataTransfer.js.map +1 -1
- package/ios/MdocDataTransfer.mm +6 -5
- package/ios/MdocDataTransfer.swift +178 -152
- package/ios/MdocDataTransferError.swift +36 -36
- package/package.json +1 -1
- package/src/specs/NativeMdocDataTransfer.ts +3 -7
package/MdocDataTransfer.podspec
CHANGED
|
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.license = package['license']
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.homepage = package['homepage']
|
|
13
|
-
s.platforms = { :ios => '
|
|
13
|
+
s.platforms = { :ios => '15.0'}
|
|
14
14
|
s.swift_version = '5.4'
|
|
15
15
|
s.source = { :git => "https://github.com/animo/mdoc-data-transfer.git", :tag => "#{s.version}" }
|
|
16
16
|
|
|
@@ -24,13 +24,19 @@ Pod::Spec.new do |s|
|
|
|
24
24
|
install_modules_dependencies(s)
|
|
25
25
|
|
|
26
26
|
if defined?(:spm_dependency)
|
|
27
|
-
spm_dependency(s,
|
|
27
|
+
spm_dependency(s,
|
|
28
28
|
# Currently we use this fork because it adds a manual `sendDeviceResponse` method
|
|
29
29
|
# Which we use as we generate this outside of the library
|
|
30
|
-
url: 'https://github.com/
|
|
31
|
-
requirement: {kind: 'upToNextMinorVersion', minimumVersion: '0.3
|
|
32
|
-
products: ['MdocDataTransfer18013']
|
|
33
|
-
)
|
|
30
|
+
url: 'https://github.com/animo/eudi-lib-ios-iso18013-data-transfer.git',
|
|
31
|
+
requirement: {kind: 'upToNextMinorVersion', minimumVersion: '0.6.3'},
|
|
32
|
+
products: ['MdocDataTransfer18013']
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
spm_dependency(s,
|
|
36
|
+
url: 'https://github.com/eu-digital-identity-wallet/eudi-lib-ios-wallet-storage.git',
|
|
37
|
+
requirement: {kind: 'upToNextMinorVersion', minimumVersion: '0.4.8'},
|
|
38
|
+
products: ['WalletStorage']
|
|
39
|
+
)
|
|
34
40
|
else
|
|
35
41
|
raise "Please upgrade React Native to >=0.75.0 to use SPM dependencies."
|
|
36
42
|
end
|
package/android/build.gradle
CHANGED
|
@@ -42,16 +42,27 @@ android {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
45
|
dependencies {
|
|
47
|
-
implementation("eu.europa.ec.eudi:eudi-lib-android-
|
|
46
|
+
implementation("eu.europa.ec.eudi:eudi-lib-android-wallet-document-manager:0.9.0") {
|
|
47
|
+
exclude group: 'org.bouncycastle'
|
|
48
|
+
exclude module: 'bcprov-jdk18on'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
implementation("com.android.identity:identity-android:202408.1") {
|
|
48
52
|
exclude group: 'org.bouncycastle'
|
|
49
53
|
exclude module: 'bcprov-jdk18on'
|
|
50
54
|
}
|
|
55
|
+
|
|
56
|
+
implementation("eu.europa.ec.eudi:eudi-lib-android-iso18013-data-transfer:0.6.0") {
|
|
57
|
+
exclude group: 'org.bouncycastle'
|
|
58
|
+
exclude module: 'bcprov-jdk18on'
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
implementation("org.bouncycastle:bcprov-jdk18on") {
|
|
52
62
|
version {
|
|
53
63
|
strictly '1.72'
|
|
54
64
|
}
|
|
55
65
|
}
|
|
66
|
+
|
|
56
67
|
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05"
|
|
57
68
|
}
|
|
@@ -6,7 +6,8 @@ import android.util.Log
|
|
|
6
6
|
import androidx.activity.ComponentActivity
|
|
7
7
|
import eu.europa.ec.eudi.iso18013.transfer.TransferEvent
|
|
8
8
|
import eu.europa.ec.eudi.iso18013.transfer.engagement.NfcEngagementService
|
|
9
|
-
import eu.europa.ec.eudi.iso18013.transfer.response.DeviceRequest
|
|
9
|
+
import eu.europa.ec.eudi.iso18013.transfer.response.device.DeviceRequest
|
|
10
|
+
import eu.europa.ec.eudi.iso18013.transfer.response.device.DeviceResponse
|
|
10
11
|
|
|
11
12
|
class MdocDataTransfer(
|
|
12
13
|
context: Context,
|
|
@@ -49,24 +50,19 @@ class MdocDataTransfer(
|
|
|
49
50
|
|
|
50
51
|
is TransferEvent.RequestReceived -> {
|
|
51
52
|
Log.d(TAG, ":::mdoc-data-transfer::: TransferEvent.RequestReceived")
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
53
|
+
val request = event.request as DeviceRequest
|
|
54
|
+
sendEvent(
|
|
55
|
+
MdocDataTransferEvent.ON_REQUEST_RECEIVED, mapOf(
|
|
56
|
+
"deviceRequest" to request.deviceRequestBytes.asList(),
|
|
57
|
+
"sessionTranscript" to request.sessionTranscriptBytes.asList()
|
|
58
|
+
)
|
|
59
|
+
)
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
is TransferEvent.ResponseSent -> {
|
|
66
63
|
Log.d(TAG, ":::mdoc-data-transfer::: TransferEvent.ResponseSent")
|
|
67
64
|
sendEvent(
|
|
68
|
-
MdocDataTransferEvent.ON_RESPONSE_SENT,
|
|
69
|
-
null
|
|
65
|
+
MdocDataTransferEvent.ON_RESPONSE_SENT, null
|
|
70
66
|
)
|
|
71
67
|
}
|
|
72
68
|
}
|
|
@@ -82,7 +78,7 @@ class MdocDataTransfer(
|
|
|
82
78
|
}
|
|
83
79
|
|
|
84
80
|
fun respond(deviceResponse: ByteArray) {
|
|
85
|
-
MdocDataTransferManager.transferManager.value.sendResponse(deviceResponse)
|
|
81
|
+
MdocDataTransferManager.transferManager.value.sendResponse(DeviceResponse(deviceResponse))
|
|
86
82
|
}
|
|
87
83
|
|
|
88
84
|
fun enableNfc() {
|
|
@@ -2,10 +2,11 @@ package id.animo.mdocdatatransfer
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
|
-
import
|
|
5
|
+
import com.android.identity.securearea.software.SoftwareSecureArea
|
|
6
|
+
import com.android.identity.storage.EphemeralStorageEngine
|
|
6
7
|
import eu.europa.ec.eudi.iso18013.transfer.TransferManager
|
|
7
|
-
import eu.europa.ec.eudi.iso18013.transfer.
|
|
8
|
-
import eu.europa.ec.eudi.
|
|
8
|
+
import eu.europa.ec.eudi.iso18013.transfer.engagement.BleRetrievalMethod
|
|
9
|
+
import eu.europa.ec.eudi.wallet.document.DocumentManager
|
|
9
10
|
|
|
10
11
|
@SuppressLint("StaticFieldLeak")
|
|
11
12
|
object MdocDataTransferManager {
|
|
@@ -16,20 +17,28 @@ object MdocDataTransferManager {
|
|
|
16
17
|
this.context = context
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
private val storageEngine = EphemeralStorageEngine()
|
|
21
|
+
private val secureArea = SoftwareSecureArea(storageEngine)
|
|
22
|
+
|
|
23
|
+
private val documentManager = DocumentManager
|
|
24
|
+
.Builder()
|
|
25
|
+
.setIdentifier("eudi_wallet_document_manager")
|
|
26
|
+
.setStorageEngine(storageEngine)
|
|
27
|
+
.addSecureArea(secureArea)
|
|
28
|
+
.build()
|
|
29
|
+
|
|
19
30
|
val transferManager = lazy {
|
|
20
|
-
TransferManager.
|
|
21
|
-
|
|
31
|
+
TransferManager.getDefault(
|
|
32
|
+
context,
|
|
33
|
+
documentManager,
|
|
34
|
+
null,
|
|
35
|
+
listOf(
|
|
22
36
|
BleRetrievalMethod(
|
|
23
37
|
peripheralServerMode = true,
|
|
24
38
|
centralClientMode = true,
|
|
25
39
|
clearBleCache = true
|
|
26
40
|
)
|
|
27
41
|
)
|
|
28
|
-
|
|
29
|
-
.apply {
|
|
30
|
-
documentsResolver = DocumentsResolver { listOf() }
|
|
31
|
-
}.build()
|
|
32
|
-
|
|
33
|
-
}.build()
|
|
42
|
+
)
|
|
34
43
|
}
|
|
35
44
|
}
|
|
@@ -18,7 +18,7 @@ class MdocDataTransferModule : Module() {
|
|
|
18
18
|
MdocDataTransferEvent.ON_RESPONSE_SENT
|
|
19
19
|
)
|
|
20
20
|
|
|
21
|
-
Function("initialize") {
|
|
21
|
+
Function("initialize") { serviceName: String ->
|
|
22
22
|
// We have to re-set the Bouncy Castle provider, otherwise the EUDI library cannot find it correctly
|
|
23
23
|
Security.removeProvider("BC")
|
|
24
24
|
Security.addProvider(BouncyCastleProvider())
|
|
@@ -32,8 +32,6 @@ class MdocDataTransferModule : Module() {
|
|
|
32
32
|
body ?: mapOf()
|
|
33
33
|
)
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
return@Function null
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type OnRequestReceivedEventPayload } from './MdocDataTransferEvent';
|
|
2
2
|
export declare let instance: MdocDataTransfer | undefined;
|
|
3
3
|
export declare const mdocDataTransfer: {
|
|
4
|
-
instance: () => MdocDataTransfer;
|
|
4
|
+
instance: (serviceName: string) => MdocDataTransfer;
|
|
5
5
|
};
|
|
6
6
|
declare class MdocDataTransfer {
|
|
7
7
|
isNfcEnabled: boolean;
|
|
8
|
-
static initialize(): MdocDataTransfer;
|
|
8
|
+
static initialize(serviceName: string): MdocDataTransfer;
|
|
9
9
|
startQrEngagement(): Promise<string>;
|
|
10
10
|
waitForDeviceRequest(): Promise<OnRequestReceivedEventPayload<Uint8Array>>;
|
|
11
11
|
sendDeviceResponse(deviceResponse: Uint8Array): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MdocDataTransfer.d.ts","sourceRoot":"","sources":["../src/MdocDataTransfer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,6BAA6B,EAEnC,MAAM,yBAAyB,CAAA;AAGhC,eAAO,IAAI,QAAQ,EAAE,gBAAgB,GAAG,SAAqB,CAAA;AAC7D,eAAO,MAAM,gBAAgB
|
|
1
|
+
{"version":3,"file":"MdocDataTransfer.d.ts","sourceRoot":"","sources":["../src/MdocDataTransfer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,6BAA6B,EAEnC,MAAM,yBAAyB,CAAA;AAGhC,eAAO,IAAI,QAAQ,EAAE,gBAAgB,GAAG,SAAqB,CAAA;AAC7D,eAAO,MAAM,gBAAgB;4BACH,MAAM;CAI/B,CAAA;AAED,cAAM,gBAAgB;IACb,YAAY,UAAQ;WAEb,UAAU,CAAC,WAAW,EAAE,MAAM;IAW/B,iBAAiB;IAIjB,oBAAoB;IAcpB,kBAAkB,CAAC,cAAc,EAAE,UAAU;IAUnD,QAAQ;IAWR,SAAS;CAKjB"}
|
|
@@ -2,16 +2,16 @@ import { MdocDataTransferEvent, } from './MdocDataTransferEvent';
|
|
|
2
2
|
import { mDocNativeModule, mDocNativeModuleEventEmitter } from './MdocDataTransferModule';
|
|
3
3
|
export let instance = undefined;
|
|
4
4
|
export const mdocDataTransfer = {
|
|
5
|
-
instance: () => {
|
|
5
|
+
instance: (serviceName) => {
|
|
6
6
|
if (instance)
|
|
7
7
|
return instance;
|
|
8
|
-
return MdocDataTransfer.initialize();
|
|
8
|
+
return MdocDataTransfer.initialize(serviceName);
|
|
9
9
|
},
|
|
10
10
|
};
|
|
11
11
|
class MdocDataTransfer {
|
|
12
12
|
isNfcEnabled = false;
|
|
13
|
-
static initialize() {
|
|
14
|
-
const error = mDocNativeModule.initialize();
|
|
13
|
+
static initialize(serviceName) {
|
|
14
|
+
const error = mDocNativeModule.initialize(serviceName);
|
|
15
15
|
if (typeof error === 'string' && error.length > 0) {
|
|
16
16
|
throw new Error(error);
|
|
17
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MdocDataTransfer.js","sourceRoot":"","sources":["../src/MdocDataTransfer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAGtB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAA;AAEzF,MAAM,CAAC,IAAI,QAAQ,GAAiC,SAAS,CAAA;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"MdocDataTransfer.js","sourceRoot":"","sources":["../src/MdocDataTransfer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAGtB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAA;AAEzF,MAAM,CAAC,IAAI,QAAQ,GAAiC,SAAS,CAAA;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,CAAC,WAAmB,EAAE,EAAE;QAChC,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAC7B,OAAO,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IACjD,CAAC;CACF,CAAA;AAED,MAAM,gBAAgB;IACb,YAAY,GAAG,KAAK,CAAA;IAEpB,MAAM,CAAC,UAAU,CAAC,WAAmB;QAC1C,MAAM,KAAK,GAAG,gBAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;QAEtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;QAED,QAAQ,GAAG,IAAI,gBAAgB,EAAE,CAAA;QACjC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAEM,KAAK,CAAC,iBAAiB;QAC5B,OAAO,MAAM,gBAAgB,CAAC,iBAAiB,EAAE,CAAA;IACnD,CAAC;IAEM,KAAK,CAAC,oBAAoB;QAC/B,OAAO,MAAM,IAAI,OAAO,CAA4C,CAAC,OAAO,EAAE,EAAE,CAC9E,4BAA4B,CAAC,WAAW,CACtC,qBAAqB,CAAC,iBAAiB,EACvC,CAAC,OAAsC,EAAE,EAAE;YACzC,OAAO,CAAC;gBACN,aAAa,EAAE,IAAI,UAAU,CAAC,OAAO,CAAC,aAAa,CAAC;gBACpD,iBAAiB,EAAE,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC;aAC7D,CAAC,CAAA;QACJ,CAAC,CACF,CACF,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAAC,cAA0B;QACxD,MAAM,CAAC,GAAG,IAAI,OAAO,CAAwB,CAAC,OAAO,EAAE,EAAE,CACvD,4BAA4B,CAAC,WAAW,CAAC,qBAAqB,CAAC,cAAc,EAAE,OAAO,CAAC,CACxF,CAAA;QAED,gBAAgB,CAAC,kBAAkB,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QAE7D,MAAM,CAAC,CAAA;IACT,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QACzB,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAA;QAEzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;QAED,QAAQ,GAAG,SAAS,CAAA;IACtB,CAAC;IAEM,SAAS;QACd,IAAI,IAAI,CAAC,YAAY;YAAE,OAAM;QAC7B,gBAAgB,CAAC,SAAS,EAAE,CAAA;QAC5B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;IAC1B,CAAC;CACF","sourcesContent":["import {\n MdocDataTransferEvent,\n type OnRequestReceivedEventPayload,\n type OnResponseSendPayload,\n} from './MdocDataTransferEvent'\nimport { mDocNativeModule, mDocNativeModuleEventEmitter } from './MdocDataTransferModule'\n\nexport let instance: MdocDataTransfer | undefined = undefined\nexport const mdocDataTransfer = {\n instance: (serviceName: string) => {\n if (instance) return instance\n return MdocDataTransfer.initialize(serviceName)\n },\n}\n\nclass MdocDataTransfer {\n public isNfcEnabled = false\n\n public static initialize(serviceName: string) {\n const error = mDocNativeModule.initialize(serviceName)\n\n if (typeof error === 'string' && error.length > 0) {\n throw new Error(error)\n }\n\n instance = new MdocDataTransfer()\n return instance\n }\n\n public async startQrEngagement() {\n return await mDocNativeModule.startQrEngagement()\n }\n\n public async waitForDeviceRequest() {\n return await new Promise<OnRequestReceivedEventPayload<Uint8Array>>((resolve) =>\n mDocNativeModuleEventEmitter.addListener(\n MdocDataTransferEvent.OnRequestReceived,\n (payload: OnRequestReceivedEventPayload) => {\n resolve({\n deviceRequest: new Uint8Array(payload.deviceRequest),\n sessionTranscript: new Uint8Array(payload.sessionTranscript),\n })\n }\n )\n )\n }\n\n public async sendDeviceResponse(deviceResponse: Uint8Array) {\n const p = new Promise<OnResponseSendPayload>((resolve) =>\n mDocNativeModuleEventEmitter.addListener(MdocDataTransferEvent.OnResponseSent, resolve)\n )\n\n mDocNativeModule.sendDeviceResponse(deviceResponse.join(':'))\n\n await p\n }\n\n public shutdown() {\n this.isNfcEnabled = false\n const error = mDocNativeModule.shutdown()\n\n if (typeof error === 'string' && error.length > 0) {\n throw new Error(error)\n }\n\n instance = undefined\n }\n\n public enableNfc() {\n if (this.isNfcEnabled) return\n mDocNativeModule.enableNfc()\n this.isNfcEnabled = true\n }\n}\n"]}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export interface Spec extends TurboModule {
|
|
1
|
+
export interface Spec {
|
|
3
2
|
enableNfc: () => void;
|
|
4
|
-
initialize: () => undefined | string;
|
|
3
|
+
initialize: (serviceName: string) => undefined | string;
|
|
5
4
|
startQrEngagement: () => Promise<string>;
|
|
6
|
-
sendDeviceResponse: (devceResponse: string) => void
|
|
5
|
+
sendDeviceResponse: (devceResponse: string) => Promise<void>;
|
|
7
6
|
shutdown: () => undefined | string;
|
|
8
7
|
}
|
|
9
|
-
export declare const turboModuleMdocDataTransfer: () => Spec;
|
|
10
8
|
//# sourceMappingURL=NativeMdocDataTransfer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeMdocDataTransfer.d.ts","sourceRoot":"","sources":["../../src/specs/NativeMdocDataTransfer.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"NativeMdocDataTransfer.d.ts","sourceRoot":"","sources":["../../src/specs/NativeMdocDataTransfer.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,SAAS,EAAE,MAAM,IAAI,CAAA;IAGrB,UAAU,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,SAAS,GAAG,MAAM,CAAA;IAEvD,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAExC,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAG5D,QAAQ,EAAE,MAAM,SAAS,GAAG,MAAM,CAAA;CACnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeMdocDataTransfer.js","sourceRoot":"","sources":["../../src/specs/NativeMdocDataTransfer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NativeMdocDataTransfer.js","sourceRoot":"","sources":["../../src/specs/NativeMdocDataTransfer.ts"],"names":[],"mappings":"","sourcesContent":["export interface Spec {\n enableNfc: () => void\n\n // String indicates an error on iOS legacy architecture\n initialize: (serviceName: string) => undefined | string\n\n startQrEngagement: () => Promise<string>\n\n sendDeviceResponse: (devceResponse: string) => Promise<void>\n\n // String indicates an error on iOS legacy architecture\n shutdown: () => undefined | string\n}\n"]}
|
package/ios/MdocDataTransfer.mm
CHANGED
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
|
|
10
10
|
RCT_EXTERN_METHOD(enableNfc)
|
|
11
11
|
|
|
12
|
-
RCT_EXTERN_METHOD(initialize)
|
|
12
|
+
RCT_EXTERN_METHOD(initialize:(NSString *)serviceName)
|
|
13
13
|
|
|
14
|
-
RCT_EXTERN_METHOD(startQrEngagement
|
|
15
|
-
:
|
|
16
|
-
: (RCTPromiseRejectBlock)reject)
|
|
14
|
+
RCT_EXTERN_METHOD(startQrEngagement:(RCTPromiseResolveBlock)resolve
|
|
15
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
17
16
|
|
|
18
|
-
RCT_EXTERN_METHOD(sendDeviceResponse
|
|
17
|
+
RCT_EXTERN_METHOD(sendDeviceResponse:(NSString)deviceResponse
|
|
18
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
19
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
19
20
|
|
|
20
21
|
RCT_EXTERN_METHOD(shutdown)
|
|
21
22
|
|
|
@@ -3,193 +3,219 @@ import MdocDataTransfer18013
|
|
|
3
3
|
import MdocSecurity18013
|
|
4
4
|
import React
|
|
5
5
|
import SwiftCBOR
|
|
6
|
+
import WalletStorage
|
|
6
7
|
|
|
7
8
|
@objc(MdocDataTransfer)
|
|
8
9
|
class MdocDataTransfer: RCTEventEmitter {
|
|
9
|
-
|
|
10
|
-
let ON_REQUEST_RECEIVED_EVENT: String = "onRequestReceived"
|
|
10
|
+
let crv: CoseEcCurve = CoseEcCurve.P256
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var rejector: RCTPromiseRejectBlock?
|
|
12
|
+
let ON_RESPONSE_SENT_EVENT: String = "onResponseSent"
|
|
13
|
+
let ON_REQUEST_RECEIVED_EVENT: String = "onRequestReceived"
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
var secureArea: SecureArea?
|
|
16
|
+
var bleServerTransfer: MdocGattServer?
|
|
17
|
+
var resolver: RCTPromiseResolveBlock?
|
|
18
|
+
var rejector: RCTPromiseRejectBlock?
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return
|
|
24
|
-
}
|
|
20
|
+
override func supportedEvents() -> [String]! {
|
|
21
|
+
return ["onResponseSent", "onRequestReceived"]
|
|
22
|
+
}
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
24
|
+
// NFC is not enabled on iOS
|
|
25
|
+
@objc func enableNfc() {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
InitializeKeys.send_response_manually.rawValue: true,
|
|
37
|
-
])
|
|
38
|
-
bleServerTransfer?.delegate = self
|
|
39
|
-
} catch {
|
|
40
|
-
return error.localizedDescription
|
|
41
|
-
}
|
|
29
|
+
@objc func initialize(_ serviceName: String) -> String? {
|
|
30
|
+
guard bleServerTransfer == nil else {
|
|
31
|
+
return MdocDataTransferError.BleGattServerAlreadyInitialized.localizedDescription
|
|
32
|
+
}
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
secureArea = SoftwareSecureArea.create(
|
|
35
|
+
storage: KeyChainSecureKeyStorage(serviceName: serviceName, accessGroup: nil))
|
|
36
|
+
|
|
37
|
+
do {
|
|
38
|
+
bleServerTransfer = try MdocGattServer(
|
|
39
|
+
parameters: InitializeTransferData(
|
|
40
|
+
dataFormats: [:],
|
|
41
|
+
documentData: [:],
|
|
42
|
+
docDisplayNames: [:],
|
|
43
|
+
privateKeyData: [:],
|
|
44
|
+
trustedCertificates: [],
|
|
45
|
+
deviceAuthMethod: DeviceAuthMethod.deviceSignature.rawValue,
|
|
46
|
+
idsToDocTypes: [:],
|
|
47
|
+
hashingAlgs: [:],
|
|
48
|
+
sendDeviceResponseManually: true)
|
|
49
|
+
)
|
|
50
|
+
bleServerTransfer?.delegate = self
|
|
51
|
+
} catch {
|
|
52
|
+
return error.localizedDescription
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
return nil
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc func startQrEngagement(
|
|
59
|
+
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
60
|
+
reject: @escaping RCTPromiseRejectBlock
|
|
61
|
+
) {
|
|
62
|
+
Task {
|
|
63
|
+
resolver = resolve
|
|
64
|
+
rejector = reject
|
|
65
|
+
|
|
66
|
+
guard let bleServerTransfer = bleServerTransfer, let secureArea = secureArea else {
|
|
67
|
+
self.reject(
|
|
68
|
+
MdocDataTransferError.BleGattServerNotInitialized
|
|
69
|
+
.localizedDescription)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
60
72
|
|
|
61
|
-
|
|
73
|
+
do {
|
|
74
|
+
try await bleServerTransfer.performDeviceEngagement(secureArea: secureArea, crv: crv)
|
|
75
|
+
} catch {
|
|
76
|
+
self.reject(error.localizedDescription)
|
|
77
|
+
}
|
|
62
78
|
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@objc func sendDeviceResponse(
|
|
82
|
+
_ deviceResponse: String,
|
|
83
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
84
|
+
reject: @escaping RCTPromiseRejectBlock
|
|
85
|
+
) {
|
|
86
|
+
Task {
|
|
87
|
+
resolver = resolve
|
|
88
|
+
rejector = reject
|
|
89
|
+
|
|
90
|
+
guard let bleServerTransfer = bleServerTransfer,
|
|
91
|
+
var sessionEncryption = bleServerTransfer.sessionEncryption
|
|
92
|
+
else {
|
|
93
|
+
self.reject(
|
|
94
|
+
MdocDataTransferError.BleGattServerNotInitialized
|
|
95
|
+
.localizedDescription)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
63
98
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
var sessionEncryption = bleServerTransfer.sessionEncryption
|
|
68
|
-
else {
|
|
69
|
-
return MdocDataTransferError.BleGattServerNotInitialized
|
|
70
|
-
.localizedDescription
|
|
99
|
+
do {
|
|
100
|
+
let byteArray = deviceResponse.split(separator: ":").compactMap {
|
|
101
|
+
UInt8($0)
|
|
71
102
|
}
|
|
72
|
-
|
|
103
|
+
let cipherData = try await sessionEncryption.encrypt(byteArray)
|
|
104
|
+
let sd = SessionData(cipher_data: cipherData, status: 20)
|
|
105
|
+
try bleServerTransfer.sendDeviceResponse(
|
|
106
|
+
Data(sd.encode(options: CBOROptions())))
|
|
107
|
+
} catch {
|
|
108
|
+
let sd = SessionData(cipher_data: nil, status: 11)
|
|
73
109
|
do {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
let cipherData = try sessionEncryption.encrypt(byteArray)
|
|
78
|
-
let sd = SessionData(cipher_data: cipherData, status: 20)
|
|
79
|
-
try bleServerTransfer.sendResponse(
|
|
80
|
-
Data(sd.encode(options: CBOROptions())))
|
|
110
|
+
try bleServerTransfer.sendDeviceResponse(
|
|
111
|
+
Data(sd.encode(options: CBOROptions())))
|
|
81
112
|
} catch {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
try bleServerTransfer.sendResponse(
|
|
85
|
-
Data(sd.encode(options: CBOROptions())))
|
|
86
|
-
} catch {
|
|
87
|
-
return error.localizedDescription
|
|
88
|
-
}
|
|
89
|
-
return error.localizedDescription
|
|
113
|
+
self.reject(error.localizedDescription)
|
|
114
|
+
return
|
|
90
115
|
}
|
|
91
|
-
|
|
92
|
-
return
|
|
116
|
+
self.reject(error.localizedDescription)
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
resolve(nil)
|
|
93
120
|
}
|
|
121
|
+
}
|
|
94
122
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.localizedDescription
|
|
100
|
-
|
|
101
|
-
}
|
|
123
|
+
@objc func shutdown() -> String? {
|
|
124
|
+
guard let bleServerTransfer = bleServerTransfer else {
|
|
125
|
+
return MdocDataTransferError.BleGattServerNotInitialized
|
|
126
|
+
.localizedDescription
|
|
102
127
|
|
|
103
|
-
|
|
128
|
+
}
|
|
104
129
|
|
|
105
|
-
|
|
106
|
-
rejector = nil
|
|
107
|
-
resolver = nil
|
|
130
|
+
bleServerTransfer.stop()
|
|
108
131
|
|
|
109
|
-
|
|
110
|
-
|
|
132
|
+
self.bleServerTransfer = nil
|
|
133
|
+
rejector = nil
|
|
134
|
+
resolver = nil
|
|
111
135
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
fatalError(
|
|
115
|
-
MdocDataTransferError.RejectorNotInitialized
|
|
116
|
-
.localizedDescription)
|
|
117
|
-
}
|
|
118
|
-
rejector("ERROR", message, nil)
|
|
136
|
+
return nil
|
|
137
|
+
}
|
|
119
138
|
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
private func reject(_ message: String) {
|
|
140
|
+
guard let rejector = rejector else {
|
|
141
|
+
fatalError(
|
|
142
|
+
MdocDataTransferError.RejectorNotInitialized
|
|
143
|
+
.localizedDescription)
|
|
122
144
|
}
|
|
145
|
+
rejector("ERROR", message, nil)
|
|
123
146
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
MdocDataTransferError.ResolverNotInitialized
|
|
128
|
-
.localizedDescription)
|
|
129
|
-
}
|
|
130
|
-
resolver(result)
|
|
147
|
+
resolver = nil
|
|
148
|
+
self.rejector = nil
|
|
149
|
+
}
|
|
131
150
|
|
|
132
|
-
|
|
133
|
-
|
|
151
|
+
private func resolve(_ result: Any?) {
|
|
152
|
+
guard let resolver = resolver else {
|
|
153
|
+
fatalError(
|
|
154
|
+
MdocDataTransferError.ResolverNotInitialized
|
|
155
|
+
.localizedDescription)
|
|
134
156
|
}
|
|
157
|
+
resolver(result)
|
|
158
|
+
|
|
159
|
+
self.resolver = nil
|
|
160
|
+
rejector = nil
|
|
161
|
+
}
|
|
135
162
|
}
|
|
136
163
|
|
|
137
164
|
extension MdocDataTransfer: MdocOfflineDelegate {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
switch newStatus {
|
|
149
|
-
case .qrEngagementReady:
|
|
150
|
-
guard let qrCode = bleServerTransfer.qrCodePayload else {
|
|
151
|
-
reject(MdocDataTransferError.QrCodeNotSet.localizedDescription)
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
-
resolve(qrCode)
|
|
155
|
-
case .error:
|
|
156
|
-
guard let error = bleServerTransfer.error else {
|
|
157
|
-
reject(MdocDataTransferError.ErrorNotSet.localizedDescription)
|
|
158
|
-
return
|
|
159
|
-
}
|
|
160
|
-
reject(error.localizedDescription)
|
|
161
|
-
return
|
|
162
|
-
case .responseSent:
|
|
163
|
-
sendEvent(withName: ON_RESPONSE_SENT_EVENT, body: nil)
|
|
164
|
-
default:
|
|
165
|
-
os_log("data transfer status change: %@", newStatus.rawValue)
|
|
166
|
-
}
|
|
167
|
-
|
|
165
|
+
public func didChangeStatus(
|
|
166
|
+
_ newStatus: MdocDataTransfer18013.TransferStatus
|
|
167
|
+
) {
|
|
168
|
+
guard let bleServerTransfer = bleServerTransfer else {
|
|
169
|
+
reject(
|
|
170
|
+
MdocDataTransferError.BleGattServerNotInitialized
|
|
171
|
+
.localizedDescription)
|
|
172
|
+
return
|
|
168
173
|
}
|
|
169
174
|
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
switch newStatus {
|
|
176
|
+
case .qrEngagementReady:
|
|
177
|
+
guard let qrCode = bleServerTransfer.qrCodePayload else {
|
|
178
|
+
reject(MdocDataTransferError.QrCodeNotSet.localizedDescription)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
resolve(qrCode)
|
|
182
|
+
case .error:
|
|
183
|
+
guard let error = bleServerTransfer.error else {
|
|
184
|
+
reject(MdocDataTransferError.ErrorNotSet.localizedDescription)
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
reject(error.localizedDescription)
|
|
188
|
+
return
|
|
189
|
+
case .responseSent:
|
|
190
|
+
sendEvent(withName: ON_RESPONSE_SENT_EVENT, body: nil)
|
|
191
|
+
default:
|
|
192
|
+
os_log("data transfer status change: %@", newStatus.rawValue)
|
|
172
193
|
}
|
|
173
194
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
"sessionTranscript": sessionTranscriptBytes,
|
|
192
|
-
"deviceRequest": deviceRequestBytes,
|
|
193
|
-
])
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public func didFinishedWithError(_ error: any Error) {
|
|
198
|
+
reject(error.localizedDescription)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public func didReceiveRequest(
|
|
202
|
+
_ request: MdocDataTransfer18013.UserRequestInfo?,
|
|
203
|
+
handleSelected: @escaping (Bool, MdocDataTransfer18013.RequestItems?) async -> Void
|
|
204
|
+
) {
|
|
205
|
+
guard
|
|
206
|
+
let sessionTranscriptBytes = bleServerTransfer?.sessionEncryption?
|
|
207
|
+
.sessionTranscriptBytes,
|
|
208
|
+
let deviceRequestBytes = bleServerTransfer?.deviceRequest?.encode(
|
|
209
|
+
options: CBOROptions())
|
|
210
|
+
else {
|
|
211
|
+
return
|
|
194
212
|
}
|
|
213
|
+
|
|
214
|
+
sendEvent(
|
|
215
|
+
withName: ON_REQUEST_RECEIVED_EVENT,
|
|
216
|
+
body: [
|
|
217
|
+
"sessionTranscript": sessionTranscriptBytes,
|
|
218
|
+
"deviceRequest": deviceRequestBytes,
|
|
219
|
+
])
|
|
220
|
+
}
|
|
195
221
|
}
|
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
public enum MdocDataTransferError: Error {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
case BleGattServerNotInitialized
|
|
3
|
+
case BleGattServerAlreadyInitialized
|
|
4
|
+
case DocumentsNotProvided
|
|
5
|
+
case RejectorNotInitialized
|
|
6
|
+
case ResolverNotInitialized
|
|
7
|
+
case QrCodeNotSet
|
|
8
|
+
case ErrorNotSet
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
extension MdocDataTransferError: LocalizedError {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
12
|
+
public var errorDescription: String? {
|
|
13
|
+
switch self {
|
|
14
|
+
case .BleGattServerNotInitialized:
|
|
15
|
+
return NSLocalizedString(
|
|
16
|
+
"Ble Gatt Server is not initialized. Please call `initialize()` before.",
|
|
17
|
+
comment: "")
|
|
18
|
+
case .BleGattServerAlreadyInitialized:
|
|
19
|
+
return NSLocalizedString(
|
|
20
|
+
"Ble Gatt Server is already initialized. Please call `shutdown()` before initializing again.",
|
|
21
|
+
comment: "")
|
|
22
|
+
case .DocumentsNotProvided:
|
|
23
|
+
return NSLocalizedString("Documents are not provided.", comment: "")
|
|
24
|
+
case .RejectorNotInitialized:
|
|
25
|
+
return NSLocalizedString(
|
|
26
|
+
"Rejector is not initialized. Invalid state. Bug occurred.",
|
|
27
|
+
comment: "")
|
|
28
|
+
case .ResolverNotInitialized:
|
|
29
|
+
return NSLocalizedString(
|
|
30
|
+
"Resolver is not initialized. Invalid state. Bug occurred.",
|
|
31
|
+
comment: "")
|
|
32
|
+
case .QrCodeNotSet:
|
|
33
|
+
return NSLocalizedString(
|
|
34
|
+
"QRCode not set on the object. Invalid state. Issue in EUDI mdoc library.",
|
|
35
|
+
comment: "")
|
|
36
|
+
case .ErrorNotSet:
|
|
37
|
+
return NSLocalizedString(
|
|
38
|
+
"Error not set on the object. Invalid state. Issue in EUDI mdoc library.",
|
|
39
|
+
comment: "")
|
|
41
40
|
}
|
|
41
|
+
}
|
|
42
42
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export interface Spec extends TurboModule {
|
|
1
|
+
export interface Spec {
|
|
4
2
|
enableNfc: () => void
|
|
5
3
|
|
|
6
4
|
// String indicates an error on iOS legacy architecture
|
|
7
|
-
initialize: () => undefined | string
|
|
5
|
+
initialize: (serviceName: string) => undefined | string
|
|
8
6
|
|
|
9
7
|
startQrEngagement: () => Promise<string>
|
|
10
8
|
|
|
11
|
-
sendDeviceResponse: (devceResponse: string) => void
|
|
9
|
+
sendDeviceResponse: (devceResponse: string) => Promise<void>
|
|
12
10
|
|
|
13
11
|
// String indicates an error on iOS legacy architecture
|
|
14
12
|
shutdown: () => undefined | string
|
|
15
13
|
}
|
|
16
|
-
|
|
17
|
-
export const turboModuleMdocDataTransfer = () => TurboModuleRegistry.getEnforcing<Spec>('MdocDataTransfer')
|