@ukeyfe/react-native-nfc-litecard 1.0.4 → 1.0.6

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 (2) hide show
  1. package/dist/nfc-core.js +12 -12
  2. package/package.json +1 -1
package/dist/nfc-core.js CHANGED
@@ -143,12 +143,13 @@ function computeCommandCmac(sessionKey, cmdCtr, command) {
143
143
  return truncateCmac(mac);
144
144
  }
145
145
  /**
146
- * Truncate a 16-byte CMAC to 8 bytes using the MIFARE convention:
147
- * select even-indexed bytes: MAC[0], MAC[2], MAC[4], ..., MAC[14].
146
+ * Truncate a 16-byte CMAC to 8 bytes using the NXP MIFARE convention:
147
+ * select odd-indexed bytes (0-based): MAC[1], MAC[3], MAC[5], ..., MAC[15].
148
+ * NXP docs refer to these as "even-numbered bytes" using 1-based numbering.
148
149
  * (First introduced in MIFARE Plus, see NXP AN13452.)
149
150
  */
150
151
  function truncateCmac(mac) {
151
- return new Uint8Array([mac[0], mac[2], mac[4], mac[6], mac[8], mac[10], mac[12], mac[14]]);
152
+ return new Uint8Array([mac[1], mac[3], mac[5], mac[7], mac[9], mac[11], mac[13], mac[15]]);
152
153
  }
153
154
  /**
154
155
  * Compute the 8-byte truncated CMAC for an NFC response.
@@ -188,27 +189,26 @@ async function transceive(command, _timeoutMs = 2000, retryCount = 0) {
188
189
  const result = react_native_1.Platform.OS === 'ios'
189
190
  ? await react_native_nfc_manager_1.default.sendMifareCommandIOS(cmdToSend)
190
191
  : await react_native_nfc_manager_1.default.nfcAHandler.transceive(cmdToSend);
192
+ if (cmacSessionKey) {
193
+ // CmdCtr increments between command and response (datasheet §8.8.3)
194
+ cmacCmdCtr++;
195
+ }
191
196
  if (cmacSessionKey && result && result.length >= 8) {
192
197
  // Response has CMAC appended: split data and MAC
193
198
  const dataLen = result.length - 8;
194
199
  const responseData = result.slice(0, dataLen);
195
200
  const responseMac = result.slice(dataLen);
196
- // Verify response CMAC (constant-time comparison)
201
+ // Verify response CMAC with incremented CmdCtr
197
202
  const expectedMac = computeResponseCmac(cmacSessionKey, cmacCmdCtr, responseData);
198
- let macValid = true;
203
+ let diff = 0;
199
204
  for (let i = 0; i < 8; i++) {
200
- macValid = macValid && (responseMac[i] === expectedMac[i]);
205
+ diff |= responseMac[i] ^ expectedMac[i];
201
206
  }
202
- if (!macValid) {
207
+ if (diff !== 0) {
203
208
  throw new Error('CMAC_VERIFY_FAILED');
204
209
  }
205
- cmacCmdCtr++;
206
210
  return responseData;
207
211
  }
208
- if (cmacSessionKey) {
209
- // ACK-only response (e.g. WRITE command) — MAC replaces ACK
210
- cmacCmdCtr++;
211
- }
212
212
  return result;
213
213
  }
214
214
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukeyfe/react-native-nfc-litecard",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "NFC read/write for MIFARE Ultralight AES (LiteCard mnemonic storage)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",