@ukeyfe/react-native-nfc-litecard 1.0.2 → 1.0.3
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/README.md +71 -34
- package/README.zh.md +275 -238
- package/dist/constants.d.ts +26 -0
- package/dist/constants.js +33 -1
- package/dist/crypto.d.ts +22 -0
- package/dist/crypto.js +165 -15
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -3
- package/dist/nfc-core.d.ts +9 -0
- package/dist/nfc-core.js +97 -9
- package/dist/reader.d.ts +13 -2
- package/dist/reader.js +153 -66
- package/dist/types.d.ts +16 -4
- package/dist/types.js +26 -24
- package/dist/utils.d.ts +16 -0
- package/dist/utils.js +36 -28
- package/dist/writer.d.ts +9 -4
- package/dist/writer.js +95 -82
- package/package.json +1 -1
package/dist/writer.d.ts
CHANGED
|
@@ -10,13 +10,18 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Based on MIFARE Ultralight AES (MF0AES(H)20) datasheet.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { NfcStatusCode, type NfcResult } from './types';
|
|
14
14
|
import { isNfcOperationLocked, releaseNfcOperationLock } from './nfc-core';
|
|
15
|
-
export {
|
|
15
|
+
export { NfcStatusCode, type NfcResult, isNfcOperationLocked, releaseNfcOperationLock };
|
|
16
16
|
/**
|
|
17
|
-
* Initialize a
|
|
17
|
+
* Initialize a card: authenticate with the default password, then write
|
|
18
|
+
* mnemonic and set a new password.
|
|
19
|
+
*
|
|
20
|
+
* @param mnemonic BIP-39 mnemonic to write.
|
|
21
|
+
* @param newPassword Password to protect the card with after initialization.
|
|
22
|
+
* @param defaultPassword Current (factory-default) password on the card.
|
|
18
23
|
*/
|
|
19
|
-
export declare function initializeCard(mnemonic: string,
|
|
24
|
+
export declare function initializeCard(mnemonic: string, newPassword: string, defaultPassword: string, onCardIdentified?: () => void): Promise<NfcResult>;
|
|
20
25
|
/**
|
|
21
26
|
* Update card: authenticate with old password, then write new mnemonic + new password.
|
|
22
27
|
*
|
package/dist/writer.js
CHANGED
|
@@ -48,7 +48,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
48
48
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
49
49
|
};
|
|
50
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
-
exports.releaseNfcOperationLock = exports.isNfcOperationLocked = exports.
|
|
51
|
+
exports.releaseNfcOperationLock = exports.isNfcOperationLocked = exports.NfcStatusCode = void 0;
|
|
52
52
|
exports.initializeCard = initializeCard;
|
|
53
53
|
exports.updateCard = updateCard;
|
|
54
54
|
exports.updatePassword = updatePassword;
|
|
@@ -59,7 +59,7 @@ const react_native_1 = require("react-native");
|
|
|
59
59
|
const bip39 = __importStar(require("bip39"));
|
|
60
60
|
const constants_1 = require("./constants");
|
|
61
61
|
const types_1 = require("./types");
|
|
62
|
-
Object.defineProperty(exports, "
|
|
62
|
+
Object.defineProperty(exports, "NfcStatusCode", { enumerable: true, get: function () { return types_1.NfcStatusCode; } });
|
|
63
63
|
const utils_1 = require("./utils");
|
|
64
64
|
const crypto_1 = require("./crypto");
|
|
65
65
|
const nfc_core_1 = require("./nfc-core");
|
|
@@ -91,9 +91,9 @@ async function writeUserMemory(data) {
|
|
|
91
91
|
const pageData = Array.from(buffer.slice(offset, offset + constants_1.PAGE_SIZE));
|
|
92
92
|
await writePage(page, pageData);
|
|
93
93
|
if (react_native_1.Platform.OS === 'ios' && i < totalPages - 1) {
|
|
94
|
-
await new Promise(r => setTimeout(r,
|
|
94
|
+
await new Promise(r => setTimeout(r, constants_1.DELAY.IOS_PAGE_WRITE));
|
|
95
95
|
// Keep-alive every 4 pages to prevent iOS session timeout
|
|
96
|
-
if ((i + 1) %
|
|
96
|
+
if ((i + 1) % constants_1.DELAY.KEEPALIVE_FREQ === 0) {
|
|
97
97
|
try {
|
|
98
98
|
await react_native_nfc_manager_1.default.sendMifareCommandIOS([0x30, 0x00]);
|
|
99
99
|
}
|
|
@@ -102,13 +102,6 @@ async function writeUserMemory(data) {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
-
/** FAST_READ pages 0x08–0x27 (user memory). */
|
|
106
|
-
async function readUserMemory() {
|
|
107
|
-
const response = await (0, nfc_core_1.transceive)([constants_1.CMD_FAST_READ, constants_1.USER_PAGE_START, constants_1.USER_PAGE_END]);
|
|
108
|
-
if (!response || response.length < constants_1.USER_MEMORY_SIZE)
|
|
109
|
-
throw new Error('READ_FAILED');
|
|
110
|
-
return new Uint8Array(response.slice(0, constants_1.USER_MEMORY_SIZE));
|
|
111
|
-
}
|
|
112
105
|
/**
|
|
113
106
|
* Write a 16-byte AES key to AES_KEY0 (pages 0x30–0x33).
|
|
114
107
|
* Byte order is reversed per the datasheet.
|
|
@@ -120,7 +113,7 @@ async function writeAesKey(key) {
|
|
|
120
113
|
const pageData = [key[off + 3], key[off + 2], key[off + 1], key[off + 0]];
|
|
121
114
|
await writePage(page, pageData);
|
|
122
115
|
if (react_native_1.Platform.OS === 'ios' && i < 3)
|
|
123
|
-
await new Promise(r => setTimeout(r,
|
|
116
|
+
await new Promise(r => setTimeout(r, constants_1.DELAY.IOS_KEY_WRITE));
|
|
124
117
|
}
|
|
125
118
|
}
|
|
126
119
|
/** Write a UTF-8 nickname into the last 3 pages of user memory. */
|
|
@@ -139,19 +132,20 @@ async function writeNicknameToCard(nickname) {
|
|
|
139
132
|
const offset = i * constants_1.PAGE_SIZE;
|
|
140
133
|
await writePage(page, Array.from(buffer.slice(offset, offset + constants_1.PAGE_SIZE)));
|
|
141
134
|
if (react_native_1.Platform.OS === 'ios' && i < totalPages - 1)
|
|
142
|
-
await new Promise(r => setTimeout(r,
|
|
135
|
+
await new Promise(r => setTimeout(r, constants_1.DELAY.IOS_NICKNAME_WRITE));
|
|
143
136
|
}
|
|
144
137
|
}
|
|
145
138
|
// ===========================================================================
|
|
146
139
|
// Auth configuration
|
|
147
140
|
// ===========================================================================
|
|
148
|
-
/** Enable read+write protection starting from USER_PAGE_START. */
|
|
141
|
+
/** Enable read+write protection and secure messaging starting from USER_PAGE_START. */
|
|
149
142
|
async function configureAuth() {
|
|
150
143
|
const cfg0 = await readPage(constants_1.PAGE_CFG0);
|
|
144
|
+
cfg0[0] = cfg0[0] | constants_1.SEC_MSG_ACT_MASK; // Enable CMAC secure messaging
|
|
151
145
|
cfg0[3] = constants_1.USER_PAGE_START;
|
|
152
146
|
await writePage(constants_1.PAGE_CFG0, cfg0.slice(0, 4));
|
|
153
147
|
if (react_native_1.Platform.OS === 'ios')
|
|
154
|
-
await new Promise(r => setTimeout(r,
|
|
148
|
+
await new Promise(r => setTimeout(r, constants_1.DELAY.IOS_CONFIG));
|
|
155
149
|
const cfg1 = await readPage(constants_1.PAGE_CFG1);
|
|
156
150
|
cfg1[0] = cfg1[0] | 0x80; // PROT bit = 1
|
|
157
151
|
await writePage(constants_1.PAGE_CFG1, cfg1.slice(0, 4));
|
|
@@ -168,7 +162,7 @@ async function disableAuth() {
|
|
|
168
162
|
cfg0[3] = 0x3c;
|
|
169
163
|
await writePage(constants_1.PAGE_CFG0, cfg0.slice(0, 4));
|
|
170
164
|
if (react_native_1.Platform.OS === 'ios')
|
|
171
|
-
await new Promise(r => setTimeout(r,
|
|
165
|
+
await new Promise(r => setTimeout(r, constants_1.DELAY.IOS_CONFIG));
|
|
172
166
|
const cfg1 = await readPage(constants_1.PAGE_CFG1);
|
|
173
167
|
cfg1[0] = cfg1[0] & 0x7f; // Clear PROT bit
|
|
174
168
|
await writePage(constants_1.PAGE_CFG1, cfg1.slice(0, 4));
|
|
@@ -185,31 +179,7 @@ function mnemonicToEntropyWithCRC(mnemonic) {
|
|
|
185
179
|
throw new Error('INVALID_MNEMONIC');
|
|
186
180
|
const entropyHex = bip39.mnemonicToEntropy(mnemonic);
|
|
187
181
|
const entropyBytes = (0, utils_1.hexToBytes)(entropyHex);
|
|
188
|
-
|
|
189
|
-
let typeStr;
|
|
190
|
-
switch (entropyBytes.length) {
|
|
191
|
-
case 16:
|
|
192
|
-
typeId = constants_1.MNEMONIC_TYPE_12;
|
|
193
|
-
typeStr = '12 words (128-bit)';
|
|
194
|
-
break;
|
|
195
|
-
case 20:
|
|
196
|
-
typeId = constants_1.MNEMONIC_TYPE_15;
|
|
197
|
-
typeStr = '15 words (160-bit)';
|
|
198
|
-
break;
|
|
199
|
-
case 24:
|
|
200
|
-
typeId = constants_1.MNEMONIC_TYPE_18;
|
|
201
|
-
typeStr = '18 words (192-bit)';
|
|
202
|
-
break;
|
|
203
|
-
case 28:
|
|
204
|
-
typeId = constants_1.MNEMONIC_TYPE_21;
|
|
205
|
-
typeStr = '21 words (224-bit)';
|
|
206
|
-
break;
|
|
207
|
-
case 32:
|
|
208
|
-
typeId = constants_1.MNEMONIC_TYPE_24;
|
|
209
|
-
typeStr = '24 words (256-bit)';
|
|
210
|
-
break;
|
|
211
|
-
default: throw new Error('UNSUPPORTED_MNEMONIC_LENGTH');
|
|
212
|
-
}
|
|
182
|
+
const { typeId, description: typeStr } = (0, utils_1.getMnemonicTypeByEntropyLength)(entropyBytes.length);
|
|
213
183
|
const dataBlock = new Uint8Array(1 + entropyBytes.length);
|
|
214
184
|
dataBlock[0] = typeId;
|
|
215
185
|
dataBlock.set(entropyBytes, 1);
|
|
@@ -223,46 +193,72 @@ function mnemonicToEntropyWithCRC(mnemonic) {
|
|
|
223
193
|
// Public API
|
|
224
194
|
// ===========================================================================
|
|
225
195
|
/**
|
|
226
|
-
* Initialize a
|
|
196
|
+
* Initialize a card: authenticate with the default password, then write
|
|
197
|
+
* mnemonic and set a new password.
|
|
198
|
+
*
|
|
199
|
+
* @param mnemonic BIP-39 mnemonic to write.
|
|
200
|
+
* @param newPassword Password to protect the card with after initialization.
|
|
201
|
+
* @param defaultPassword Current (factory-default) password on the card.
|
|
227
202
|
*/
|
|
228
|
-
async function initializeCard(mnemonic,
|
|
203
|
+
async function initializeCard(mnemonic, newPassword, defaultPassword, onCardIdentified) {
|
|
229
204
|
try {
|
|
230
205
|
await (0, nfc_core_1.acquireNfcLock)();
|
|
231
206
|
}
|
|
232
207
|
catch {
|
|
233
|
-
return { code: types_1.
|
|
208
|
+
return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
|
|
234
209
|
}
|
|
210
|
+
let retryCountAfterPreDecrement;
|
|
235
211
|
try {
|
|
236
212
|
try {
|
|
237
213
|
await (0, nfc_core_1.requestNfcTech)();
|
|
238
214
|
}
|
|
239
215
|
catch {
|
|
240
216
|
(0, nfc_core_1.releaseNfcLock)();
|
|
241
|
-
return { code: types_1.
|
|
217
|
+
return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
|
|
242
218
|
}
|
|
243
219
|
try {
|
|
244
220
|
const entropyResult = mnemonicToEntropyWithCRC(mnemonic);
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
221
|
+
// Decrement retry counter before auth
|
|
222
|
+
try {
|
|
223
|
+
const n = await (0, nfc_core_1.decrementRetryCountInSession)();
|
|
224
|
+
if (typeof n === 'number')
|
|
225
|
+
retryCountAfterPreDecrement = n;
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
const code = (0, types_1.errorToCode)(error);
|
|
229
|
+
if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
|
|
230
|
+
await (0, nfc_core_1.releaseNfcTech)();
|
|
231
|
+
(0, nfc_core_1.releaseNfcLock)();
|
|
232
|
+
return (0, types_1.nfcResultRetryCountExhausted)();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Authenticate with factory-default password
|
|
236
|
+
const oldKey = (0, crypto_1.passwordToAesKey)(defaultPassword);
|
|
237
|
+
await (0, nfc_core_1.authenticate)(oldKey);
|
|
238
|
+
// Auth succeeded – reset retry counter
|
|
251
239
|
try {
|
|
252
240
|
await (0, nfc_core_1.writeRetryCountInSession)(constants_1.DEFAULT_PIN_RETRY_COUNT);
|
|
241
|
+
retryCountAfterPreDecrement = constants_1.DEFAULT_PIN_RETRY_COUNT;
|
|
253
242
|
}
|
|
254
243
|
catch { /* non-fatal */ }
|
|
244
|
+
onCardIdentified?.();
|
|
245
|
+
// Write mnemonic (while still authenticated)
|
|
246
|
+
await writeUserMemory(entropyResult.data);
|
|
247
|
+
// Switch to new password
|
|
248
|
+
const newKey = (0, crypto_1.passwordToAesKey)(newPassword);
|
|
249
|
+
await disableAuth();
|
|
250
|
+
await writeAesKey(newKey);
|
|
251
|
+
await configureAuth();
|
|
255
252
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
256
253
|
(0, nfc_core_1.releaseNfcLock)();
|
|
257
254
|
return {
|
|
258
|
-
code: types_1.
|
|
255
|
+
code: types_1.NfcStatusCode.INIT_SUCCESS,
|
|
259
256
|
success: true,
|
|
260
257
|
data: {
|
|
261
258
|
type: entropyResult.type,
|
|
262
259
|
entropyHex: entropyResult.entropyHex,
|
|
263
260
|
rawBytes: entropyResult.rawBytes,
|
|
264
261
|
crc16: entropyResult.crc16,
|
|
265
|
-
aesKeyHex,
|
|
266
262
|
retryCount: constants_1.DEFAULT_PIN_RETRY_COUNT,
|
|
267
263
|
},
|
|
268
264
|
};
|
|
@@ -271,7 +267,11 @@ async function initializeCard(mnemonic, password, onCardIdentified) {
|
|
|
271
267
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
272
268
|
(0, nfc_core_1.releaseNfcLock)();
|
|
273
269
|
const code = (0, types_1.errorToCode)(error);
|
|
274
|
-
return {
|
|
270
|
+
return {
|
|
271
|
+
code,
|
|
272
|
+
success: false,
|
|
273
|
+
data: typeof retryCountAfterPreDecrement === 'number' ? { retryCount: retryCountAfterPreDecrement } : undefined,
|
|
274
|
+
};
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
catch (error) {
|
|
@@ -292,7 +292,7 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
|
|
|
292
292
|
await (0, nfc_core_1.acquireNfcLock)();
|
|
293
293
|
}
|
|
294
294
|
catch {
|
|
295
|
-
return { code: types_1.
|
|
295
|
+
return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
|
|
296
296
|
}
|
|
297
297
|
let retryCountAfterPreDecrement;
|
|
298
298
|
try {
|
|
@@ -301,7 +301,7 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
|
|
|
301
301
|
}
|
|
302
302
|
catch {
|
|
303
303
|
(0, nfc_core_1.releaseNfcLock)();
|
|
304
|
-
return { code: types_1.
|
|
304
|
+
return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
|
|
305
305
|
}
|
|
306
306
|
try {
|
|
307
307
|
try {
|
|
@@ -311,7 +311,7 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
|
|
|
311
311
|
}
|
|
312
312
|
catch (error) {
|
|
313
313
|
const code = (0, types_1.errorToCode)(error);
|
|
314
|
-
if (code === types_1.
|
|
314
|
+
if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
|
|
315
315
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
316
316
|
(0, nfc_core_1.releaseNfcLock)();
|
|
317
317
|
return (0, types_1.nfcResultRetryCountExhausted)();
|
|
@@ -328,21 +328,21 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
|
|
|
328
328
|
onCardIdentified?.();
|
|
329
329
|
if (options?.precheckExistingMnemonic) {
|
|
330
330
|
try {
|
|
331
|
-
const data = await readUserMemory();
|
|
331
|
+
const data = await (0, nfc_core_1.readUserMemory)();
|
|
332
332
|
const decoded = (0, utils_1.validateMnemonicPayload)(data);
|
|
333
333
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
334
334
|
(0, nfc_core_1.releaseNfcLock)();
|
|
335
335
|
return {
|
|
336
|
-
code: types_1.
|
|
336
|
+
code: types_1.NfcStatusCode.PRECHECK_HAS_BACKUP,
|
|
337
337
|
success: true,
|
|
338
338
|
data: { type: decoded.type, retryCount: constants_1.DEFAULT_PIN_RETRY_COUNT },
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
341
|
catch (e) {
|
|
342
342
|
const c = (0, types_1.errorToCode)(e);
|
|
343
|
-
if (c === types_1.
|
|
344
|
-
c === types_1.
|
|
345
|
-
c === types_1.
|
|
343
|
+
if (c === types_1.NfcStatusCode.CHECK_EMPTY ||
|
|
344
|
+
c === types_1.NfcStatusCode.CRC16_CHECK_FAILED ||
|
|
345
|
+
c === types_1.NfcStatusCode.INVALID_CARD_DATA) {
|
|
346
346
|
// No valid mnemonic on card — fall through to write
|
|
347
347
|
}
|
|
348
348
|
else {
|
|
@@ -362,7 +362,7 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
|
|
|
362
362
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
363
363
|
(0, nfc_core_1.releaseNfcLock)();
|
|
364
364
|
return {
|
|
365
|
-
code: types_1.
|
|
365
|
+
code: types_1.NfcStatusCode.WRITE_SUCCESS,
|
|
366
366
|
success: true,
|
|
367
367
|
data: {
|
|
368
368
|
type: entropyResult.type,
|
|
@@ -397,7 +397,7 @@ async function updatePassword(oldPassword, newPassword, onCardIdentified) {
|
|
|
397
397
|
await (0, nfc_core_1.acquireNfcLock)();
|
|
398
398
|
}
|
|
399
399
|
catch {
|
|
400
|
-
return { code: types_1.
|
|
400
|
+
return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
|
|
401
401
|
}
|
|
402
402
|
let retryCountAfterPreDecrement;
|
|
403
403
|
try {
|
|
@@ -406,7 +406,7 @@ async function updatePassword(oldPassword, newPassword, onCardIdentified) {
|
|
|
406
406
|
}
|
|
407
407
|
catch {
|
|
408
408
|
(0, nfc_core_1.releaseNfcLock)();
|
|
409
|
-
return { code: types_1.
|
|
409
|
+
return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
|
|
410
410
|
}
|
|
411
411
|
try {
|
|
412
412
|
try {
|
|
@@ -416,7 +416,7 @@ async function updatePassword(oldPassword, newPassword, onCardIdentified) {
|
|
|
416
416
|
}
|
|
417
417
|
catch (error) {
|
|
418
418
|
const code = (0, types_1.errorToCode)(error);
|
|
419
|
-
if (code === types_1.
|
|
419
|
+
if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
|
|
420
420
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
421
421
|
(0, nfc_core_1.releaseNfcLock)();
|
|
422
422
|
return (0, types_1.nfcResultRetryCountExhausted)();
|
|
@@ -439,7 +439,7 @@ async function updatePassword(oldPassword, newPassword, onCardIdentified) {
|
|
|
439
439
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
440
440
|
(0, nfc_core_1.releaseNfcLock)();
|
|
441
441
|
return {
|
|
442
|
-
code: types_1.
|
|
442
|
+
code: types_1.NfcStatusCode.UPDATE_PASSWORD_SUCCESS,
|
|
443
443
|
success: true,
|
|
444
444
|
data: { aesKeyHex, retryCount: constants_1.DEFAULT_PIN_RETRY_COUNT },
|
|
445
445
|
};
|
|
@@ -466,7 +466,7 @@ async function writeUserNickname(password, nickname, onCardIdentified) {
|
|
|
466
466
|
await (0, nfc_core_1.acquireNfcLock)();
|
|
467
467
|
}
|
|
468
468
|
catch {
|
|
469
|
-
return { code: types_1.
|
|
469
|
+
return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
|
|
470
470
|
}
|
|
471
471
|
try {
|
|
472
472
|
try {
|
|
@@ -474,11 +474,28 @@ async function writeUserNickname(password, nickname, onCardIdentified) {
|
|
|
474
474
|
}
|
|
475
475
|
catch {
|
|
476
476
|
(0, nfc_core_1.releaseNfcLock)();
|
|
477
|
-
return { code: types_1.
|
|
477
|
+
return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
|
|
478
478
|
}
|
|
479
479
|
try {
|
|
480
|
+
// Pre-decrement retry counter before auth
|
|
481
|
+
try {
|
|
482
|
+
await (0, nfc_core_1.decrementRetryCountInSession)();
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
const code = (0, types_1.errorToCode)(error);
|
|
486
|
+
if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
|
|
487
|
+
await (0, nfc_core_1.releaseNfcTech)();
|
|
488
|
+
(0, nfc_core_1.releaseNfcLock)();
|
|
489
|
+
return (0, types_1.nfcResultRetryCountExhausted)();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
480
492
|
const aesKey = (0, crypto_1.passwordToAesKey)(password);
|
|
481
493
|
await (0, nfc_core_1.authenticate)(aesKey);
|
|
494
|
+
// Auth succeeded – reset retry counter
|
|
495
|
+
try {
|
|
496
|
+
await (0, nfc_core_1.writeRetryCountInSession)(constants_1.DEFAULT_PIN_RETRY_COUNT);
|
|
497
|
+
}
|
|
498
|
+
catch { /* non-fatal */ }
|
|
482
499
|
onCardIdentified?.();
|
|
483
500
|
await disableAuth();
|
|
484
501
|
await writeNicknameToCard(nickname);
|
|
@@ -486,7 +503,7 @@ async function writeUserNickname(password, nickname, onCardIdentified) {
|
|
|
486
503
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
487
504
|
(0, nfc_core_1.releaseNfcLock)();
|
|
488
505
|
return {
|
|
489
|
-
code: types_1.
|
|
506
|
+
code: types_1.NfcStatusCode.WRITE_NICKNAME_SUCCESS,
|
|
490
507
|
success: true,
|
|
491
508
|
};
|
|
492
509
|
}
|
|
@@ -513,7 +530,7 @@ async function resetCard(password, newPassword, onCardIdentified) {
|
|
|
513
530
|
await (0, nfc_core_1.acquireNfcLock)();
|
|
514
531
|
}
|
|
515
532
|
catch {
|
|
516
|
-
return { code: types_1.
|
|
533
|
+
return { code: types_1.NfcStatusCode.UNKNOWN_ERROR, success: false };
|
|
517
534
|
}
|
|
518
535
|
let retryCountAfterPreDecrement;
|
|
519
536
|
try {
|
|
@@ -522,7 +539,7 @@ async function resetCard(password, newPassword, onCardIdentified) {
|
|
|
522
539
|
}
|
|
523
540
|
catch {
|
|
524
541
|
(0, nfc_core_1.releaseNfcLock)();
|
|
525
|
-
return { code: types_1.
|
|
542
|
+
return { code: types_1.NfcStatusCode.NFC_CONNECT_FAILED, success: false };
|
|
526
543
|
}
|
|
527
544
|
try {
|
|
528
545
|
if (password) {
|
|
@@ -533,7 +550,7 @@ async function resetCard(password, newPassword, onCardIdentified) {
|
|
|
533
550
|
}
|
|
534
551
|
catch (error) {
|
|
535
552
|
const code = (0, types_1.errorToCode)(error);
|
|
536
|
-
if (code === types_1.
|
|
553
|
+
if (code === types_1.NfcStatusCode.RETRY_COUNT_EXHAUSTED) {
|
|
537
554
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
538
555
|
(0, nfc_core_1.releaseNfcLock)();
|
|
539
556
|
return (0, types_1.nfcResultRetryCountExhausted)();
|
|
@@ -565,11 +582,10 @@ async function resetCard(password, newPassword, onCardIdentified) {
|
|
|
565
582
|
}
|
|
566
583
|
catch { /* non-fatal */ }
|
|
567
584
|
}
|
|
568
|
-
await disableAuth();
|
|
569
585
|
}
|
|
570
586
|
else {
|
|
571
587
|
try {
|
|
572
|
-
await
|
|
588
|
+
await (0, nfc_core_1.authenticate)((0, crypto_1.passwordToAesKey)(newPassword));
|
|
573
589
|
}
|
|
574
590
|
catch {
|
|
575
591
|
throw new Error('AUTH_WRONG_PASSWORD');
|
|
@@ -578,18 +594,15 @@ async function resetCard(password, newPassword, onCardIdentified) {
|
|
|
578
594
|
}
|
|
579
595
|
// Wipe mnemonic data (nickname is preserved)
|
|
580
596
|
await writeUserMemory(new Uint8Array(constants_1.MNEMONIC_MEMORY_SIZE));
|
|
581
|
-
// Set new password
|
|
597
|
+
// Set new password and keep protection enabled
|
|
582
598
|
const resetKey = (0, crypto_1.passwordToAesKey)(newPassword);
|
|
599
|
+
await disableAuth();
|
|
583
600
|
await writeAesKey(resetKey);
|
|
584
|
-
|
|
585
|
-
try {
|
|
586
|
-
await disableAuth();
|
|
587
|
-
}
|
|
588
|
-
catch { /* may already be off */ }
|
|
601
|
+
await configureAuth();
|
|
589
602
|
await (0, nfc_core_1.releaseNfcTech)();
|
|
590
603
|
(0, nfc_core_1.releaseNfcLock)();
|
|
591
604
|
return {
|
|
592
|
-
code: types_1.
|
|
605
|
+
code: types_1.NfcStatusCode.RESET_SUCCESS,
|
|
593
606
|
success: true,
|
|
594
607
|
data: { retryCount: constants_1.DEFAULT_PIN_RETRY_COUNT },
|
|
595
608
|
};
|