@trustchex/react-native-sdk 1.381.0 → 1.464.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/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKModule.kt +2 -8
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +60 -13
- package/android/src/main/java/com/trustchex/reactnativesdk/mlkit/MLKitModule.kt +1 -1
- package/ios/Camera/TrustchexCameraView.swift +10 -13
- package/ios/MLKit/MLKitModule.swift +1 -1
- package/lib/module/Screens/Debug/BarcodeTestScreen.js +308 -0
- package/lib/module/Screens/Debug/MRZTestScreen.js +105 -13
- package/lib/module/Screens/Debug/NFCScanTestScreen.js +635 -0
- package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +49 -32
- package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +22 -4
- package/lib/module/Screens/Dynamic/IdentityDocumentScanningScreen.js +5 -0
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +126 -27
- package/lib/module/Screens/Dynamic/VerbalConsentScreen.js +1079 -0
- package/lib/module/Screens/Dynamic/VideoCallScreen.js +678 -0
- package/lib/module/Screens/Static/OTPVerificationScreen.js +6 -0
- package/lib/module/Screens/Static/QrCodeScanningScreen.js +7 -1
- package/lib/module/Screens/Static/ResultScreen.js +154 -34
- package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +59 -51
- package/lib/module/Shared/Animations/recording.json +1 -0
- package/lib/module/Shared/Animations/video-call.json +1 -0
- package/lib/module/Shared/Components/DebugNavigationPanel.js +231 -67
- package/lib/module/Shared/Components/EIDScanner.js +213 -112
- package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +5 -3
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +77 -39
- package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +13 -4
- package/lib/module/Shared/Components/NavigationManager.js +39 -19
- package/lib/module/Shared/Contexts/AppContext.js +1 -0
- package/lib/module/Shared/EIDReader/aesSecureMessagingWrapper.js +51 -0
- package/lib/module/Shared/EIDReader/apduLevelPACECapable.js +3 -0
- package/lib/module/Shared/EIDReader/bacKey.js +16 -2
- package/lib/module/Shared/EIDReader/eidReader.js +354 -13
- package/lib/module/Shared/EIDReader/eidService.js +25 -1
- package/lib/module/Shared/EIDReader/nfcManagerCardService.js +4 -7
- package/lib/module/Shared/EIDReader/paceInfo.js +85 -0
- package/lib/module/Shared/EIDReader/paceKeySpec.js +51 -0
- package/lib/module/Shared/EIDReader/protocol/paceAPDUSender.js +100 -0
- package/lib/module/Shared/EIDReader/protocol/paceProtocol.js +655 -0
- package/lib/module/Shared/EIDReader/protocol/paceResult.js +37 -0
- package/lib/module/Shared/EIDReader/secureMessagingWrapper.js +27 -4
- package/lib/module/Shared/EIDReader/smartcards/commandAPDU.js +2 -1
- package/lib/module/Shared/EIDReader/tlv/tlv.helpers.js +1 -1
- package/lib/module/Shared/EIDReader/tlv/tlv.utils.js +6 -3
- package/lib/module/Shared/EIDReader/utils/aesCrypto.utils.js +189 -0
- package/lib/module/Shared/Libs/SignalingClient.js +128 -0
- package/lib/module/Shared/Libs/analytics.utils.js +8 -0
- package/lib/module/Shared/Libs/contains.js +1 -40
- package/lib/module/Shared/Libs/country-display.utils.js +34 -0
- package/lib/module/Shared/Libs/deeplink.utils.js +9 -1
- package/lib/module/Shared/Libs/demo.utils.js +8 -0
- package/lib/module/Shared/Libs/http-client.js +9 -0
- package/lib/module/Shared/Libs/mrz.utils.js +3 -2
- package/lib/module/Shared/Libs/promise.utils.js +16 -2
- package/lib/module/Shared/Libs/status-bar.utils.js +23 -0
- package/lib/module/Shared/Services/DataUploadService.js +294 -0
- package/lib/module/Shared/Services/VideoSessionService.js +156 -0
- package/lib/module/Shared/Services/WebRTCService.js +510 -0
- package/lib/module/Shared/Types/analytics.types.js +4 -0
- package/lib/module/Translation/Resources/en.js +61 -2
- package/lib/module/Translation/Resources/tr.js +61 -2
- package/lib/module/Trustchex.js +64 -20
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Debug/BarcodeTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/BarcodeTestScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/IdentityDocumentScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts +3 -0
- package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts.map +1 -0
- package/lib/typescript/src/Screens/Static/OTPVerificationScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/QrCodeScanningScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +5 -0
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts +1 -0
- package/lib/typescript/src/Shared/Contexts/AppContext.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts +18 -0
- package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts +23 -0
- package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts +6 -0
- package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts +9 -0
- package/lib/typescript/src/Shared/EIDReader/eidService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/nfcManagerCardService.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts +50 -0
- package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts +30 -0
- package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts +17 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts +105 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts +24 -0
- package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts.map +1 -0
- package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts +15 -0
- package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/smartcards/commandAPDU.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/tlv/tlv.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts +39 -0
- package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/SignalingClient.d.ts +24 -0
- package/lib/typescript/src/Shared/Libs/SignalingClient.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/contains.d.ts +0 -7
- package/lib/typescript/src/Shared/Libs/contains.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts +2 -0
- package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/deeplink.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts +1 -1
- package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/promise.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts +9 -0
- package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Services/DataUploadService.d.ts +25 -0
- package/lib/typescript/src/Shared/Services/DataUploadService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Services/VideoSessionService.d.ts +33 -0
- package/lib/typescript/src/Shared/Services/VideoSessionService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Services/WebRTCService.d.ts +58 -0
- package/lib/typescript/src/Shared/Services/WebRTCService.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts +4 -0
- package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Types/identificationInfo.d.ts +13 -1
- package/lib/typescript/src/Shared/Types/identificationInfo.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +60 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +60 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/Trustchex.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +35 -5
- package/src/Screens/Debug/BarcodeTestScreen.tsx +317 -0
- package/src/Screens/Debug/MRZTestScreen.tsx +107 -13
- package/src/Screens/Debug/NFCScanTestScreen.tsx +692 -0
- package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +58 -35
- package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +27 -4
- package/src/Screens/Dynamic/IdentityDocumentScanningScreen.tsx +6 -0
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +156 -27
- package/src/Screens/Dynamic/VerbalConsentScreen.tsx +1401 -0
- package/src/Screens/Dynamic/VideoCallScreen.tsx +766 -0
- package/src/Screens/Static/OTPVerificationScreen.tsx +6 -0
- package/src/Screens/Static/QrCodeScanningScreen.tsx +7 -1
- package/src/Screens/Static/ResultScreen.tsx +235 -48
- package/src/Screens/Static/VerificationSessionCheckScreen.tsx +67 -72
- package/src/Shared/Animations/recording.json +1 -0
- package/src/Shared/Animations/video-call.json +1 -0
- package/src/Shared/Components/DebugNavigationPanel.tsx +252 -51
- package/src/Shared/Components/EIDScanner.tsx +223 -116
- package/src/Shared/Components/IdentityDocumentCamera.flows.ts +7 -4
- package/src/Shared/Components/IdentityDocumentCamera.tsx +224 -188
- package/src/Shared/Components/IdentityDocumentCamera.utils.ts +13 -4
- package/src/Shared/Components/NavigationManager.tsx +41 -19
- package/src/Shared/Contexts/AppContext.ts +2 -0
- package/src/Shared/EIDReader/aesSecureMessagingWrapper.ts +69 -0
- package/src/Shared/EIDReader/apduLevelPACECapable.ts +34 -0
- package/src/Shared/EIDReader/bacKey.ts +24 -8
- package/src/Shared/EIDReader/eidReader.ts +398 -12
- package/src/Shared/EIDReader/eidService.ts +49 -1
- package/src/Shared/EIDReader/nfcManagerCardService.ts +4 -6
- package/src/Shared/EIDReader/paceInfo.ts +159 -0
- package/src/Shared/EIDReader/paceKeySpec.ts +56 -0
- package/src/Shared/EIDReader/protocol/paceAPDUSender.ts +163 -0
- package/src/Shared/EIDReader/protocol/paceProtocol.ts +946 -0
- package/src/Shared/EIDReader/protocol/paceResult.ts +62 -0
- package/src/Shared/EIDReader/secureMessagingWrapper.ts +28 -10
- package/src/Shared/EIDReader/smartcards/commandAPDU.ts +2 -1
- package/src/Shared/EIDReader/tlv/tlv.helpers.ts +1 -1
- package/src/Shared/EIDReader/tlv/tlv.utils.ts +8 -5
- package/src/Shared/EIDReader/utils/aesCrypto.utils.ts +217 -0
- package/src/Shared/Libs/SignalingClient.ts +189 -0
- package/src/Shared/Libs/analytics.utils.ts +8 -0
- package/src/Shared/Libs/contains.ts +0 -53
- package/src/Shared/Libs/country-display.utils.ts +55 -0
- package/src/Shared/Libs/crypto.utils.ts +2 -2
- package/src/Shared/Libs/deeplink.utils.ts +12 -1
- package/src/Shared/Libs/demo.utils.ts +10 -0
- package/src/Shared/Libs/http-client.ts +19 -1
- package/src/Shared/Libs/mrz.utils.ts +3 -2
- package/src/Shared/Libs/promise.utils.ts +16 -2
- package/src/Shared/Libs/status-bar.utils.ts +21 -0
- package/src/Shared/Services/DataUploadService.ts +395 -0
- package/src/Shared/Services/VideoSessionService.ts +190 -0
- package/src/Shared/Services/WebRTCService.ts +636 -0
- package/src/Shared/Types/analytics.types.ts +4 -0
- package/src/Shared/Types/identificationInfo.ts +16 -1
- package/src/Translation/Resources/en.ts +88 -3
- package/src/Translation/Resources/tr.ts +89 -3
- package/src/Trustchex.tsx +65 -19
- package/src/version.ts +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AccessKeySpec } from '../accessKeySpec';
|
|
2
|
+
import type { SecureMessagingWrapper } from '../secureMessagingWrapper';
|
|
3
|
+
import type { MappingType } from '../paceInfo';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Result of PACE protocol execution.
|
|
7
|
+
*/
|
|
8
|
+
export class PACEResult {
|
|
9
|
+
private paceKey: AccessKeySpec;
|
|
10
|
+
private mappingType: MappingType;
|
|
11
|
+
private agreementAlg: string;
|
|
12
|
+
private cipherAlg: string;
|
|
13
|
+
private digestAlg: string;
|
|
14
|
+
private keyLength: number;
|
|
15
|
+
private wrapper: SecureMessagingWrapper;
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
paceKey: AccessKeySpec,
|
|
19
|
+
mappingType: MappingType,
|
|
20
|
+
agreementAlg: string,
|
|
21
|
+
cipherAlg: string,
|
|
22
|
+
digestAlg: string,
|
|
23
|
+
keyLength: number,
|
|
24
|
+
wrapper: SecureMessagingWrapper
|
|
25
|
+
) {
|
|
26
|
+
this.paceKey = paceKey;
|
|
27
|
+
this.mappingType = mappingType;
|
|
28
|
+
this.agreementAlg = agreementAlg;
|
|
29
|
+
this.cipherAlg = cipherAlg;
|
|
30
|
+
this.digestAlg = digestAlg;
|
|
31
|
+
this.keyLength = keyLength;
|
|
32
|
+
this.wrapper = wrapper;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public getPACEKey(): AccessKeySpec {
|
|
36
|
+
return this.paceKey;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public getMappingType(): MappingType {
|
|
40
|
+
return this.mappingType;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public getAgreementAlg(): string {
|
|
44
|
+
return this.agreementAlg;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public getCipherAlg(): string {
|
|
48
|
+
return this.cipherAlg;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public getDigestAlg(): string {
|
|
52
|
+
return this.digestAlg;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public getKeyLength(): number {
|
|
56
|
+
return this.keyLength;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public getWrapper(): SecureMessagingWrapper {
|
|
60
|
+
return this.wrapper;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -87,7 +87,7 @@ export abstract class SecureMessagingWrapper implements APDUWrapper {
|
|
|
87
87
|
dataOutputStream.push(...paddedData);
|
|
88
88
|
let cc2 = Uint8Array.from(
|
|
89
89
|
Buffer.from(
|
|
90
|
-
|
|
90
|
+
this.computeMAC(
|
|
91
91
|
Buffer.from(dataOutputStream).toString('hex'),
|
|
92
92
|
this.ksMac
|
|
93
93
|
),
|
|
@@ -116,6 +116,30 @@ export abstract class SecureMessagingWrapper implements APDUWrapper {
|
|
|
116
116
|
|
|
117
117
|
protected abstract getEncodedSendSequenceCounter(): Uint8Array;
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Encrypt data using the session encryption key.
|
|
121
|
+
* Subclasses override for AES vs 3DES.
|
|
122
|
+
*/
|
|
123
|
+
protected encrypt(dataHex: string, keyHex: string): string {
|
|
124
|
+
return cryptoUtils.encryptWith3DES(dataHex, keyHex);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Decrypt data using the session encryption key.
|
|
129
|
+
* Subclasses override for AES vs 3DES.
|
|
130
|
+
*/
|
|
131
|
+
protected decrypt(dataHex: string, keyHex: string): string {
|
|
132
|
+
return cryptoUtils.decryptWith3DES(dataHex, keyHex);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Compute MAC over data using the session MAC key.
|
|
137
|
+
* Subclasses override for AES-CMAC vs 3DES MAC.
|
|
138
|
+
*/
|
|
139
|
+
protected computeMAC(dataHex: string, keyHex: string): string {
|
|
140
|
+
return cryptoUtils.computeMac(dataHex, keyHex);
|
|
141
|
+
}
|
|
142
|
+
|
|
119
143
|
private wrapCommandAPDU(commandAPDU: CommandAPDU): CommandAPDU {
|
|
120
144
|
const cla = commandAPDU.getCLA();
|
|
121
145
|
const ins = commandAPDU.getINS();
|
|
@@ -149,10 +173,7 @@ export abstract class SecureMessagingWrapper implements APDUWrapper {
|
|
|
149
173
|
this.getPadLength()
|
|
150
174
|
);
|
|
151
175
|
const ciphertext = Buffer.from(
|
|
152
|
-
|
|
153
|
-
Buffer.from(data).toString('hex'),
|
|
154
|
-
this.ksEnc
|
|
155
|
-
),
|
|
176
|
+
this.encrypt(Buffer.from(data).toString('hex'), this.ksEnc),
|
|
156
177
|
'hex'
|
|
157
178
|
);
|
|
158
179
|
output.push(hasDO85 ? 0x85 : 0x87);
|
|
@@ -180,7 +201,7 @@ export abstract class SecureMessagingWrapper implements APDUWrapper {
|
|
|
180
201
|
);
|
|
181
202
|
|
|
182
203
|
const cc = Buffer.from(
|
|
183
|
-
|
|
204
|
+
this.computeMAC(Buffer.from(n).toString('hex'), this.ksMac),
|
|
184
205
|
'hex'
|
|
185
206
|
);
|
|
186
207
|
let ccLength = cc.length;
|
|
@@ -329,10 +350,7 @@ export abstract class SecureMessagingWrapper implements APDUWrapper {
|
|
|
329
350
|
inputStream.readFully(ciphertext);
|
|
330
351
|
const paddedData = Array.from(
|
|
331
352
|
Buffer.from(
|
|
332
|
-
|
|
333
|
-
Buffer.from(ciphertext).toString('hex'),
|
|
334
|
-
this.ksEnc
|
|
335
|
-
),
|
|
353
|
+
this.decrypt(Buffer.from(ciphertext).toString('hex'), this.ksEnc),
|
|
336
354
|
'hex'
|
|
337
355
|
)
|
|
338
356
|
);
|
|
@@ -18,7 +18,8 @@ export class CommandAPDU {
|
|
|
18
18
|
ne?: number
|
|
19
19
|
) {
|
|
20
20
|
this.nc = dataLength || 0;
|
|
21
|
-
|
|
21
|
+
// Java JMRTD uses -1 to mean "no Le field" (ne=0). Guard against negatives.
|
|
22
|
+
this.ne = ne == null || ne < 0 ? 0 : ne;
|
|
22
23
|
this.apdu = this.buildAPDU(
|
|
23
24
|
cla,
|
|
24
25
|
ins,
|
|
@@ -6,7 +6,6 @@ import { Buffer } from 'buffer';
|
|
|
6
6
|
import { TLVHelpers } from './tlv.helpers';
|
|
7
7
|
|
|
8
8
|
class TLVUtil extends TLVHelpers {
|
|
9
|
-
|
|
10
9
|
public static wrapDO(tag: number, data: number[]): Uint8Array {
|
|
11
10
|
if (data == null) {
|
|
12
11
|
throw new Error('Data to wrap is null');
|
|
@@ -49,7 +48,7 @@ class TLVUtil extends TLVHelpers {
|
|
|
49
48
|
const actualTag = await tlvInputStream.readTag();
|
|
50
49
|
if (actualTag !== expectedTag) {
|
|
51
50
|
throw new Error(
|
|
52
|
-
`Expected tag ${expectedTag.toString(16)}, found
|
|
51
|
+
`Expected TLV tag 0x${expectedTag.toString(16)}, found 0x${actualTag.toString(16)} in data: ${Buffer.from(wrappedData.slice(0, 16)).toString('hex')}`
|
|
53
52
|
);
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -61,8 +60,13 @@ class TLVUtil extends TLVHelpers {
|
|
|
61
60
|
}
|
|
62
61
|
return result;
|
|
63
62
|
} catch (ioe) {
|
|
64
|
-
//
|
|
65
|
-
|
|
63
|
+
// Re-throw original error with context rather than masking it
|
|
64
|
+
if (ioe instanceof Error && ioe.message.includes('Expected TLV tag')) {
|
|
65
|
+
throw ioe;
|
|
66
|
+
}
|
|
67
|
+
throw new Error(
|
|
68
|
+
`TLV unwrap error (expected tag 0x${expectedTag.toString(16)}): ${ioe instanceof Error ? ioe.message : String(ioe)}`
|
|
69
|
+
);
|
|
66
70
|
} finally {
|
|
67
71
|
try {
|
|
68
72
|
tlvInputStream.close();
|
|
@@ -72,7 +76,6 @@ class TLVUtil extends TLVHelpers {
|
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
|
-
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
export default TLVUtil;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import CryptoJS from 'crypto-js';
|
|
2
|
+
import { Buffer } from 'buffer';
|
|
3
|
+
import 'react-native-get-random-values';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* AES cryptographic utilities for PACE protocol.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Encrypt data using AES in CBC mode with zero IV.
|
|
11
|
+
*/
|
|
12
|
+
export const aesEncryptCBC = (
|
|
13
|
+
dataHex: string,
|
|
14
|
+
keyHex: string,
|
|
15
|
+
ivHex: string = '00000000000000000000000000000000'
|
|
16
|
+
): string => {
|
|
17
|
+
const data = CryptoJS.enc.Hex.parse(dataHex);
|
|
18
|
+
const key = CryptoJS.enc.Hex.parse(keyHex);
|
|
19
|
+
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
|
20
|
+
|
|
21
|
+
const encrypted = CryptoJS.AES.encrypt(data, key, {
|
|
22
|
+
mode: CryptoJS.mode.CBC,
|
|
23
|
+
padding: CryptoJS.pad.NoPadding,
|
|
24
|
+
iv,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return encrypted.ciphertext.toString(CryptoJS.enc.Hex);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Decrypt data using AES in CBC mode with zero IV.
|
|
32
|
+
*/
|
|
33
|
+
export const aesDecryptCBC = (
|
|
34
|
+
dataHex: string,
|
|
35
|
+
keyHex: string,
|
|
36
|
+
ivHex: string = '00000000000000000000000000000000'
|
|
37
|
+
): string => {
|
|
38
|
+
const data = CryptoJS.enc.Hex.parse(dataHex);
|
|
39
|
+
const key = CryptoJS.enc.Hex.parse(keyHex);
|
|
40
|
+
const iv = CryptoJS.enc.Hex.parse(ivHex);
|
|
41
|
+
|
|
42
|
+
const cipherParams = CryptoJS.lib.CipherParams.create({
|
|
43
|
+
ciphertext: data,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const decrypted = CryptoJS.AES.decrypt(cipherParams, key, {
|
|
47
|
+
mode: CryptoJS.mode.CBC,
|
|
48
|
+
padding: CryptoJS.pad.NoPadding,
|
|
49
|
+
iv,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return decrypted.toString(CryptoJS.enc.Hex);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Encrypt a single block with AES in ECB mode (for SSC encryption).
|
|
57
|
+
*/
|
|
58
|
+
export const aesEncryptECB = (dataHex: string, keyHex: string): string => {
|
|
59
|
+
const data = CryptoJS.enc.Hex.parse(dataHex);
|
|
60
|
+
const key = CryptoJS.enc.Hex.parse(keyHex);
|
|
61
|
+
|
|
62
|
+
const encrypted = CryptoJS.AES.encrypt(data, key, {
|
|
63
|
+
mode: CryptoJS.mode.ECB,
|
|
64
|
+
padding: CryptoJS.pad.NoPadding,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return encrypted.ciphertext.toString(CryptoJS.enc.Hex);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Compute AES CMAC (OMAC1) as defined in RFC 4493.
|
|
72
|
+
*/
|
|
73
|
+
export const aesCMAC = (dataHex: string, keyHex: string): string => {
|
|
74
|
+
const key = Buffer.from(keyHex, 'hex');
|
|
75
|
+
const data = Buffer.from(dataHex, 'hex');
|
|
76
|
+
const blockSize = 16;
|
|
77
|
+
|
|
78
|
+
// Step 1: Generate subkeys
|
|
79
|
+
const zeroBlock = '00000000000000000000000000000000';
|
|
80
|
+
const L = Buffer.from(aesEncryptECB(zeroBlock, keyHex), 'hex');
|
|
81
|
+
const K1 = generateSubkey(L);
|
|
82
|
+
const K2 = generateSubkey(K1);
|
|
83
|
+
|
|
84
|
+
// Step 2: Determine if we need to pad
|
|
85
|
+
const n = data.length === 0 ? 1 : Math.ceil(data.length / blockSize);
|
|
86
|
+
const lastBlockComplete = data.length > 0 && data.length % blockSize === 0;
|
|
87
|
+
|
|
88
|
+
// Step 3: Process last block
|
|
89
|
+
const lastBlock = Buffer.alloc(blockSize);
|
|
90
|
+
if (lastBlockComplete) {
|
|
91
|
+
const start = (n - 1) * blockSize;
|
|
92
|
+
for (let i = 0; i < blockSize; i++) {
|
|
93
|
+
lastBlock[i] = data[start + i] ^ K1[i];
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
// Pad with 10*
|
|
97
|
+
const start = (n - 1) * blockSize;
|
|
98
|
+
const remaining = data.length - start;
|
|
99
|
+
const padded = Buffer.alloc(blockSize);
|
|
100
|
+
for (let i = 0; i < remaining; i++) {
|
|
101
|
+
padded[i] = data[start + i];
|
|
102
|
+
}
|
|
103
|
+
padded[remaining] = 0x80;
|
|
104
|
+
for (let i = 0; i < blockSize; i++) {
|
|
105
|
+
lastBlock[i] = padded[i] ^ K2[i];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Step 4: CBC-MAC
|
|
110
|
+
let X = Buffer.alloc(blockSize);
|
|
111
|
+
for (let i = 0; i < n - 1; i++) {
|
|
112
|
+
const block = data.subarray(i * blockSize, (i + 1) * blockSize);
|
|
113
|
+
const Y = Buffer.alloc(blockSize);
|
|
114
|
+
for (let j = 0; j < blockSize; j++) {
|
|
115
|
+
Y[j] = X[j] ^ block[j];
|
|
116
|
+
}
|
|
117
|
+
X = Buffer.from(aesEncryptECB(Y.toString('hex'), keyHex), 'hex');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Process last block
|
|
121
|
+
const Y = Buffer.alloc(blockSize);
|
|
122
|
+
for (let j = 0; j < blockSize; j++) {
|
|
123
|
+
Y[j] = X[j] ^ lastBlock[j];
|
|
124
|
+
}
|
|
125
|
+
const T = aesEncryptECB(Y.toString('hex'), keyHex);
|
|
126
|
+
|
|
127
|
+
return T;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
function generateSubkey(input: Buffer): Buffer {
|
|
131
|
+
const blockSize = 16;
|
|
132
|
+
const Rb = Buffer.alloc(blockSize);
|
|
133
|
+
Rb[blockSize - 1] = 0x87;
|
|
134
|
+
|
|
135
|
+
// Left shift by 1
|
|
136
|
+
const output = Buffer.alloc(blockSize);
|
|
137
|
+
const msb = (input[0] & 0x80) !== 0;
|
|
138
|
+
for (let i = 0; i < blockSize - 1; i++) {
|
|
139
|
+
output[i] = ((input[i] << 1) | (input[i + 1] >> 7)) & 0xff;
|
|
140
|
+
}
|
|
141
|
+
output[blockSize - 1] = (input[blockSize - 1] << 1) & 0xff;
|
|
142
|
+
|
|
143
|
+
if (msb) {
|
|
144
|
+
for (let i = 0; i < blockSize; i++) {
|
|
145
|
+
output[i] ^= Rb[i];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return output;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Derive AES key from shared secret using KDF as per TR-SAC.
|
|
154
|
+
*
|
|
155
|
+
* @param sharedSecretHex the shared secret bytes as hex
|
|
156
|
+
* @param cipherAlg 'AES' or 'DESede'
|
|
157
|
+
* @param keyLength 128, 192, or 256
|
|
158
|
+
* @param mode 1 = ENC, 2 = MAC, 3 = PACE
|
|
159
|
+
*/
|
|
160
|
+
export const deriveKey = (
|
|
161
|
+
sharedSecretHex: string,
|
|
162
|
+
cipherAlg: string,
|
|
163
|
+
keyLength: number,
|
|
164
|
+
mode: number
|
|
165
|
+
): string => {
|
|
166
|
+
const input = sharedSecretHex + '000000' + mode.toString(16).padStart(2, '0');
|
|
167
|
+
|
|
168
|
+
let hash: string;
|
|
169
|
+
if (cipherAlg === 'AES' && keyLength > 128) {
|
|
170
|
+
// Use SHA-256 for AES-192 and AES-256
|
|
171
|
+
hash = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(input)).toString(
|
|
172
|
+
CryptoJS.enc.Hex
|
|
173
|
+
);
|
|
174
|
+
} else {
|
|
175
|
+
// Use SHA-1 for DESede and AES-128
|
|
176
|
+
hash = CryptoJS.SHA1(CryptoJS.enc.Hex.parse(input)).toString(
|
|
177
|
+
CryptoJS.enc.Hex
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (cipherAlg === 'DESede') {
|
|
182
|
+
// 3DES: 24-byte key (K1 || K2 || K1)
|
|
183
|
+
const ka = hash.substring(0, 16);
|
|
184
|
+
const kb = hash.substring(16, 32);
|
|
185
|
+
return ka + kb + ka;
|
|
186
|
+
} else {
|
|
187
|
+
// AES: return first keyLength/8 bytes
|
|
188
|
+
const keyBytes = keyLength / 4; // hex chars = keyLength / 8 * 2
|
|
189
|
+
return hash.substring(0, keyBytes);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Pad data using ISO 9797-1 method 2 with given block size.
|
|
195
|
+
*/
|
|
196
|
+
export const padISO9797 = (data: Buffer, blockSize: number = 16): Buffer => {
|
|
197
|
+
const n = data.length;
|
|
198
|
+
const padLength = blockSize - (n % blockSize);
|
|
199
|
+
const out = Buffer.alloc(n + padLength);
|
|
200
|
+
data.copy(out);
|
|
201
|
+
out[n] = 0x80;
|
|
202
|
+
return out;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Unpad ISO 9797-1 method 2.
|
|
207
|
+
*/
|
|
208
|
+
export const unpadISO9797 = (data: Buffer): Buffer => {
|
|
209
|
+
let i = data.length - 1;
|
|
210
|
+
while (i >= 0 && data[i] === 0x00) {
|
|
211
|
+
i--;
|
|
212
|
+
}
|
|
213
|
+
if (i >= 0 && data[i] === 0x80) {
|
|
214
|
+
return data.subarray(0, i);
|
|
215
|
+
}
|
|
216
|
+
return data;
|
|
217
|
+
};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import EventSource, { type EventSourceListener } from 'react-native-sse';
|
|
2
|
+
|
|
3
|
+
export type SignalingMessageType =
|
|
4
|
+
| 'offer'
|
|
5
|
+
| 'answer'
|
|
6
|
+
| 'ice-candidate'
|
|
7
|
+
| 'command';
|
|
8
|
+
|
|
9
|
+
export interface SignalingMessage {
|
|
10
|
+
id?: string;
|
|
11
|
+
type: SignalingMessageType;
|
|
12
|
+
payload: any;
|
|
13
|
+
createdAt?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type SignalingEventHandler = (message: SignalingMessage) => void;
|
|
17
|
+
export type SessionEndedHandler = (state: string) => void;
|
|
18
|
+
|
|
19
|
+
export class SignalingClient {
|
|
20
|
+
private eventSource: EventSource | null = null;
|
|
21
|
+
private sessionId: string;
|
|
22
|
+
private baseUrl: string;
|
|
23
|
+
private onMessage: SignalingEventHandler;
|
|
24
|
+
private onConnected?: () => void;
|
|
25
|
+
private onDisconnected?: () => void;
|
|
26
|
+
private onSessionEnded?: SessionEndedHandler;
|
|
27
|
+
private identificationId?: string;
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
baseUrl: string,
|
|
31
|
+
sessionId: string,
|
|
32
|
+
onMessage: SignalingEventHandler,
|
|
33
|
+
identificationId?: string,
|
|
34
|
+
onSessionEnded?: SessionEndedHandler
|
|
35
|
+
) {
|
|
36
|
+
this.baseUrl = baseUrl;
|
|
37
|
+
this.sessionId = sessionId;
|
|
38
|
+
this.onMessage = onMessage;
|
|
39
|
+
this.identificationId = identificationId;
|
|
40
|
+
this.onSessionEnded = onSessionEnded;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public connect(): void {
|
|
44
|
+
if (this.eventSource) {
|
|
45
|
+
this.eventSource.close();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const urlParams = new URLSearchParams();
|
|
49
|
+
if (this.identificationId) {
|
|
50
|
+
urlParams.append('identificationId', this.identificationId);
|
|
51
|
+
}
|
|
52
|
+
const url = `${this.baseUrl}/api/app/mobile/video-sessions/${this.sessionId}/signaling/stream?${urlParams.toString()}`;
|
|
53
|
+
|
|
54
|
+
console.log('[SignalingClient] Connecting to SSE:', url);
|
|
55
|
+
|
|
56
|
+
this.eventSource = new EventSource(url, {
|
|
57
|
+
pollingInterval: 0, // 0 means default/no polling if SSE is real
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const listener: EventSourceListener = (event) => {
|
|
61
|
+
if (event.type === 'open') {
|
|
62
|
+
console.log('[SignalingClient] Connected');
|
|
63
|
+
this.onConnected?.();
|
|
64
|
+
} else if (event.type === 'error') {
|
|
65
|
+
console.error(
|
|
66
|
+
'[SignalingClient] Connection error:',
|
|
67
|
+
JSON.stringify(event, null, 2)
|
|
68
|
+
);
|
|
69
|
+
this.onDisconnected?.();
|
|
70
|
+
} else if (event.type === 'message') {
|
|
71
|
+
try {
|
|
72
|
+
const data = JSON.parse(event.data || '{}');
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
['offer', 'answer', 'ice-candidate', 'command'].includes(data.type)
|
|
76
|
+
) {
|
|
77
|
+
this.onMessage({
|
|
78
|
+
id: data.id,
|
|
79
|
+
type: data.type as SignalingMessageType,
|
|
80
|
+
payload: data.payload,
|
|
81
|
+
createdAt: data.createdAt,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error('[SignalingClient] Error parsing message:', e);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const customEventListener = (event: any) => {
|
|
91
|
+
try {
|
|
92
|
+
const data = JSON.parse(event.data || '{}');
|
|
93
|
+
const eventType = event.type;
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
['offer', 'answer', 'ice-candidate', 'command'].includes(eventType)
|
|
97
|
+
) {
|
|
98
|
+
this.onMessage({
|
|
99
|
+
id: data.id,
|
|
100
|
+
type: eventType as SignalingMessageType,
|
|
101
|
+
payload: data.payload,
|
|
102
|
+
createdAt: data.createdAt,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.error('[SignalingClient] Error parsing custom event:', e);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Ping handler - server sends pings to keep connection alive
|
|
111
|
+
const pingListener = (event: any) => {
|
|
112
|
+
console.log('[SignalingClient] Received ping');
|
|
113
|
+
// Just acknowledge by doing nothing, server-side heartbeat keeps connection alive
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Session-ended event listener
|
|
117
|
+
const sessionEndedListener = (event: any) => {
|
|
118
|
+
try {
|
|
119
|
+
const data = JSON.parse(event.data || '{}');
|
|
120
|
+
console.log('[SignalingClient] Session ended:', data.state);
|
|
121
|
+
if (this.onSessionEnded) {
|
|
122
|
+
this.onSessionEnded(data.state);
|
|
123
|
+
}
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.error(
|
|
126
|
+
'[SignalingClient] Error parsing session-ended event:',
|
|
127
|
+
e
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
this.eventSource.addEventListener('open', listener);
|
|
133
|
+
this.eventSource.addEventListener('message', listener);
|
|
134
|
+
this.eventSource.addEventListener('error', listener);
|
|
135
|
+
this.eventSource.addEventListener('ping' as any, pingListener);
|
|
136
|
+
this.eventSource.addEventListener('offer' as any, customEventListener);
|
|
137
|
+
this.eventSource.addEventListener('answer' as any, customEventListener);
|
|
138
|
+
this.eventSource.addEventListener(
|
|
139
|
+
'ice-candidate' as any,
|
|
140
|
+
customEventListener
|
|
141
|
+
);
|
|
142
|
+
this.eventSource.addEventListener('command' as any, customEventListener);
|
|
143
|
+
this.eventSource.addEventListener(
|
|
144
|
+
'session-ended' as any,
|
|
145
|
+
sessionEndedListener
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async send(type: SignalingMessageType, payload: any): Promise<void> {
|
|
150
|
+
const urlParams = new URLSearchParams();
|
|
151
|
+
if (this.identificationId) {
|
|
152
|
+
urlParams.append('identificationId', this.identificationId);
|
|
153
|
+
}
|
|
154
|
+
const url = `${this.baseUrl}/api/app/mobile/video-sessions/${this.sessionId}/signaling?${urlParams.toString()}`;
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const body = {
|
|
158
|
+
type,
|
|
159
|
+
data: payload,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const response = await fetch(url, {
|
|
163
|
+
method: 'POST',
|
|
164
|
+
headers: {
|
|
165
|
+
'Content-Type': 'application/json',
|
|
166
|
+
},
|
|
167
|
+
body: JSON.stringify(body),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (!response.ok) {
|
|
171
|
+
throw new Error(
|
|
172
|
+
`Failed to send signaling message: ${response.statusText}`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error('[SignalingClient] Error sending message:', error);
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
public disconnect(): void {
|
|
182
|
+
if (this.eventSource) {
|
|
183
|
+
this.eventSource.removeAllEventListeners();
|
|
184
|
+
this.eventSource.close();
|
|
185
|
+
this.eventSource = null;
|
|
186
|
+
this.onDisconnected?.();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -289,6 +289,14 @@ const STEP_EVENT_MAP: Record<
|
|
|
289
289
|
started: AnalyticsEventName.LIVENESS_CHECK_STARTED,
|
|
290
290
|
completed: AnalyticsEventName.LIVENESS_CHECK_COMPLETED,
|
|
291
291
|
},
|
|
292
|
+
verbal_consent: {
|
|
293
|
+
started: AnalyticsEventName.VERBAL_CONSENT_VIDEO_STARTED,
|
|
294
|
+
completed: AnalyticsEventName.VERBAL_CONSENT_VIDEO_COMPLETED,
|
|
295
|
+
},
|
|
296
|
+
video_call: {
|
|
297
|
+
started: AnalyticsEventName.VIDEO_CALL_STARTED,
|
|
298
|
+
completed: AnalyticsEventName.VIDEO_CALL_COMPLETED,
|
|
299
|
+
},
|
|
292
300
|
};
|
|
293
301
|
|
|
294
302
|
function getStepEventName(
|
|
@@ -4,56 +4,3 @@ export interface Rect {
|
|
|
4
4
|
width: number;
|
|
5
5
|
height: number;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
interface Contains {
|
|
9
|
-
outside: Rect;
|
|
10
|
-
inside: Rect;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function contains({ outside, inside }: Contains) {
|
|
14
|
-
const outsideMaxX = outside.minX + outside.width;
|
|
15
|
-
const insideMaxX = inside.minX + inside.width;
|
|
16
|
-
|
|
17
|
-
const outsideMaxY = outside.minY + outside.height;
|
|
18
|
-
const insideMaxY = inside.minY + inside.height;
|
|
19
|
-
|
|
20
|
-
if (inside.minX < outside.minX) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
if (insideMaxX > outsideMaxX) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
if (inside.minY < outside.minY) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
if (insideMaxY > outsideMaxY) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function contains2({ outside, inside }: Contains) {
|
|
37
|
-
const outsideMaxX = outside.minX + outside.width;
|
|
38
|
-
const insideMaxX = inside.minX + inside.width;
|
|
39
|
-
|
|
40
|
-
const outsideMaxY = outside.minY + outside.height;
|
|
41
|
-
const insideMaxY = inside.minY + inside.height;
|
|
42
|
-
|
|
43
|
-
const xIntersect = Math.max(
|
|
44
|
-
0,
|
|
45
|
-
Math.min(insideMaxX, outsideMaxX) - Math.max(inside.minX, outside.minX)
|
|
46
|
-
);
|
|
47
|
-
const yIntersect = Math.max(
|
|
48
|
-
0,
|
|
49
|
-
Math.min(insideMaxY, outsideMaxY) - Math.max(inside.minY, outside.minY)
|
|
50
|
-
);
|
|
51
|
-
const intersectArea = xIntersect * yIntersect;
|
|
52
|
-
|
|
53
|
-
const insideArea = inside.width * inside.height;
|
|
54
|
-
const outsideArea = outside.width * outside.height;
|
|
55
|
-
|
|
56
|
-
const unionArea = insideArea + outsideArea - intersectArea;
|
|
57
|
-
|
|
58
|
-
return unionArea === outsideArea;
|
|
59
|
-
}
|