@trustchex/react-native-sdk 1.409.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.
Files changed (156) hide show
  1. package/android/src/main/java/com/trustchex/reactnativesdk/TrustchexSDKModule.kt +2 -8
  2. package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +59 -1
  3. package/ios/Camera/TrustchexCameraView.swift +9 -1
  4. package/lib/module/Screens/Debug/NFCScanTestScreen.js +635 -0
  5. package/lib/module/Screens/Dynamic/ContractAcceptanceScreen.js +1 -4
  6. package/lib/module/Screens/Dynamic/IdentityDocumentEIDScanningScreen.js +17 -4
  7. package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +102 -23
  8. package/lib/module/Screens/Dynamic/VerbalConsentScreen.js +1079 -0
  9. package/lib/module/Screens/Dynamic/VideoCallScreen.js +3 -1
  10. package/lib/module/Screens/Static/ResultScreen.js +128 -22
  11. package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +8 -0
  12. package/lib/module/Shared/Animations/recording.json +1 -0
  13. package/lib/module/Shared/Components/DebugNavigationPanel.js +69 -71
  14. package/lib/module/Shared/Components/EIDScanner.js +212 -108
  15. package/lib/module/Shared/Components/IdentityDocumentCamera.flows.js +5 -3
  16. package/lib/module/Shared/Components/IdentityDocumentCamera.js +53 -36
  17. package/lib/module/Shared/Components/IdentityDocumentCamera.utils.js +13 -4
  18. package/lib/module/Shared/Components/NavigationManager.js +24 -16
  19. package/lib/module/Shared/EIDReader/aesSecureMessagingWrapper.js +51 -0
  20. package/lib/module/Shared/EIDReader/apduLevelPACECapable.js +3 -0
  21. package/lib/module/Shared/EIDReader/bacKey.js +16 -2
  22. package/lib/module/Shared/EIDReader/eidReader.js +354 -13
  23. package/lib/module/Shared/EIDReader/eidService.js +25 -1
  24. package/lib/module/Shared/EIDReader/nfcManagerCardService.js +4 -7
  25. package/lib/module/Shared/EIDReader/paceInfo.js +85 -0
  26. package/lib/module/Shared/EIDReader/paceKeySpec.js +51 -0
  27. package/lib/module/Shared/EIDReader/protocol/paceAPDUSender.js +100 -0
  28. package/lib/module/Shared/EIDReader/protocol/paceProtocol.js +655 -0
  29. package/lib/module/Shared/EIDReader/protocol/paceResult.js +37 -0
  30. package/lib/module/Shared/EIDReader/secureMessagingWrapper.js +27 -4
  31. package/lib/module/Shared/EIDReader/smartcards/commandAPDU.js +2 -1
  32. package/lib/module/Shared/EIDReader/tlv/tlv.helpers.js +1 -1
  33. package/lib/module/Shared/EIDReader/tlv/tlv.utils.js +6 -3
  34. package/lib/module/Shared/EIDReader/utils/aesCrypto.utils.js +189 -0
  35. package/lib/module/Shared/Libs/analytics.utils.js +4 -0
  36. package/lib/module/Shared/Libs/contains.js +1 -40
  37. package/lib/module/Shared/Libs/country-display.utils.js +34 -0
  38. package/lib/module/Shared/Libs/demo.utils.js +8 -0
  39. package/lib/module/Shared/Libs/mrz.utils.js +3 -2
  40. package/lib/module/Shared/Libs/status-bar.utils.js +4 -2
  41. package/lib/module/Shared/Types/analytics.types.js +2 -0
  42. package/lib/module/Translation/Resources/en.js +41 -2
  43. package/lib/module/Translation/Resources/tr.js +41 -2
  44. package/lib/module/Trustchex.js +54 -20
  45. package/lib/module/version.js +1 -1
  46. package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts +3 -0
  47. package/lib/typescript/src/Screens/Debug/NFCScanTestScreen.d.ts.map +1 -0
  48. package/lib/typescript/src/Screens/Dynamic/ContractAcceptanceScreen.d.ts.map +1 -1
  49. package/lib/typescript/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.d.ts.map +1 -1
  50. package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
  51. package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts +3 -0
  52. package/lib/typescript/src/Screens/Dynamic/VerbalConsentScreen.d.ts.map +1 -0
  53. package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts.map +1 -1
  54. package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
  55. package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
  56. package/lib/typescript/src/Shared/Components/DebugNavigationPanel.d.ts.map +1 -1
  57. package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
  58. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  59. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts +1 -1
  60. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.flows.d.ts.map +1 -1
  61. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts +5 -0
  62. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.utils.d.ts.map +1 -1
  63. package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
  64. package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts +18 -0
  65. package/lib/typescript/src/Shared/EIDReader/aesSecureMessagingWrapper.d.ts.map +1 -0
  66. package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts +23 -0
  67. package/lib/typescript/src/Shared/EIDReader/apduLevelPACECapable.d.ts.map +1 -0
  68. package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts +6 -0
  69. package/lib/typescript/src/Shared/EIDReader/bacKey.d.ts.map +1 -1
  70. package/lib/typescript/src/Shared/EIDReader/eidReader.d.ts.map +1 -1
  71. package/lib/typescript/src/Shared/EIDReader/eidService.d.ts +9 -0
  72. package/lib/typescript/src/Shared/EIDReader/eidService.d.ts.map +1 -1
  73. package/lib/typescript/src/Shared/EIDReader/nfcManagerCardService.d.ts.map +1 -1
  74. package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts +50 -0
  75. package/lib/typescript/src/Shared/EIDReader/paceInfo.d.ts.map +1 -0
  76. package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts +30 -0
  77. package/lib/typescript/src/Shared/EIDReader/paceKeySpec.d.ts.map +1 -0
  78. package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts +17 -0
  79. package/lib/typescript/src/Shared/EIDReader/protocol/paceAPDUSender.d.ts.map +1 -0
  80. package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts +105 -0
  81. package/lib/typescript/src/Shared/EIDReader/protocol/paceProtocol.d.ts.map +1 -0
  82. package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts +24 -0
  83. package/lib/typescript/src/Shared/EIDReader/protocol/paceResult.d.ts.map +1 -0
  84. package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts +15 -0
  85. package/lib/typescript/src/Shared/EIDReader/secureMessagingWrapper.d.ts.map +1 -1
  86. package/lib/typescript/src/Shared/EIDReader/smartcards/commandAPDU.d.ts.map +1 -1
  87. package/lib/typescript/src/Shared/EIDReader/tlv/tlv.utils.d.ts.map +1 -1
  88. package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts +39 -0
  89. package/lib/typescript/src/Shared/EIDReader/utils/aesCrypto.utils.d.ts.map +1 -0
  90. package/lib/typescript/src/Shared/Libs/analytics.utils.d.ts.map +1 -1
  91. package/lib/typescript/src/Shared/Libs/contains.d.ts +0 -7
  92. package/lib/typescript/src/Shared/Libs/contains.d.ts.map +1 -1
  93. package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts +2 -0
  94. package/lib/typescript/src/Shared/Libs/country-display.utils.d.ts.map +1 -0
  95. package/lib/typescript/src/Shared/Libs/demo.utils.d.ts.map +1 -1
  96. package/lib/typescript/src/Shared/Libs/http-client.d.ts +1 -1
  97. package/lib/typescript/src/Shared/Libs/http-client.d.ts.map +1 -1
  98. package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
  99. package/lib/typescript/src/Shared/Libs/status-bar.utils.d.ts.map +1 -1
  100. package/lib/typescript/src/Shared/Types/analytics.types.d.ts +2 -0
  101. package/lib/typescript/src/Shared/Types/analytics.types.d.ts.map +1 -1
  102. package/lib/typescript/src/Shared/Types/identificationInfo.d.ts +10 -1
  103. package/lib/typescript/src/Shared/Types/identificationInfo.d.ts.map +1 -1
  104. package/lib/typescript/src/Translation/Resources/en.d.ts +40 -1
  105. package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
  106. package/lib/typescript/src/Translation/Resources/tr.d.ts +40 -1
  107. package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
  108. package/lib/typescript/src/Trustchex.d.ts.map +1 -1
  109. package/lib/typescript/src/version.d.ts +1 -1
  110. package/package.json +7 -4
  111. package/src/Screens/Debug/NFCScanTestScreen.tsx +692 -0
  112. package/src/Screens/Dynamic/ContractAcceptanceScreen.tsx +1 -4
  113. package/src/Screens/Dynamic/IdentityDocumentEIDScanningScreen.tsx +21 -4
  114. package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +124 -23
  115. package/src/Screens/Dynamic/VerbalConsentScreen.tsx +1401 -0
  116. package/src/Screens/Dynamic/VideoCallScreen.tsx +3 -1
  117. package/src/Screens/Static/ResultScreen.tsx +183 -31
  118. package/src/Screens/Static/VerificationSessionCheckScreen.tsx +9 -0
  119. package/src/Shared/Animations/recording.json +1 -0
  120. package/src/Shared/Components/DebugNavigationPanel.tsx +73 -48
  121. package/src/Shared/Components/EIDScanner.tsx +222 -111
  122. package/src/Shared/Components/IdentityDocumentCamera.flows.ts +7 -4
  123. package/src/Shared/Components/IdentityDocumentCamera.tsx +199 -184
  124. package/src/Shared/Components/IdentityDocumentCamera.utils.ts +13 -4
  125. package/src/Shared/Components/NavigationManager.tsx +27 -18
  126. package/src/Shared/EIDReader/aesSecureMessagingWrapper.ts +69 -0
  127. package/src/Shared/EIDReader/apduLevelPACECapable.ts +34 -0
  128. package/src/Shared/EIDReader/bacKey.ts +24 -8
  129. package/src/Shared/EIDReader/eidReader.ts +398 -12
  130. package/src/Shared/EIDReader/eidService.ts +49 -1
  131. package/src/Shared/EIDReader/nfcManagerCardService.ts +4 -6
  132. package/src/Shared/EIDReader/paceInfo.ts +159 -0
  133. package/src/Shared/EIDReader/paceKeySpec.ts +56 -0
  134. package/src/Shared/EIDReader/protocol/paceAPDUSender.ts +163 -0
  135. package/src/Shared/EIDReader/protocol/paceProtocol.ts +946 -0
  136. package/src/Shared/EIDReader/protocol/paceResult.ts +62 -0
  137. package/src/Shared/EIDReader/secureMessagingWrapper.ts +28 -10
  138. package/src/Shared/EIDReader/smartcards/commandAPDU.ts +2 -1
  139. package/src/Shared/EIDReader/tlv/tlv.helpers.ts +1 -1
  140. package/src/Shared/EIDReader/tlv/tlv.utils.ts +8 -5
  141. package/src/Shared/EIDReader/utils/aesCrypto.utils.ts +217 -0
  142. package/src/Shared/Libs/analytics.utils.ts +4 -0
  143. package/src/Shared/Libs/contains.ts +0 -53
  144. package/src/Shared/Libs/country-display.utils.ts +55 -0
  145. package/src/Shared/Libs/crypto.utils.ts +2 -2
  146. package/src/Shared/Libs/demo.utils.ts +10 -0
  147. package/src/Shared/Libs/http-client.ts +12 -4
  148. package/src/Shared/Libs/mrz.utils.ts +3 -2
  149. package/src/Shared/Libs/status-bar.utils.ts +4 -2
  150. package/src/Shared/Services/VideoSessionService.ts +1 -1
  151. package/src/Shared/Types/analytics.types.ts +2 -0
  152. package/src/Shared/Types/identificationInfo.ts +11 -0
  153. package/src/Translation/Resources/en.ts +63 -3
  154. package/src/Translation/Resources/tr.ts +62 -3
  155. package/src/Trustchex.tsx +53 -17
  156. package/src/version.ts +1 -1
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ import { SecureMessagingWrapper } from "./secureMessagingWrapper.js";
4
+ import { Buffer } from 'buffer';
5
+ import { aesEncryptCBC, aesDecryptCBC, aesEncryptECB, aesCMAC } from "./utils/aesCrypto.utils.js";
6
+
7
+ /**
8
+ * AES-based secure messaging wrapper for PACE.
9
+ *
10
+ * Uses AES-CBC for encryption and AES-CMAC for MAC computation,
11
+ * as specified in ICAO Doc 9303 Part 11.
12
+ */
13
+ export class AESSecureMessagingWrapper extends SecureMessagingWrapper {
14
+ constructor(ksEnc, ksMac, maxTransceiveLength, shouldCheckMAC, ssc) {
15
+ super(ksEnc, ksMac, maxTransceiveLength, shouldCheckMAC, ssc);
16
+ }
17
+ getType() {
18
+ return 'AES';
19
+ }
20
+ getPadLength() {
21
+ return 16;
22
+ }
23
+ getIV() {
24
+ // AES IV is E(ksEnc, SSC)
25
+ const sscHex = Buffer.from(this.getEncodedSendSequenceCounter()).toString('hex');
26
+ const ivHex = aesEncryptECB(sscHex, this.getEncryptionKey());
27
+ return Array.from(Buffer.from(ivHex, 'hex'));
28
+ }
29
+ encrypt(dataHex, keyHex) {
30
+ const ivHex = Buffer.from(this.getIV()).toString('hex');
31
+ return aesEncryptCBC(dataHex, keyHex, ivHex);
32
+ }
33
+ decrypt(dataHex, keyHex) {
34
+ const ivHex = Buffer.from(this.getIV()).toString('hex');
35
+ return aesDecryptCBC(dataHex, keyHex, ivHex);
36
+ }
37
+ computeMAC(dataHex, keyHex) {
38
+ return aesCMAC(dataHex, keyHex);
39
+ }
40
+ getEncodedSendSequenceCounter() {
41
+ // AES uses 16-byte SSC (128-bit counter)
42
+ const ssc = this.getSendSequenceCounter();
43
+ const bytes = new Uint8Array(16);
44
+ let remaining = ssc;
45
+ for (let i = 15; i >= 0; i--) {
46
+ bytes[i] = Number(remaining & 0xffn);
47
+ remaining >>= 8n;
48
+ }
49
+ return bytes;
50
+ }
51
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ export {};
@@ -69,13 +69,27 @@ export class BACKey {
69
69
  */
70
70
  getKey() {
71
71
  try {
72
- const mrz = this.documentNumber + MRZInfo.checkDigit(this.documentNumber, false) + this.dateOfBirth + MRZInfo.checkDigit(this.dateOfBirth, false) + this.dateOfExpiry + MRZInfo.checkDigit(this.dateOfExpiry, false);
73
- return cryptoUtils.computeKeySeed(mrz, 'SHA-1', true);
72
+ return cryptoUtils.computeKeySeed(this.getMRZString(), 'SHA-1', true);
74
73
  } catch (gse) {
75
74
  throw new Error('Unexpected exception');
76
75
  }
77
76
  }
78
77
 
78
+ /**
79
+ * Returns the key seed for PACE, which is the full (non-truncated) SHA-1 hash
80
+ * of the MRZ info. PACE uses the full 20-byte hash unlike BAC which truncates to 16.
81
+ */
82
+ getKeySeedForPACE() {
83
+ try {
84
+ return cryptoUtils.computeKeySeed(this.getMRZString(), 'SHA-1', false);
85
+ } catch (gse) {
86
+ throw new Error('Unexpected exception');
87
+ }
88
+ }
89
+ getMRZString() {
90
+ return this.documentNumber + MRZInfo.checkDigit(this.documentNumber, false) + this.dateOfBirth + MRZInfo.checkDigit(this.dateOfBirth, false) + this.dateOfExpiry + MRZInfo.checkDigit(this.dateOfExpiry, false);
91
+ }
92
+
79
93
  /**
80
94
  * Sets the document number.
81
95
  *
@@ -1,35 +1,374 @@
1
1
  "use strict";
2
2
 
3
3
  import { BACKey } from "./bacKey.js";
4
+ import { PACEKeySpec } from "./paceKeySpec.js";
4
5
  import { NFCManagerCardService } from "./nfcManagerCardService.js";
5
6
  import { EIDService } from "./eidService.js";
6
7
  import { DG1File } from "./lds/icao/dg1File.js";
7
8
  import { DG2File } from "./lds/icao/dg2File.js";
8
9
  import { Buffer } from 'buffer';
9
10
  import { InputStream } from "./java/inputStream.js";
11
+
12
+ // --- Minimal PNG encoder (pure JS, no native deps) ---
13
+ // Uses deflate stored (uncompressed) blocks for O(n) encoding speed.
14
+ // A naive DCT-based JPEG encoder would be O(n²) and freeze the JS thread
15
+ // on real passport photos (400×500+ pixels).
16
+
17
+ /** Standard CRC32 lookup table */
18
+ const CRC_TABLE = new Uint32Array(256);
19
+ for (let n = 0; n < 256; n++) {
20
+ let c = n;
21
+ for (let k = 0; k < 8; k++) {
22
+ c = c & 1 ? 0xedb88320 ^ c >>> 1 : c >>> 1;
23
+ }
24
+ CRC_TABLE[n] = c;
25
+ }
26
+ function crc32(data) {
27
+ let crc = 0xffffffff;
28
+ for (let i = 0; i < data.length; i++) {
29
+ crc = CRC_TABLE[(crc ^ data[i]) & 0xff] ^ crc >>> 8;
30
+ }
31
+ return (crc ^ 0xffffffff) >>> 0;
32
+ }
33
+ function adler32(data) {
34
+ let a = 1;
35
+ let b = 0;
36
+ for (let i = 0; i < data.length; i++) {
37
+ a = (a + data[i]) % 65521;
38
+ b = (b + a) % 65521;
39
+ }
40
+ return (b << 16 | a) >>> 0;
41
+ }
42
+ function writeU32BE(arr, offset, val) {
43
+ arr[offset] = val >>> 24 & 0xff;
44
+ arr[offset + 1] = val >>> 16 & 0xff;
45
+ arr[offset + 2] = val >>> 8 & 0xff;
46
+ arr[offset + 3] = val & 0xff;
47
+ }
48
+
49
+ /**
50
+ * Encode raw RGB/RGBA pixels as an uncompressed PNG.
51
+ * Uses deflate stored blocks (no compression) for maximum compatibility.
52
+ */
53
+ function pixelsToPng(pixels, width, height, channels) {
54
+ // Build raw scanlines: filter byte (0) + RGB data per row
55
+ const rawRowLen = 1 + width * 3; // filter byte + RGB
56
+ const rawData = new Uint8Array(rawRowLen * height);
57
+ for (let y = 0; y < height; y++) {
58
+ const rowOff = y * rawRowLen;
59
+ rawData[rowOff] = 0; // filter: None
60
+ for (let x = 0; x < width; x++) {
61
+ const srcIdx = (y * width + x) * channels;
62
+ const dstIdx = rowOff + 1 + x * 3;
63
+ rawData[dstIdx] = pixels[srcIdx]; // R
64
+ rawData[dstIdx + 1] = pixels[srcIdx + 1]; // G
65
+ rawData[dstIdx + 2] = pixels[srcIdx + 2]; // B
66
+ }
67
+ }
68
+
69
+ // Wrap raw data in zlib stored (uncompressed) format
70
+ const MAX_BLOCK = 65535;
71
+ const numBlocks = Math.ceil(rawData.length / MAX_BLOCK) || 1;
72
+ const zlibSize = 2 + rawData.length + numBlocks * 5 + 4;
73
+ const zlib = new Uint8Array(zlibSize);
74
+ let zOff = 0;
75
+ // zlib header: CMF=0x78 (deflate, 32K window), FLG=0x01 (check bits, no dict, level 0)
76
+ zlib[zOff++] = 0x78;
77
+ zlib[zOff++] = 0x01;
78
+ let remaining = rawData.length;
79
+ let srcOff = 0;
80
+ while (remaining > 0) {
81
+ const blockLen = Math.min(remaining, MAX_BLOCK);
82
+ const isFinal = remaining <= MAX_BLOCK ? 1 : 0;
83
+ zlib[zOff++] = isFinal; // BFINAL + BTYPE=00 (stored)
84
+ zlib[zOff++] = blockLen & 0xff;
85
+ zlib[zOff++] = blockLen >>> 8 & 0xff;
86
+ zlib[zOff++] = ~blockLen & 0xff;
87
+ zlib[zOff++] = ~blockLen >>> 8 & 0xff;
88
+ zlib.set(rawData.subarray(srcOff, srcOff + blockLen), zOff);
89
+ zOff += blockLen;
90
+ srcOff += blockLen;
91
+ remaining -= blockLen;
92
+ }
93
+ // Adler32 of uncompressed data
94
+ const adl = adler32(rawData);
95
+ writeU32BE(zlib, zOff, adl);
96
+ zOff += 4;
97
+ const zlibData = zlib.subarray(0, zOff);
98
+
99
+ // Build PNG chunks
100
+ const PNG_SIG = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
101
+ function makeChunk(type, data) {
102
+ const chunk = new Uint8Array(4 + 4 + data.length + 4);
103
+ writeU32BE(chunk, 0, data.length);
104
+ chunk[4] = type.charCodeAt(0);
105
+ chunk[5] = type.charCodeAt(1);
106
+ chunk[6] = type.charCodeAt(2);
107
+ chunk[7] = type.charCodeAt(3);
108
+ chunk.set(data, 8);
109
+ const crcInput = chunk.subarray(4, 8 + data.length);
110
+ writeU32BE(chunk, 8 + data.length, crc32(crcInput));
111
+ return chunk;
112
+ }
113
+
114
+ // IHDR: width, height, bit depth 8, color type 2 (RGB)
115
+ const ihdrData = new Uint8Array(13);
116
+ writeU32BE(ihdrData, 0, width);
117
+ writeU32BE(ihdrData, 4, height);
118
+ ihdrData[8] = 8; // bit depth
119
+ ihdrData[9] = 2; // color type: RGB
120
+ ihdrData[10] = 0; // compression
121
+ ihdrData[11] = 0; // filter
122
+ ihdrData[12] = 0; // interlace
123
+
124
+ const ihdrChunk = makeChunk('IHDR', ihdrData);
125
+ const idatChunk = makeChunk('IDAT', zlibData);
126
+ const iendChunk = makeChunk('IEND', new Uint8Array(0));
127
+ const png = new Uint8Array(PNG_SIG.length + ihdrChunk.length + idatChunk.length + iendChunk.length);
128
+ let off = 0;
129
+ png.set(PNG_SIG, off);
130
+ off += PNG_SIG.length;
131
+ png.set(ihdrChunk, off);
132
+ off += ihdrChunk.length;
133
+ png.set(idatChunk, off);
134
+ off += idatChunk.length;
135
+ png.set(iendChunk, off);
136
+ return png;
137
+ }
138
+
139
+ /**
140
+ * If the image is JPEG 2000, decode and convert to PNG so React Native can display it.
141
+ * Returns { base64, mimeType } with the converted image, or the original if not JP2.
142
+ */
143
+ function convertJP2IfNeeded(imageBuffer, mimeType) {
144
+ if (mimeType !== 'image/jp2') {
145
+ return {
146
+ base64: imageBuffer.toString('base64'),
147
+ mimeType
148
+ };
149
+ }
150
+ console.debug('[EID] Face image is JP2, attempting conversion…');
151
+ try {
152
+ // Lazy-load jpeg2000 to avoid crashing if it fails to import
153
+ const {
154
+ JpxImage
155
+ } = require('jpeg2000');
156
+ const jpx = new JpxImage();
157
+ jpx.parse(imageBuffer);
158
+ const tile = jpx.tiles[0];
159
+ console.debug(`[EID] JP2 decoded: ${tile.width}x${tile.height}, ${jpx.componentsCount} channels, ${tile.items.length} bytes`);
160
+ const pngBytes = pixelsToPng(tile.items, tile.width, tile.height, jpx.componentsCount);
161
+ const pngBase64 = Buffer.from(pngBytes).toString('base64');
162
+ console.debug(`[EID] Converted JP2 → PNG (${pngBytes.length} bytes, ${pngBase64.length} base64 chars)`);
163
+ return {
164
+ base64: pngBase64,
165
+ mimeType: 'image/png'
166
+ };
167
+ } catch (err) {
168
+ console.debug('[EID] JP2 conversion failed:', err);
169
+ return {
170
+ base64: imageBuffer.toString('base64'),
171
+ mimeType
172
+ };
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Try to parse PACE OID and parameter ID from EF.CardAccess data.
178
+ * Returns null if no PACE info is found.
179
+ */
180
+ function parsePACEInfoFromCardAccess(data) {
181
+ try {
182
+ // EF.CardAccess is a SET of SecurityInfo sequences (ASN.1 DER)
183
+ // Each SecurityInfo: SEQUENCE { OID, INTEGER (version), optional INTEGER (parameterId) }
184
+ let offset = 0;
185
+ if (data[offset] === 0x31) {
186
+ // SET tag
187
+ offset++;
188
+ const setLen = readASN1Length(data, offset);
189
+ offset = setLen.nextOffset;
190
+ }
191
+ while (offset < data.length) {
192
+ if (data[offset] !== 0x30) break; // SEQUENCE tag
193
+ offset++;
194
+ const seqLen = readASN1Length(data, offset);
195
+ const seqEnd = seqLen.nextOffset + seqLen.length;
196
+ offset = seqLen.nextOffset;
197
+
198
+ // Read OID
199
+ if (data[offset] !== 0x06) {
200
+ offset = seqEnd;
201
+ continue;
202
+ }
203
+ offset++;
204
+ const oidLen = readASN1Length(data, offset);
205
+ offset = oidLen.nextOffset;
206
+ const oidBytes = data.subarray(offset, offset + oidLen.length);
207
+ const oid = decodeOID(oidBytes);
208
+ offset += oidLen.length;
209
+
210
+ // Check if this is a PACE OID
211
+ if (oid.startsWith('0.4.0.127.0.7.2.2.4.')) {
212
+ // Read version (INTEGER)
213
+ let parameterId = 13; // default brainpoolP256r1
214
+ if (offset < seqEnd && data[offset] === 0x02) {
215
+ offset++;
216
+ const intLen = readASN1Length(data, offset);
217
+ offset = intLen.nextOffset + intLen.length;
218
+ }
219
+ // Read optional parameterId (INTEGER)
220
+ if (offset < seqEnd && data[offset] === 0x02) {
221
+ offset++;
222
+ const intLen = readASN1Length(data, offset);
223
+ offset = intLen.nextOffset;
224
+ parameterId = 0;
225
+ for (let i = 0; i < intLen.length; i++) {
226
+ parameterId = parameterId << 8 | data[offset + i];
227
+ }
228
+ }
229
+ return {
230
+ oid,
231
+ parameterId
232
+ };
233
+ }
234
+ offset = seqEnd;
235
+ }
236
+ } catch {
237
+ // Failed to parse, PACE not available
238
+ }
239
+ return null;
240
+ }
241
+ function readASN1Length(data, offset) {
242
+ const firstByte = data[offset];
243
+ if ((firstByte & 0x80) === 0) {
244
+ return {
245
+ length: firstByte,
246
+ nextOffset: offset + 1
247
+ };
248
+ }
249
+ const numBytes = firstByte & 0x7f;
250
+ let length = 0;
251
+ for (let i = 0; i < numBytes; i++) {
252
+ length = length << 8 | data[offset + 1 + i];
253
+ }
254
+ return {
255
+ length,
256
+ nextOffset: offset + 1 + numBytes
257
+ };
258
+ }
259
+ function decodeOID(bytes) {
260
+ const components = [];
261
+ components.push(Math.floor(bytes[0] / 40));
262
+ components.push(bytes[0] % 40);
263
+ let value = 0;
264
+ for (let i = 1; i < bytes.length; i++) {
265
+ value = value << 7 | bytes[i] & 0x7f;
266
+ if ((bytes[i] & 0x80) === 0) {
267
+ components.push(value);
268
+ value = 0;
269
+ }
270
+ }
271
+ return components.join('.');
272
+ }
10
273
  const eidReader = async (documentNumber, dateOfBirth, dateOfExpiry, progressCallback) => {
11
274
  let progress = 0;
12
275
  const nfcManagerCardService = new NFCManagerCardService();
13
276
  const passportService = new EIDService(nfcManagerCardService, EIDService.NORMAL_MAX_TRANSCEIVE_LENGTH, EIDService.DEFAULT_MAX_BLOCKSIZE, false, true);
14
277
  try {
15
278
  await passportService.open();
279
+ progress = 1;
280
+ if (progressCallback) {
281
+ progressCallback(progress);
282
+ }
16
283
 
17
- // Select Applet for MRTD
18
- await passportService.sendSelectApplet(false);
19
- progress = 10;
284
+ // Try to read EF.CardAccess before selecting applet to check for PACE.
285
+ // Explicitly SELECT MF first so the SFI=0x1C context is correct,
286
+ // regardless of which application the chip activates on power-on.
287
+ let hasPACESucceeded = false;
288
+ try {
289
+ await passportService.sendSelectMF();
290
+ console.debug('[EID] SELECT MF OK');
291
+ } catch (mfErr) {
292
+ const mfMsg = mfErr instanceof Error ? mfErr.message : String(mfErr);
293
+ console.debug(`[EID] SELECT MF failed (${mfMsg}), continuing with SFI read anyway`);
294
+ }
295
+ progress = 2;
20
296
  if (progressCallback) {
21
297
  progressCallback(progress);
22
298
  }
23
299
 
24
- // Check if EF_COM is available
300
+ // Read EF.CardAccess kept in a separate try/catch so we can distinguish
301
+ // "file read failure" from "PACE protocol failure" in the logs.
302
+ let cardAccessBuf = null;
25
303
  try {
26
- const efComStream = passportService.getInputStream(EIDService.EF_COM);
27
- await efComStream.init();
28
- await efComStream.read();
29
- } catch (error) {
30
- // EF_COM not available -> try to do BAC
31
- const bacKey = new BACKey(documentNumber, dateOfBirth, dateOfExpiry);
32
- await passportService.doBAC(bacKey);
304
+ const cardAccessStream = passportService.getInputStream(EIDService.EF_CARD_ACCESS);
305
+ await cardAccessStream.init();
306
+ const cardAccessLen = cardAccessStream.getLength();
307
+ const buf = Buffer.alloc(cardAccessLen);
308
+ for (let i = 0; i < cardAccessLen; i++) {
309
+ buf[i] = await cardAccessStream.read();
310
+ }
311
+ cardAccessBuf = buf;
312
+ console.debug(`[EID] EF.CardAccess read OK: ${cardAccessLen} bytes = ${cardAccessBuf.toString('hex')}`);
313
+ } catch (readErr) {
314
+ const readMsg = readErr instanceof Error ? readErr.message : String(readErr);
315
+ console.debug(`[EID] EF.CardAccess read FAILED: ${readMsg} — falling back to BAC`);
316
+ }
317
+ progress = 3;
318
+ if (progressCallback) {
319
+ progressCallback(progress);
320
+ }
321
+
322
+ // If EF.CardAccess was read successfully, attempt PACE.
323
+ if (cardAccessBuf !== null) {
324
+ try {
325
+ const paceInfo = parsePACEInfoFromCardAccess(cardAccessBuf);
326
+ if (paceInfo) {
327
+ console.debug(`[EID] PACE available: oid=${paceInfo.oid} parameterId=${paceInfo.parameterId}`);
328
+ // PACE is available - derive key from MRZ and perform PACE
329
+ const bacKey = new BACKey(documentNumber, dateOfBirth, dateOfExpiry);
330
+ const paceKey = PACEKeySpec.createMRZKey(bacKey.getKeySeedForPACE());
331
+ progress = 4;
332
+ if (progressCallback) {
333
+ progressCallback(progress);
334
+ }
335
+ await passportService.doPACE(paceKey, paceInfo.oid, paceInfo.parameterId, progressCallback);
336
+ hasPACESucceeded = true;
337
+ console.debug('[EID] PACE succeeded');
338
+ } else {
339
+ console.debug('[EID] EF.CardAccess read OK but no PACE SecurityInfo found — document does not support PACE, falling back to BAC');
340
+ }
341
+ } catch (paceError) {
342
+ // PACE protocol exchange failed — fall back to BAC
343
+ const msg = paceError instanceof Error ? paceError.message : String(paceError);
344
+ console.debug(`[EID] PACE protocol failed (${msg}), falling back to BAC`);
345
+ if (paceError instanceof Error && paceError.stack) {
346
+ console.debug('[EID] PACE error stack:', paceError.stack);
347
+ }
348
+ }
349
+ }
350
+ progress = 9;
351
+ if (progressCallback) {
352
+ progressCallback(progress);
353
+ }
354
+
355
+ // Select Applet for MRTD
356
+ await passportService.sendSelectApplet(hasPACESucceeded);
357
+ progress = 10;
358
+ if (progressCallback) {
359
+ progressCallback(progress);
360
+ }
361
+ if (!hasPACESucceeded) {
362
+ // Check if EF_COM is available
363
+ try {
364
+ const efComStream = passportService.getInputStream(EIDService.EF_COM);
365
+ await efComStream.init();
366
+ await efComStream.read();
367
+ } catch (error) {
368
+ // EF_COM not available -> try to do BAC
369
+ const bacKey = new BACKey(documentNumber, dateOfBirth, dateOfExpiry);
370
+ await passportService.doBAC(bacKey);
371
+ }
33
372
  }
34
373
  progress = 20;
35
374
  if (progressCallback) {
@@ -69,8 +408,10 @@ const eidReader = async (documentNumber, dateOfBirth, dateOfExpiry, progressCall
69
408
  const imageInputStream = await faceImageInfo.getImageInputStream();
70
409
  const buffer = Buffer.alloc(imageLength);
71
410
  await imageInputStream.readBytesWithOffset(buffer, 0, imageLength);
72
- imageAsBase64 = buffer.toString('base64');
73
- mimeType = faceImageInfo.getMimeType();
411
+ const rawMimeType = faceImageInfo.getMimeType();
412
+ const converted = convertJP2IfNeeded(buffer, rawMimeType);
413
+ imageAsBase64 = converted.base64;
414
+ mimeType = converted.mimeType;
74
415
  }
75
416
  progress = 100;
76
417
  if (progressCallback) {
@@ -6,6 +6,8 @@ import { DefaultFileSystem } from "./defaultFileSystem.js";
6
6
  import { BACAPDUSender } from "./protocol/bacAPDUSender.js";
7
7
  import { ReadBinaryAPDUSender } from "./protocol/readBinaryAPDUSender.js";
8
8
  import { BACProtocol } from "./protocol/bacProtocol.js";
9
+ import { PACEAPDUSender } from "./protocol/paceAPDUSender.js";
10
+ import { PACEProtocol } from "./protocol/paceProtocol.js";
9
11
  import { EID_CONSTANTS } from "./constants/eidConstants.js";
10
12
  export class EIDService extends AbstractMRTDCardService {
11
13
  /** Shared secret type for non-PACE key. */
@@ -175,7 +177,13 @@ export class EIDService extends AbstractMRTDCardService {
175
177
  this.shouldCheckMAC = shouldCheckMAC;
176
178
  this.isAppletSelected = false;
177
179
  this.isOpen = false;
178
- this.rootFileSystem = new DefaultFileSystem(this.readBinarySender, false);
180
+ // EF.CardAccess and EF.CardSecurity live in the MF (Master File), outside
181
+ // the ICAO applet. They must be read via SFI-based READ BINARY (no SELECT
182
+ // needed). Without SFI, the implementation falls back to SELECT-by-FID
183
+ // which many passport chips reject at MF level before applet selection,
184
+ // causing PACE to be falsely reported as "not available".
185
+ const rootFidToSFI = new Map([[EID_CONSTANTS.EF_CARD_ACCESS, EID_CONSTANTS.SFI_CARD_ACCESS], [EID_CONSTANTS.EF_CARD_SECURITY, EID_CONSTANTS.SFI_CARD_SECURITY]]);
186
+ this.rootFileSystem = new DefaultFileSystem(this.readBinarySender, true, rootFidToSFI);
179
187
  this.appletFileSystem = new DefaultFileSystem(this.readBinarySender, isSFIEnabled);
180
188
  }
181
189
  async open() {
@@ -209,6 +217,22 @@ export class EIDService extends AbstractMRTDCardService {
209
217
  this.appletFileSystem.setWrapper(this.wrapper);
210
218
  return bacResult;
211
219
  }
220
+
221
+ /**
222
+ * Performs the PACE protocol.
223
+ *
224
+ * @param accessKey the access key (MRZ or CAN based)
225
+ * @param oid the PACE OID string from EF.CardAccess
226
+ * @param parameterId the standard domain parameter ID (e.g. 13 for brainpoolP256r1)
227
+ */
228
+ async doPACE(accessKey, oid, parameterId, progressCallback) {
229
+ const paceSender = new PACEAPDUSender(this.service);
230
+ const paceProtocol = new PACEProtocol(paceSender, this.wrapper, EIDService.NORMAL_MAX_TRANSCEIVE_LENGTH, this.maxTransceiveLengthForSecureMessaging, this.shouldCheckMAC);
231
+ const paceResult = await paceProtocol.doPACE(accessKey, oid, parameterId, progressCallback);
232
+ this.wrapper = paceResult.getWrapper();
233
+ this.appletFileSystem.setWrapper(this.wrapper);
234
+ return paceResult;
235
+ }
212
236
  async close() {
213
237
  try {
214
238
  await this.service.close();
@@ -9,17 +9,16 @@ export class NFCManagerCardService extends CardService {
9
9
  async open() {
10
10
  await NFCManager.start();
11
11
  await NFCManager.requestTechnology([NfcTech.IsoDep, NfcTech.NfcA, NfcTech.NfcB]);
12
- // await NFCManager.setTimeout(5000);
12
+ // Increase transceive timeout for slow curves (e.g. brainpoolP512r1 ECDH on passport chip)
13
+ if (Platform.OS === 'android') {
14
+ await NFCManager.setTimeout(10000);
15
+ }
13
16
  this.isOpened = true;
14
17
  }
15
18
  getIsOpen() {
16
19
  return this.isOpened;
17
20
  }
18
21
  async transmit(commandAPDU) {
19
- // console.debug(
20
- // `T[${ISO7816_INS[commandAPDU.getINS()]}]:`,
21
- // Buffer.from(commandAPDU.getBytes()).toString('hex').toUpperCase(),
22
- // );
23
22
  let response;
24
23
  if (Platform.OS === 'ios') {
25
24
  const iosResponse = await NFCManager.sendCommandAPDUIOS(Array.from(commandAPDU.getBytes()));
@@ -27,8 +26,6 @@ export class NFCManagerCardService extends CardService {
27
26
  } else {
28
27
  response = await NFCManager.transceive(Array.from(commandAPDU.getBytes()));
29
28
  }
30
- // console.debug('R:', Buffer.from(response).toString('hex').toUpperCase());
31
-
32
29
  return new ResponseAPDU(response);
33
30
  }
34
31
  getATR() {
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * PACE (Password Authenticated Connection Establishment) protocol info.
5
+ * Parses PACE OIDs to extract mapping type, cipher, digest, key agreement algorithm, and key length.
6
+ *
7
+ * Based on ICAO Doc 9303 Part 11 and BSI TR-03110.
8
+ */
9
+
10
+ export let MappingType = /*#__PURE__*/function (MappingType) {
11
+ MappingType["GM"] = "GM";
12
+ MappingType["IM"] = "IM";
13
+ MappingType["CAM"] = "CAM";
14
+ return MappingType;
15
+ }({});
16
+
17
+ // PACE OID constants (BSI TR-03110 / ICAO 9303)
18
+ export const ID_PACE = '0.4.0.127.0.7.2.2.4';
19
+ export const ID_PACE_DH_GM = '0.4.0.127.0.7.2.2.4.1';
20
+ export const ID_PACE_DH_GM_3DES_CBC_CBC = '0.4.0.127.0.7.2.2.4.1.1';
21
+ export const ID_PACE_DH_GM_AES_CBC_CMAC_128 = '0.4.0.127.0.7.2.2.4.1.2';
22
+ export const ID_PACE_DH_GM_AES_CBC_CMAC_192 = '0.4.0.127.0.7.2.2.4.1.3';
23
+ export const ID_PACE_DH_GM_AES_CBC_CMAC_256 = '0.4.0.127.0.7.2.2.4.1.4';
24
+ export const ID_PACE_ECDH_GM = '0.4.0.127.0.7.2.2.4.2';
25
+ export const ID_PACE_ECDH_GM_3DES_CBC_CBC = '0.4.0.127.0.7.2.2.4.2.1';
26
+ export const ID_PACE_ECDH_GM_AES_CBC_CMAC_128 = '0.4.0.127.0.7.2.2.4.2.2';
27
+ export const ID_PACE_ECDH_GM_AES_CBC_CMAC_192 = '0.4.0.127.0.7.2.2.4.2.3';
28
+ export const ID_PACE_ECDH_GM_AES_CBC_CMAC_256 = '0.4.0.127.0.7.2.2.4.2.4';
29
+ export const ID_PACE_DH_IM = '0.4.0.127.0.7.2.2.4.3';
30
+ export const ID_PACE_DH_IM_3DES_CBC_CBC = '0.4.0.127.0.7.2.2.4.3.1';
31
+ export const ID_PACE_DH_IM_AES_CBC_CMAC_128 = '0.4.0.127.0.7.2.2.4.3.2';
32
+ export const ID_PACE_DH_IM_AES_CBC_CMAC_192 = '0.4.0.127.0.7.2.2.4.3.3';
33
+ export const ID_PACE_DH_IM_AES_CBC_CMAC_256 = '0.4.0.127.0.7.2.2.4.3.4';
34
+ export const ID_PACE_ECDH_IM = '0.4.0.127.0.7.2.2.4.4';
35
+ export const ID_PACE_ECDH_IM_3DES_CBC_CBC = '0.4.0.127.0.7.2.2.4.4.1';
36
+ export const ID_PACE_ECDH_IM_AES_CBC_CMAC_128 = '0.4.0.127.0.7.2.2.4.4.2';
37
+ export const ID_PACE_ECDH_IM_AES_CBC_CMAC_192 = '0.4.0.127.0.7.2.2.4.4.3';
38
+ export const ID_PACE_ECDH_IM_AES_CBC_CMAC_256 = '0.4.0.127.0.7.2.2.4.4.4';
39
+ export const ID_PACE_ECDH_CAM = '0.4.0.127.0.7.2.2.4.6';
40
+ export const ID_PACE_ECDH_CAM_AES_CBC_CMAC_128 = '0.4.0.127.0.7.2.2.4.6.2';
41
+ export const ID_PACE_ECDH_CAM_AES_CBC_CMAC_192 = '0.4.0.127.0.7.2.2.4.6.3';
42
+ export const ID_PACE_ECDH_CAM_AES_CBC_CMAC_256 = '0.4.0.127.0.7.2.2.4.6.4';
43
+
44
+ // Standard domain parameter identifiers
45
+ export const PARAM_ID_ECP_NIST_P256_R1 = 12;
46
+ export const PARAM_ID_ECP_BRAINPOOL_P256_R1 = 13;
47
+ export const PARAM_ID_ECP_BRAINPOOL_P384_R1 = 16;
48
+ export const PARAM_ID_ECP_BRAINPOOL_P512_R1 = 17;
49
+ export const PARAM_ID_ECP_NIST_P384_R1 = 15;
50
+ export const PARAM_ID_ECP_NIST_P521_R1 = 18;
51
+ const GM_OIDS = new Set([ID_PACE_DH_GM_3DES_CBC_CBC, ID_PACE_DH_GM_AES_CBC_CMAC_128, ID_PACE_DH_GM_AES_CBC_CMAC_192, ID_PACE_DH_GM_AES_CBC_CMAC_256, ID_PACE_ECDH_GM_3DES_CBC_CBC, ID_PACE_ECDH_GM_AES_CBC_CMAC_128, ID_PACE_ECDH_GM_AES_CBC_CMAC_192, ID_PACE_ECDH_GM_AES_CBC_CMAC_256]);
52
+ const IM_OIDS = new Set([ID_PACE_DH_IM_3DES_CBC_CBC, ID_PACE_DH_IM_AES_CBC_CMAC_128, ID_PACE_DH_IM_AES_CBC_CMAC_192, ID_PACE_DH_IM_AES_CBC_CMAC_256, ID_PACE_ECDH_IM_3DES_CBC_CBC, ID_PACE_ECDH_IM_AES_CBC_CMAC_128, ID_PACE_ECDH_IM_AES_CBC_CMAC_192, ID_PACE_ECDH_IM_AES_CBC_CMAC_256]);
53
+ const CAM_OIDS = new Set([ID_PACE_ECDH_CAM_AES_CBC_CMAC_128, ID_PACE_ECDH_CAM_AES_CBC_CMAC_192, ID_PACE_ECDH_CAM_AES_CBC_CMAC_256]);
54
+ const DH_OIDS = new Set([ID_PACE_DH_GM_3DES_CBC_CBC, ID_PACE_DH_GM_AES_CBC_CMAC_128, ID_PACE_DH_GM_AES_CBC_CMAC_192, ID_PACE_DH_GM_AES_CBC_CMAC_256, ID_PACE_DH_IM_3DES_CBC_CBC, ID_PACE_DH_IM_AES_CBC_CMAC_128, ID_PACE_DH_IM_AES_CBC_CMAC_192, ID_PACE_DH_IM_AES_CBC_CMAC_256]);
55
+ const DES_OIDS = new Set([ID_PACE_DH_GM_3DES_CBC_CBC, ID_PACE_DH_IM_3DES_CBC_CBC, ID_PACE_ECDH_GM_3DES_CBC_CBC, ID_PACE_ECDH_IM_3DES_CBC_CBC]);
56
+ const KEY_128_OIDS = new Set([ID_PACE_DH_GM_3DES_CBC_CBC, ID_PACE_DH_IM_3DES_CBC_CBC, ID_PACE_ECDH_GM_3DES_CBC_CBC, ID_PACE_ECDH_IM_3DES_CBC_CBC, ID_PACE_DH_GM_AES_CBC_CMAC_128, ID_PACE_DH_IM_AES_CBC_CMAC_128, ID_PACE_ECDH_GM_AES_CBC_CMAC_128, ID_PACE_ECDH_IM_AES_CBC_CMAC_128, ID_PACE_ECDH_CAM_AES_CBC_CMAC_128]);
57
+ const KEY_192_OIDS = new Set([ID_PACE_DH_GM_AES_CBC_CMAC_192, ID_PACE_DH_IM_AES_CBC_CMAC_192, ID_PACE_ECDH_GM_AES_CBC_CMAC_192, ID_PACE_ECDH_IM_AES_CBC_CMAC_192, ID_PACE_ECDH_CAM_AES_CBC_CMAC_192]);
58
+ const KEY_256_OIDS = new Set([ID_PACE_DH_GM_AES_CBC_CMAC_256, ID_PACE_DH_IM_AES_CBC_CMAC_256, ID_PACE_ECDH_GM_AES_CBC_CMAC_256, ID_PACE_ECDH_IM_AES_CBC_CMAC_256, ID_PACE_ECDH_CAM_AES_CBC_CMAC_256]);
59
+ const SHA256_OIDS = new Set([...KEY_192_OIDS, ...KEY_256_OIDS]);
60
+ export class PACEInfo {
61
+ static toMappingType(oid) {
62
+ if (GM_OIDS.has(oid)) return MappingType.GM;
63
+ if (IM_OIDS.has(oid)) return MappingType.IM;
64
+ if (CAM_OIDS.has(oid)) return MappingType.CAM;
65
+ throw new Error(`Unknown PACE OID: ${oid}`);
66
+ }
67
+ static toKeyAgreementAlgorithm(oid) {
68
+ if (DH_OIDS.has(oid)) return 'DH';
69
+ return 'ECDH';
70
+ }
71
+ static toCipherAlgorithm(oid) {
72
+ if (DES_OIDS.has(oid)) return 'DESede';
73
+ return 'AES';
74
+ }
75
+ static toDigestAlgorithm(oid) {
76
+ if (SHA256_OIDS.has(oid)) return 'SHA-256';
77
+ return 'SHA-1';
78
+ }
79
+ static toKeyLength(oid) {
80
+ if (KEY_128_OIDS.has(oid)) return 128;
81
+ if (KEY_192_OIDS.has(oid)) return 192;
82
+ if (KEY_256_OIDS.has(oid)) return 256;
83
+ throw new Error(`Unknown PACE OID: ${oid}`);
84
+ }
85
+ }