@ukeyfe/react-native-nfc-litecard 1.0.1 → 1.0.2

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 CHANGED
@@ -1,41 +1,41 @@
1
1
  # @ukeyfe/react-native-nfc-litecard
2
2
 
3
- [English](./README.en.md) | 中文
3
+ English | [中文](./README.zh.md)
4
4
 
5
- 基于 **MIFARE Ultralight AES** (MF0AES(H)20) React Native NFC 读写库,用于 LiteCard 助记词存储。
5
+ React Native NFC read/write library for **MIFARE Ultralight AES** (MF0AES(H)20), designed for LiteCard mnemonic storage.
6
6
 
7
- > **设计原则**:库只返回状态码 (`code`) 和数据 (`data`),**不提供用户提示文案**。调用方根据 `ResultCode` 自行处理本地化提示。
7
+ > **Design principle**: The library only returns status codes (`code`) and data (`data`). It does **not** provide user-facing messages. The caller should map `ResultCode` to their own localised strings.
8
8
 
9
- ## 功能概览
9
+ ## Features
10
10
 
11
- | 功能 | 方法 | 说明 |
12
- |------|------|------|
13
- | 检测卡片 | `checkCard()` | 判断卡片是空卡还是已有数据 |
14
- | 读取助记词 | `readMnemonic()` | 密码认证后读取 BIP-39 助记词 |
15
- | 读取昵称 | `readUserNickname()` | 读取卡片上的用户昵称 |
16
- | 读取重试次数 | `readMnemonicRetryCount()` | 读取 PIN 重试计数器 |
17
- | 重置重试次数 | `resetRetryCountTo10()` | 重置 PIN 重试计数器为默认值 10 |
18
- | 初始化卡片 | `initializeCard()` | 向空卡写入助记词并设置密码保护 |
19
- | 更新卡片 | `updateCard()` | 更新助记词和密码(需要旧密码) |
20
- | 修改密码 | `updatePassword()` | 仅修改密码(需要旧密码) |
21
- | 写入昵称 | `writeUserNickname()` | 写入用户昵称到卡片 |
22
- | 重置卡片 | `resetCard()` | 清空数据,密码重置为 "000000" |
11
+ | Feature | Method | Description |
12
+ |---------|--------|-------------|
13
+ | Check card | `checkCard()` | Detect whether the card is empty or contains data |
14
+ | Read mnemonic | `readMnemonic()` | Read BIP-39 mnemonic (password required) |
15
+ | Read nickname | `readUserNickname()` | Read user nickname from card |
16
+ | Read retry count | `readMnemonicRetryCount()` | Read PIN retry counter |
17
+ | Reset retry count | `resetRetryCountTo10()` | Reset PIN retry counter to default (10) |
18
+ | Initialize card | `initializeCard()` | Write mnemonic + set password on a blank card |
19
+ | Update card | `updateCard()` | Update mnemonic & password (old password required) |
20
+ | Change password | `updatePassword()` | Change password only (old password required) |
21
+ | Write nickname | `writeUserNickname()` | Write user nickname to card |
22
+ | Reset card | `resetCard()` | Wipe mnemonic data, set a new password |
23
23
 
24
- ## 安装
24
+ ## Installation
25
25
 
26
26
  ```bash
27
27
  npm install @ukeyfe/react-native-nfc-litecard
28
28
  ```
29
29
 
30
- ### 前置依赖
30
+ ### Peer Dependencies
31
31
 
32
- 本库需要以下 peer dependencies,请确保项目中已安装:
32
+ This library requires the following peer dependencies:
33
33
 
34
34
  ```bash
35
35
  npm install react-native react-native-nfc-manager
36
36
  ```
37
37
 
38
- ## 快速上手
38
+ ## Quick Start
39
39
 
40
40
  ```typescript
41
41
  import {
@@ -53,85 +53,85 @@ import {
53
53
  } from '@ukeyfe/react-native-nfc-litecard';
54
54
  ```
55
55
 
56
- ## API 文档
56
+ ## API Reference
57
57
 
58
58
  ### `checkCard(password?, onCardIdentified?)`
59
59
 
60
- 检测卡片状态(空卡 / 有数据)。
60
+ Detect card status (empty / has data).
61
61
 
62
- **不传密码(快速探测):**
62
+ **Without password (quick probe):**
63
63
  ```typescript
64
64
  const result = await checkCard();
65
65
  if (result.code === ResultCode.CHECK_EMPTY) {
66
- // 空卡,可以初始化
66
+ // Empty card – ready to initialize
67
67
  } else if (result.code === ResultCode.CHECK_HAS_DATA) {
68
- // 有数据(或卡开了读保护无法确定)
68
+ // Has data (or read-protected, cannot determine)
69
69
  }
70
70
  ```
71
71
 
72
- **传密码(认证后深度检查,适用于开了读保护的卡):**
72
+ **With password (authenticated deep check, for read-protected cards):**
73
73
  ```typescript
74
74
  const result = await checkCard('password');
75
75
  if (result.code === ResultCode.CHECK_EMPTY) {
76
- // 空卡,可以写入
76
+ // Empty card – ready to write
77
77
  } else if (result.code === ResultCode.CHECK_HAS_DATA) {
78
- // 有合法助记词备份,类型: result.data?.type
78
+ // Valid mnemonic backup exists, type: result.data?.type
79
79
  } else if (result.code === ResultCode.AUTH_WRONG_PASSWORD) {
80
- // 密码错误
80
+ // Wrong password
81
81
  }
82
82
  ```
83
83
 
84
- **参数:**
85
- | 参数 | 类型 | 必填 | 说明 |
86
- |------|------|------|------|
87
- | `password` | `string` | | 卡片保护密码。不传时直接尝试读取(适合未加密的卡);传入后先用密码进行 AES 认证再读取完整数据并校验 CRC16(适合开了读保护的卡,结果更准确) |
88
- | `onCardIdentified` | `() => void` | | NFC 连接建立后的回调,可用于 UI 提示"已识别到卡片" |
84
+ **Parameters:**
85
+ | Parameter | Type | Required | Description |
86
+ |-----------|------|----------|-------------|
87
+ | `password` | `string` | No | Card protection password. If omitted, the library reads directly (suited for unencrypted cards). If provided, AES authentication runs first, then full data is read and CRC16 is verified (suited for read-protected cards; more accurate). |
88
+ | `onCardIdentified` | `() => void` | No | Called after the NFC session is established; use for UI such as "card detected". |
89
89
 
90
- **返回值 (`NfcResult`):**
91
- | code | 含义 |
92
- |------|------|
93
- | `ResultCode.CHECK_EMPTY` (10104) | 空卡,没有助记词数据 |
94
- | `ResultCode.CHECK_HAS_DATA` (10105) | 卡上有数据。传密码时 `data.type` 包含助记词类型(如 "12 words (128-bit)" |
95
- | `ResultCode.AUTH_WRONG_PASSWORD` (40002) | 密码错误(仅传密码时可能返回) |
96
- | `ResultCode.NFC_CONNECT_FAILED` (40001) | NFC 连接失败,卡片未贴近或设备不支持 |
90
+ **Result codes:**
91
+ | Code | Meaning |
92
+ |------|---------|
93
+ | `ResultCode.CHECK_EMPTY` (10104) | Empty card – no mnemonic data |
94
+ | `ResultCode.CHECK_HAS_DATA` (10105) | Card has data. When a password is supplied, `data.type` contains the mnemonic type (e.g. `"12 words (128-bit)"`). |
95
+ | `ResultCode.AUTH_WRONG_PASSWORD` (40002) | Wrong password (only possible when a password is provided) |
96
+ | `ResultCode.NFC_CONNECT_FAILED` (40001) | NFC connection failed – card not tapped or device unsupported |
97
97
 
98
98
  ---
99
99
 
100
100
  ### `readMnemonic(password, onCardIdentified?)`
101
101
 
102
- 读取助记词(需要密码认证)。认证前会自动递减重试计数器,认证成功后重置为 10
102
+ Read the mnemonic (password authentication required). The retry counter is decremented before authentication and reset to 10 after a successful authentication.
103
103
 
104
104
  ```typescript
105
105
  const result = await readMnemonic('your-password');
106
106
  if (result.success) {
107
- console.log('助记词:', result.data?.mnemonic);
108
- console.log('类型:', result.data?.type); // "12 words (128-bit)"
109
- console.log('昵称:', result.data?.nickname);
110
- console.log('剩余重试:', result.data?.retryCount);
107
+ console.log('Mnemonic:', result.data?.mnemonic);
108
+ console.log('Type:', result.data?.type); // "12 words (128-bit)"
109
+ console.log('Nickname:', result.data?.nickname);
110
+ console.log('Retry count:', result.data?.retryCount);
111
111
  }
112
112
  ```
113
113
 
114
- **参数:**
115
- | 参数 | 类型 | 必填 | 说明 |
116
- |------|------|------|------|
117
- | `password` | `string` | | 卡片保护密码,用于 AES-128 认证 |
118
- | `onCardIdentified` | `() => void` | | 认证成功后、开始读取数据前的回调,可用于 UI 提示"正在读取" |
119
-
120
- **返回 `data` 字段:**
121
- | 字段 | 类型 | 说明 |
122
- |------|------|------|
123
- | `mnemonic` | `string` | BIP-39 助记词(如 "abandon abandon ... about" |
124
- | `type` | `string` | 助记词类型(如 "12 words (128-bit)""24 words (256-bit)" |
125
- | `entropyHex` | `string` | 熵数据的十六进制字符串 |
126
- | `rawBytes` | `string` | 卡上原始数据(类型+熵)的十六进制字符串 |
127
- | `nickname` | `string` | 用户昵称(如果卡上有设置) |
128
- | `retryCount` | `number` | 认证成功后重置的重试次数(正常为 10 |
114
+ **Parameters:**
115
+ | Parameter | Type | Required | Description |
116
+ |-----------|------|----------|-------------|
117
+ | `password` | `string` | Yes | Card protection password for AES-128 authentication |
118
+ | `onCardIdentified` | `() => void` | No | Called after successful authentication and before reading data; use for UI such as "reading". |
119
+
120
+ **Returned `data` fields:**
121
+ | Field | Type | Description |
122
+ |-------|------|-------------|
123
+ | `mnemonic` | `string` | BIP-39 mnemonic (e.g. `"abandon abandon ... about"`) |
124
+ | `type` | `string` | Mnemonic type (e.g. `"12 words (128-bit)"`, `"24 words (256-bit)"`) |
125
+ | `entropyHex` | `string` | Entropy as a hexadecimal string |
126
+ | `rawBytes` | `string` | Hex string of raw on-card data (type + entropy) |
127
+ | `nickname` | `string` | User nickname if set on the card |
128
+ | `retryCount` | `number` | Retry count after successful authentication (normally 10) |
129
129
 
130
130
  ---
131
131
 
132
132
  ### `initializeCard(mnemonic, password, onCardIdentified?)`
133
133
 
134
- 初始化空卡:将助记词转为 BIP-39 熵写入卡片,设置 AES 密码保护,开启读写认证。
134
+ Initialize a blank card: convert the mnemonic to BIP-39 entropy, write it to the card, enable AES password protection, and require read/write authentication.
135
135
 
136
136
  ```typescript
137
137
  const result = await initializeCard(
@@ -139,170 +139,172 @@ const result = await initializeCard(
139
139
  'your-password'
140
140
  );
141
141
  if (result.code === ResultCode.INIT_SUCCESS) {
142
- console.log('初始化成功');
142
+ console.log('Initialization successful');
143
143
  }
144
144
  ```
145
145
 
146
- **参数:**
147
- | 参数 | 类型 | 必填 | 说明 |
148
- |------|------|------|------|
149
- | `mnemonic` | `string` | | BIP-39 助记词,支持 12/15/18/21/24 词。库会自动转为熵 + CRC16 写入卡片 |
150
- | `password` | `string` | | 要设置的保护密码,用于生成 AES-128 密钥并写入卡片 |
151
- | `onCardIdentified` | `() => void` | | NFC 连接建立后、开始写入前的回调,可用于 UI 提示"正在写入" |
146
+ **Parameters:**
147
+ | Parameter | Type | Required | Description |
148
+ |-----------|------|----------|-------------|
149
+ | `mnemonic` | `string` | Yes | BIP-39 mnemonic; supports 12/15/18/21/24 words. The library converts to entropy + CRC16 and writes to the card. |
150
+ | `password` | `string` | Yes | Protection password to set; used to derive the AES-128 key written to the card. |
151
+ | `onCardIdentified` | `() => void` | No | Called after NFC connection is established and before writing begins; use for UI such as "writing". |
152
152
 
153
153
  ---
154
154
 
155
155
  ### `updateCard(oldPassword, newPassword, newMnemonic, onCardIdentified?, options?)`
156
156
 
157
- 更新卡片:用旧密码认证后,写入新助记词和新密码。认证前自动递减重试计数器。
157
+ Update the card: authenticate with the old password, then write the new mnemonic and new password. The retry counter is decremented automatically before authentication.
158
158
 
159
159
  ```typescript
160
160
  const result = await updateCard('old-password', 'new-password', 'new mnemonic words ...');
161
161
  if (result.code === ResultCode.WRITE_SUCCESS) {
162
- console.log('更新成功');
162
+ console.log('Update successful');
163
163
  }
164
164
  ```
165
165
 
166
- **写入前检查是否已有备份:**
166
+ **Pre-check for existing backup:**
167
167
 
168
168
  ```typescript
169
169
  const result = await updateCard('old-password', 'new-password', 'mnemonic ...', undefined, {
170
170
  precheckExistingMnemonic: true,
171
171
  });
172
172
  if (result.code === ResultCode.PRECHECK_HAS_BACKUP) {
173
- console.log('卡上已有备份,未写入。类型:', result.data?.type);
173
+ // Card already has a valid mnemonic backup; write was skipped
174
+ console.log('Backup exists, type:', result.data?.type);
174
175
  } else if (result.code === ResultCode.WRITE_SUCCESS) {
175
- console.log('写入成功');
176
+ console.log('Write successful');
176
177
  }
177
178
  ```
178
179
 
179
- **参数:**
180
- | 参数 | 类型 | 必填 | 说明 |
181
- |------|------|------|------|
182
- | `oldPassword` | `string` | | 当前卡片密码,用于 AES 认证 |
183
- | `newPassword` | `string` | | 新密码,写入后卡片将使用此密码保护 |
184
- | `newMnemonic` | `string` | | 新的 BIP-39 助记词(12/15/18/21/24 词) |
185
- | `onCardIdentified` | `() => void` | | 认证成功后的回调,可用于 UI 提示"正在写入" |
186
- | `options.precheckExistingMnemonic` | `boolean` | | 设为 `true` 时,认证后先读取卡片数据并校验 CRC16。如果已有合法助记词,返回 `PRECHECK_HAS_BACKUP` 不执行写入 |
180
+ **Parameters:**
181
+ | Parameter | Type | Required | Description |
182
+ |-----------|------|----------|-------------|
183
+ | `oldPassword` | `string` | Yes | Current card password for AES authentication |
184
+ | `newPassword` | `string` | Yes | New password; the card will be protected with this password after the write |
185
+ | `newMnemonic` | `string` | Yes | New BIP-39 mnemonic (12/15/18/21/24 words) |
186
+ | `onCardIdentified` | `() => void` | No | Called after successful authentication; use for UI such as "writing". |
187
+ | `options.precheckExistingMnemonic` | `boolean` | No | When `true`, after authentication the library reads card data and verifies CRC16. If a valid mnemonic already exists, returns `PRECHECK_HAS_BACKUP` and does not write. |
187
188
 
188
189
  ---
189
190
 
190
191
  ### `updatePassword(oldPassword, newPassword, onCardIdentified?)`
191
192
 
192
- 仅修改密码,不更改卡上的助记词数据。认证前自动递减重试计数器。
193
+ Change the password only; mnemonic data on the card is unchanged. The retry counter is decremented automatically before authentication.
193
194
 
194
195
  ```typescript
195
196
  const result = await updatePassword('old-password', 'new-password');
196
197
  if (result.code === ResultCode.UPDATE_PASSWORD_SUCCESS) {
197
- console.log('密码修改成功');
198
+ console.log('Password updated');
198
199
  }
199
200
  ```
200
201
 
201
- **参数:**
202
- | 参数 | 类型 | 必填 | 说明 |
203
- |------|------|------|------|
204
- | `oldPassword` | `string` | | 当前卡片密码,用于 AES 认证 |
205
- | `newPassword` | `string` | | 新密码,修改后卡片将使用此密码保护 |
206
- | `onCardIdentified` | `() => void` | | 认证成功后的回调 |
202
+ **Parameters:**
203
+ | Parameter | Type | Required | Description |
204
+ |-----------|------|----------|-------------|
205
+ | `oldPassword` | `string` | Yes | Current card password for AES authentication |
206
+ | `newPassword` | `string` | Yes | New password; the card will use this password after the change |
207
+ | `onCardIdentified` | `() => void` | No | Called after successful authentication |
207
208
 
208
209
  ---
209
210
 
210
211
  ### `writeUserNickname(password, nickname, onCardIdentified?)`
211
212
 
212
- 写入用户昵称到卡片。昵称使用 UTF-8 编码,最长 12 字节(超出自动截断)。
213
+ Write a user nickname to the card. The nickname is UTF-8 encoded, max 12 bytes (longer input is truncated).
213
214
 
214
215
  ```typescript
215
216
  const result = await writeUserNickname('your-password', 'MyCard');
216
217
  if (result.code === ResultCode.WRITE_NICKNAME_SUCCESS) {
217
- console.log('昵称写入成功');
218
+ console.log('Nickname written');
218
219
  }
219
220
  ```
220
221
 
221
- **参数:**
222
- | 参数 | 类型 | 必填 | 说明 |
223
- |------|------|------|------|
224
- | `password` | `string` | | 卡片保护密码,用于 AES 认证 |
225
- | `nickname` | `string` | | 用户昵称,UTF-8 编码最长 12 字节。中文约 4 个字,英文 12 个字符 |
226
- | `onCardIdentified` | `() => void` | | 认证成功后的回调 |
222
+ **Parameters:**
223
+ | Parameter | Type | Required | Description |
224
+ |-----------|------|----------|-------------|
225
+ | `password` | `string` | Yes | Card protection password for AES authentication |
226
+ | `nickname` | `string` | Yes | User nickname; UTF-8 max 12 bytes (roughly 4 CJK characters or 12 Latin letters) |
227
+ | `onCardIdentified` | `() => void` | No | Called after successful authentication |
227
228
 
228
229
  ---
229
230
 
230
231
  ### `readUserNickname(password?, onCardIdentified?)`
231
232
 
232
- 读取卡片上的用户昵称。
233
+ Read the user nickname from the card.
233
234
 
234
235
  ```typescript
235
236
  const result = await readUserNickname('your-password');
236
237
  if (result.success) {
237
- console.log('昵称:', result.data?.nickname);
238
+ console.log('Nickname:', result.data?.nickname);
238
239
  }
239
240
  ```
240
241
 
241
- **参数:**
242
- | 参数 | 类型 | 必填 | 说明 |
243
- |------|------|------|------|
244
- | `password` | `string` | | 卡片密码。如果卡开了读保护(PROT=1)则必须传入,否则可省略 |
245
- | `onCardIdentified` | `() => void` | | 认证成功后的回调 |
242
+ **Parameters:**
243
+ | Parameter | Type | Required | Description |
244
+ |-----------|------|----------|-------------|
245
+ | `password` | `string` | No | Card password. Required if read protection is enabled (`PROT=1`); otherwise optional. |
246
+ | `onCardIdentified` | `() => void` | No | Called after successful authentication |
246
247
 
247
248
  ---
248
249
 
249
- ### `resetCard(password?, onCardIdentified?)`
250
+ ### `resetCard(password, newPassword, onCardIdentified?)`
250
251
 
251
- 重置卡片:清空所有用户数据(助记词、昵称),密码重置为 `"000000"`,关闭读写保护。
252
+ Reset the card: wipe mnemonic data, set a new password, and disable read/write protection. Nickname is preserved.
252
253
 
253
254
  ```typescript
254
- const result = await resetCard('your-password');
255
+ const result = await resetCard('old-password', 'new-password');
255
256
  if (result.code === ResultCode.RESET_SUCCESS) {
256
- console.log('重置成功');
257
+ console.log('Reset successful');
257
258
  }
258
259
  ```
259
260
 
260
- > ⚠️ 重置操作不可逆,卡上的助记词数据将被永久清除。
261
+ > ⚠️ This operation is irreversible; mnemonic data on the card is permanently erased.
261
262
 
262
- **参数:**
263
- | 参数 | 类型 | 必填 | 说明 |
264
- |------|------|------|------|
265
- | `password` | `string` | | 当前卡片密码。如果卡开了保护则必须传入,否则可省略。认证前自动递减重试计数器 |
266
- | `onCardIdentified` | `() => void` | | 认证成功后的回调 |
263
+ **Parameters:**
264
+ | Parameter | Type | Required | Description |
265
+ |-----------|------|----------|-------------|
266
+ | `password` | `string \| undefined` | No | Current card password. Required if the card is protected; pass `undefined` otherwise. The retry counter is decremented automatically before authentication. |
267
+ | `newPassword` | `string` | Yes | Password to set after reset. |
268
+ | `onCardIdentified` | `() => void` | No | Called after successful authentication |
267
269
 
268
270
  ---
269
271
 
270
272
  ### `readMnemonicRetryCount(onCardIdentified?)`
271
273
 
272
- 读取卡片上的 PIN 重试计数器值。不需要密码认证(计数器页不在保护区域内)。
274
+ Read the PIN retry counter on the card. No password authentication is required (the counter page is outside the protected area).
273
275
 
274
276
  ```typescript
275
277
  const result = await readMnemonicRetryCount();
276
278
  if (result.success) {
277
- console.log('剩余重试次数:', result.data?.retryCount);
279
+ console.log('Remaining retries:', result.data?.retryCount);
278
280
  }
279
281
  ```
280
282
 
281
- **参数:**
282
- | 参数 | 类型 | 必填 | 说明 |
283
- |------|------|------|------|
284
- | `onCardIdentified` | `() => void` | | NFC 连接建立后的回调 |
283
+ **Parameters:**
284
+ | Parameter | Type | Required | Description |
285
+ |-----------|------|----------|-------------|
286
+ | `onCardIdentified` | `() => void` | No | Called after the NFC session is established |
285
287
 
286
288
  ---
287
289
 
288
290
  ### `resetRetryCountTo10(onCardIdentified?)`
289
291
 
290
- PIN 重试计数器重置为默认值 10。不需要密码认证。
292
+ Reset the PIN retry counter to its default value (10). No password authentication is required.
291
293
 
292
294
  ```typescript
293
295
  const result = await resetRetryCountTo10();
294
296
  ```
295
297
 
296
- **参数:**
297
- | 参数 | 类型 | 必填 | 说明 |
298
- |------|------|------|------|
299
- | `onCardIdentified` | `() => void` | | NFC 连接建立后的回调 |
298
+ **Parameters:**
299
+ | Parameter | Type | Required | Description |
300
+ |-----------|------|----------|-------------|
301
+ | `onCardIdentified` | `() => void` | No | Called after the NFC session is established |
300
302
 
301
303
  ---
302
304
 
303
- ### NFC 锁管理
305
+ ### NFC Lock Management
304
306
 
305
- 用于 App 页面生命周期中的 NFC 会话管理:
307
+ For app-level NFC session lifecycle management:
306
308
 
307
309
  ```typescript
308
310
  import {
@@ -313,22 +315,22 @@ import {
313
315
  } from '@ukeyfe/react-native-nfc-litecard';
314
316
  ```
315
317
 
316
- | 方法 | 说明 |
317
- |------|------|
318
- | `isNfcOperationLocked()` | 检查 NFC 操作锁是否被持有 |
319
- | `releaseNfcOperationLock()` | 强制释放锁(页面关闭时使用) |
320
- | `markNfcOperationCancelledByCleanup()` | 标记当前操作被页面清理中断 |
321
- | `consumeNfcOperationCancelledByCleanup()` | 消费清理标记(返回是否被中断) |
318
+ | Method | Description |
319
+ |--------|-------------|
320
+ | `isNfcOperationLocked()` | Check if the NFC operation lock is held |
321
+ | `releaseNfcOperationLock()` | Force-release the lock (use on page unmount) |
322
+ | `markNfcOperationCancelledByCleanup()` | Mark current operation as interrupted by cleanup |
323
+ | `consumeNfcOperationCancelledByCleanup()` | Consume the cleanup flag (returns whether it was set) |
322
324
 
323
- ## NfcResult 返回结构
325
+ ## NfcResult Structure
324
326
 
325
- 所有 API 统一返回 `NfcResult`:
327
+ All APIs return a unified `NfcResult`:
326
328
 
327
329
  ```typescript
328
330
  interface NfcResult {
329
- code: number; // 状态码,与 ResultCode 常量比较
330
- success: boolean; // 操作是否成功
331
- data?: { // 可选数据,仅部分操作返回
331
+ code: number; // Status code – compare against ResultCode
332
+ success: boolean; // Whether the operation succeeded
333
+ data?: { // Optional data, only present for some operations
332
334
  mnemonic?: string;
333
335
  type?: string;
334
336
  entropyHex?: string;
@@ -341,7 +343,7 @@ interface NfcResult {
341
343
  }
342
344
  ```
343
345
 
344
- ## 错误处理示例
346
+ ## Error Handling Example
345
347
 
346
348
  ```typescript
347
349
  import { ResultCode, readMnemonic } from '@ukeyfe/react-native-nfc-litecard';
@@ -350,110 +352,110 @@ const result = await readMnemonic('password');
350
352
 
351
353
  switch (result.code) {
352
354
  case ResultCode.READ_SUCCESS:
353
- console.log('读取成功:', result.data?.mnemonic);
355
+ console.log('Read successful:', result.data?.mnemonic);
354
356
  break;
355
357
  case ResultCode.AUTH_WRONG_PASSWORD:
356
- alert('密码错误');
358
+ alert('Wrong password');
357
359
  break;
358
360
  case ResultCode.NFC_CONNECT_FAILED:
359
- alert('NFC 连接失败,请重新贴卡');
361
+ alert('NFC connection failed, please re-tap the card');
360
362
  break;
361
363
  case ResultCode.NFC_USER_CANCELED:
362
- // iOS 用户取消,静默处理
364
+ // iOS user cancelled – handle silently
363
365
  break;
364
366
  case ResultCode.READ_TIMEOUT:
365
- alert('读取超时,请将卡片移开后重新贴近');
367
+ alert('Read timeout – remove and re-tap the card');
366
368
  break;
367
369
  case ResultCode.RETRY_COUNT_EXHAUSTED:
368
- alert('重试次数已用完,卡片已锁定');
370
+ alert('Retry count exhausted – card is locked');
369
371
  break;
370
372
  default:
371
- alert('操作失败');
373
+ alert('Operation failed');
372
374
  }
373
375
  ```
374
376
 
375
- ## 返回码一览
376
-
377
- ### 成功码
378
-
379
- | 常量 | | 说明 |
380
- |------|------|------|
381
- | `READ_SUCCESS` | 10102 | 读取助记词成功 |
382
- | `READ_NICKNAME_SUCCESS` | 10103 | 读取昵称成功 |
383
- | `CHECK_EMPTY` | 10104 | 空卡 |
384
- | `CHECK_HAS_DATA` | 10105 | 卡片有数据 |
385
- | `READ_RETRY_COUNT_SUCCESS` | 10106 | 读取重试次数成功 |
386
- | `INIT_SUCCESS` | 10201 | 初始化成功 |
387
- | `WRITE_SUCCESS` | 10203 | 写入/更新成功 |
388
- | `UPDATE_PASSWORD_SUCCESS` | 10204 | 修改密码成功 |
389
- | `WRITE_NICKNAME_SUCCESS` | 10205 | 写入昵称成功 |
390
- | `RESET_SUCCESS` | 10206 | 重置卡片成功 |
391
- | `PRECHECK_HAS_BACKUP` | 10207 | 卡上已有合法备份,写入被跳过 |
392
-
393
- ### 错误码
394
-
395
- | 常量 | | 说明 |
396
- |------|------|------|
397
- | `NFC_CONNECT_FAILED` | 40001 | NFC 连接失败 |
398
- | `AUTH_WRONG_PASSWORD` | 40002 | 密码错误 |
399
- | `AUTH_INVALID_RESPONSE` | 40003 | 认证响应无效 |
400
- | `AUTH_VERIFY_FAILED` | 40004 | 认证验证失败 |
401
- | `READ_FAILED` | 40005 | 读取失败 |
402
- | `WRITE_FAILED` | 40006 | 写入失败 |
403
- | `INVALID_MNEMONIC` | 40007 | 无效的助记词 |
404
- | `UNSUPPORTED_MNEMONIC_LENGTH` | 40008 | 不支持的助记词长度 |
405
- | `INVALID_CARD_DATA` | 40009 | 卡片数据无效 |
406
- | `UNKNOWN_ERROR` | 40010 | 未知错误 |
407
- | `NFC_USER_CANCELED` | 40011 | 用户取消 NFC 扫描 (iOS) |
408
- | `READ_TIMEOUT` | 40012 | 读取超时 |
409
- | `NFC_LOCK_TIMEOUT` | 40013 | NFC 锁超时 |
410
- | `CRC16_CHECK_FAILED` | 40014 | CRC16 校验失败 |
411
- | `RETRY_COUNT_EXHAUSTED` | 40015 | PIN 重试次数已用完,卡片锁定 |
412
-
413
- ## 存储格式
414
-
415
- 卡片使用 BIP-39 熵压缩存储助记词:
377
+ ## Result Codes
378
+
379
+ ### Success Codes
380
+
381
+ | Constant | Value | Description |
382
+ |----------|-------|-------------|
383
+ | `READ_SUCCESS` | 10102 | Mnemonic read successful |
384
+ | `READ_NICKNAME_SUCCESS` | 10103 | Nickname read successful |
385
+ | `CHECK_EMPTY` | 10104 | Empty card |
386
+ | `CHECK_HAS_DATA` | 10105 | Card has data |
387
+ | `READ_RETRY_COUNT_SUCCESS` | 10106 | Retry count read successful |
388
+ | `INIT_SUCCESS` | 10201 | Initialization successful |
389
+ | `WRITE_SUCCESS` | 10203 | Write/update successful |
390
+ | `UPDATE_PASSWORD_SUCCESS` | 10204 | Password change successful |
391
+ | `WRITE_NICKNAME_SUCCESS` | 10205 | Nickname written |
392
+ | `RESET_SUCCESS` | 10206 | Card reset successful |
393
+ | `PRECHECK_HAS_BACKUP` | 10207 | Card already has a valid backup; write was skipped |
394
+
395
+ ### Error Codes
396
+
397
+ | Constant | Value | Description |
398
+ |----------|-------|-------------|
399
+ | `NFC_CONNECT_FAILED` | 40001 | NFC connection failed |
400
+ | `AUTH_WRONG_PASSWORD` | 40002 | Wrong password |
401
+ | `AUTH_INVALID_RESPONSE` | 40003 | Invalid authentication response |
402
+ | `AUTH_VERIFY_FAILED` | 40004 | Authentication verification failed |
403
+ | `READ_FAILED` | 40005 | Read failed |
404
+ | `WRITE_FAILED` | 40006 | Write failed |
405
+ | `INVALID_MNEMONIC` | 40007 | Invalid mnemonic |
406
+ | `UNSUPPORTED_MNEMONIC_LENGTH` | 40008 | Unsupported mnemonic length |
407
+ | `INVALID_CARD_DATA` | 40009 | Invalid card data |
408
+ | `UNKNOWN_ERROR` | 40010 | Unknown error |
409
+ | `NFC_USER_CANCELED` | 40011 | User cancelled NFC scan (iOS) |
410
+ | `READ_TIMEOUT` | 40012 | Read timeout |
411
+ | `NFC_LOCK_TIMEOUT` | 40013 | NFC lock timeout |
412
+ | `CRC16_CHECK_FAILED` | 40014 | CRC16 check failed |
413
+ | `RETRY_COUNT_EXHAUSTED` | 40015 | PIN retry count exhausted, card locked |
414
+
415
+ ## Storage Format
416
+
417
+ The card stores BIP-39 mnemonics using entropy compression:
416
418
 
417
419
  ```
418
- [类型 1字节] [熵数据 16-32字节] [CRC16 2字节]
420
+ [type 1B] [entropy 16-32B] [CRC16 2B]
419
421
  ```
420
422
 
421
- | 类型值 | 助记词长度 | 熵长度 |
422
- |--------|-----------|--------|
423
- | 0x01 | 12 | 16 字节 (128-bit) |
424
- | 0x02 | 15 | 20 字节 (160-bit) |
425
- | 0x03 | 18 | 24 字节 (192-bit) |
426
- | 0x04 | 21 | 28 字节 (224-bit) |
427
- | 0x05 | 24 | 32 字节 (256-bit) |
423
+ | Type | Mnemonic Length | Entropy Size |
424
+ |------|----------------|--------------|
425
+ | 0x01 | 12 words | 16 bytes (128-bit) |
426
+ | 0x02 | 15 words | 20 bytes (160-bit) |
427
+ | 0x03 | 18 words | 24 bytes (192-bit) |
428
+ | 0x04 | 21 words | 28 bytes (224-bit) |
429
+ | 0x05 | 24 words | 32 bytes (256-bit) |
428
430
 
429
- ## 安全机制
431
+ ## Security
430
432
 
431
- - **AES-128 硬件级双向认证**(3-pass mutual authentication
432
- - **SHA-256 密钥派生**:用户密码 → SHA-256 → 取前 16 字节作为 AES 密钥
433
- - **CRC16-Modbus 校验**:数据完整性验证
434
- - **PIN 重试计数器**:密码错误自动递减,成功后恢复为 10
435
- - **安全随机数**:认证使用 `crypto.getRandomValues()`(需 Hermes ≥ 0.72 `react-native-get-random-values` polyfill
433
+ - **AES-128 hardware-level mutual authentication** (3-pass)
434
+ - **SHA-256 key derivation**: password → SHA-256 → first 16 bytes as AES key
435
+ - **CRC16-Modbus checksum**: data integrity verification
436
+ - **PIN retry counter**: auto-decrements on wrong password, resets to 10 on success
437
+ - **Secure random**: authentication uses `crypto.getRandomValues()` (requires Hermes ≥ 0.72 or `react-native-get-random-values` polyfill)
436
438
 
437
- ## 项目结构
439
+ ## Project Structure
438
440
 
439
441
  ```
440
442
  src/
441
- ├── index.ts # 公共 API 导出
442
- ├── constants.ts # 共享常量(页地址、NFC 命令、助记词类型)
443
- ├── types.ts # 统一 ResultCodeNfcResult 接口、错误映射
444
- ├── crypto.ts # AES 加解密、密钥派生、安全随机数生成
445
- ├── utils.ts # CRC16hex 转换、数组工具
446
- ├── nfc-core.ts # NFC 锁、transceive、认证、重试计数器
447
- ├── reader.ts # 读卡 API
448
- └── writer.ts # 写卡 API
443
+ ├── index.ts # Public API exports
444
+ ├── constants.ts # Shared constants (page addresses, NFC commands, mnemonic types)
445
+ ├── types.ts # Unified ResultCode, NfcResult interface, error mapping
446
+ ├── crypto.ts # AES encrypt/decrypt, key derivation, secure random
447
+ ├── utils.ts # CRC16, hex conversion, array utilities
448
+ ├── nfc-core.ts # NFC lock, transceive, authentication, retry counter
449
+ ├── reader.ts # Reader API
450
+ └── writer.ts # Writer API
449
451
  ```
450
452
 
451
- ## 平台支持
453
+ ## Platform Support
452
454
 
453
- | 平台 | 技术 | 说明 |
454
- |------|------|------|
455
- | iOS | MifareIOS | 需要 iPhone 7 及以上 |
456
- | Android | NfcA | 需要设备支持 NFC |
455
+ | Platform | Technology | Requirements |
456
+ |----------|-----------|--------------|
457
+ | iOS | MifareIOS | iPhone 7 or later |
458
+ | Android | NfcA | NFC-capable device |
457
459
 
458
460
  ## License
459
461
 
@@ -1,6 +1,6 @@
1
1
  # @ukeyfe/react-native-nfc-litecard
2
2
 
3
- English | [中文](./README.md)
3
+ [English](./README.md) | 中文
4
4
 
5
5
  React Native NFC read/write library for **MIFARE Ultralight AES** (MF0AES(H)20), designed for LiteCard mnemonic storage.
6
6
 
@@ -19,7 +19,7 @@ React Native NFC read/write library for **MIFARE Ultralight AES** (MF0AES(H)20),
19
19
  | Update card | `updateCard()` | Update mnemonic & password (old password required) |
20
20
  | Change password | `updatePassword()` | Change password only (old password required) |
21
21
  | Write nickname | `writeUserNickname()` | Write user nickname to card |
22
- | Reset card | `resetCard()` | Wipe data, reset password to "000000" |
22
+ | Reset card | `resetCard()` | Wipe mnemonic data, set a new password |
23
23
 
24
24
  ## Installation
25
25
 
@@ -247,12 +247,12 @@ if (result.success) {
247
247
 
248
248
  ---
249
249
 
250
- ### `resetCard(password?, onCardIdentified?)`
250
+ ### `resetCard(password, newPassword, onCardIdentified?)`
251
251
 
252
- Reset the card: wipe all user data (mnemonic, nickname), set password to `"000000"`, and disable read/write protection.
252
+ Reset the card: wipe mnemonic data, set a new password, and disable read/write protection. Nickname is preserved.
253
253
 
254
254
  ```typescript
255
- const result = await resetCard('your-password');
255
+ const result = await resetCard('old-password', 'new-password');
256
256
  if (result.code === ResultCode.RESET_SUCCESS) {
257
257
  console.log('Reset successful');
258
258
  }
@@ -263,7 +263,8 @@ if (result.code === ResultCode.RESET_SUCCESS) {
263
263
  **Parameters:**
264
264
  | Parameter | Type | Required | Description |
265
265
  |-----------|------|----------|-------------|
266
- | `password` | `string` | No | Current card password. Required if the card is protected; otherwise optional. The retry counter is decremented automatically before authentication. |
266
+ | `password` | `string \| undefined` | No | Current card password. Required if the card is protected; pass `undefined` otherwise. The retry counter is decremented automatically before authentication. |
267
+ | `newPassword` | `string` | Yes | Password to set after reset. |
267
268
  | `onCardIdentified` | `() => void` | No | Called after successful authentication |
268
269
 
269
270
  ---
@@ -43,6 +43,10 @@ export declare const MNEMONIC_TYPE_18 = 3;
43
43
  export declare const MNEMONIC_TYPE_21 = 4;
44
44
  /** 24-word mnemonic (256-bit entropy, 32 bytes) */
45
45
  export declare const MNEMONIC_TYPE_24 = 5;
46
+ /** Mnemonic data end page (stops before nickname area) */
47
+ export declare const MNEMONIC_PAGE_END: number;
48
+ /** Mnemonic data size: (0x24 - 0x08 + 1) * 4 = 116 bytes */
49
+ export declare const MNEMONIC_MEMORY_SIZE: number;
46
50
  /** Nickname start page */
47
51
  export declare const USER_NICKNAME_PAGE_START: number;
48
52
  /** Nickname end page */
package/dist/constants.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Shared constants for MIFARE Ultralight AES (MF0AES(H)20) NFC operations.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_PIN_RETRY_COUNT = exports.RETRY_COUNTER_OFFSET = exports.RETRY_COUNTER_PAGE = exports.USER_NICKNAME_MAX_LENGTH = exports.USER_NICKNAME_PAGE_END = exports.USER_NICKNAME_PAGE_START = exports.MNEMONIC_TYPE_24 = exports.MNEMONIC_TYPE_21 = exports.MNEMONIC_TYPE_18 = exports.MNEMONIC_TYPE_15 = exports.MNEMONIC_TYPE_12 = exports.USER_CARD_INFO_SIZE = exports.USER_MEMORY_SIZE = exports.PAGE_AES_KEY0_START = exports.PAGE_CFG1 = exports.PAGE_CFG0 = exports.USER_CARD_INFO_PAGE_END = exports.USER_CARD_INFO_PAGE_START = exports.USER_PAGE_END = exports.USER_PAGE_START = exports.PAGE_SIZE = exports.KEY_NO_DATA_PROT = exports.CMD_AUTH_PART2 = exports.CMD_AUTH_PART1 = exports.CMD_FAST_READ = exports.CMD_WRITE = exports.CMD_READ = void 0;
6
+ exports.DEFAULT_PIN_RETRY_COUNT = exports.RETRY_COUNTER_OFFSET = exports.RETRY_COUNTER_PAGE = exports.USER_NICKNAME_MAX_LENGTH = exports.USER_NICKNAME_PAGE_END = exports.USER_NICKNAME_PAGE_START = exports.MNEMONIC_MEMORY_SIZE = exports.MNEMONIC_PAGE_END = exports.MNEMONIC_TYPE_24 = exports.MNEMONIC_TYPE_21 = exports.MNEMONIC_TYPE_18 = exports.MNEMONIC_TYPE_15 = exports.MNEMONIC_TYPE_12 = exports.USER_CARD_INFO_SIZE = exports.USER_MEMORY_SIZE = exports.PAGE_AES_KEY0_START = exports.PAGE_CFG1 = exports.PAGE_CFG0 = exports.USER_CARD_INFO_PAGE_END = exports.USER_CARD_INFO_PAGE_START = exports.USER_PAGE_END = exports.USER_PAGE_START = exports.PAGE_SIZE = exports.KEY_NO_DATA_PROT = exports.CMD_AUTH_PART2 = exports.CMD_AUTH_PART1 = exports.CMD_FAST_READ = exports.CMD_WRITE = exports.CMD_READ = void 0;
7
7
  // ---------------------------------------------------------------------------
8
8
  // NFC command codes
9
9
  // ---------------------------------------------------------------------------
@@ -59,6 +59,13 @@ exports.MNEMONIC_TYPE_21 = 0x04;
59
59
  /** 24-word mnemonic (256-bit entropy, 32 bytes) */
60
60
  exports.MNEMONIC_TYPE_24 = 0x05;
61
61
  // ---------------------------------------------------------------------------
62
+ // Mnemonic data area (excludes nickname pages)
63
+ // ---------------------------------------------------------------------------
64
+ /** Mnemonic data end page (stops before nickname area) */
65
+ exports.MNEMONIC_PAGE_END = exports.USER_PAGE_END - 3; // 0x24
66
+ /** Mnemonic data size: (0x24 - 0x08 + 1) * 4 = 116 bytes */
67
+ exports.MNEMONIC_MEMORY_SIZE = (exports.MNEMONIC_PAGE_END - exports.USER_PAGE_START + 1) * exports.PAGE_SIZE;
68
+ // ---------------------------------------------------------------------------
62
69
  // User nickname area (last 3 pages of user memory)
63
70
  // ---------------------------------------------------------------------------
64
71
  /** Nickname start page */
package/dist/writer.d.ts CHANGED
@@ -33,7 +33,9 @@ export declare function updatePassword(oldPassword: string, newPassword: string,
33
33
  /** Write a user nickname (password required for authentication). */
34
34
  export declare function writeUserNickname(password: string, nickname: string, onCardIdentified?: () => void): Promise<NfcResult>;
35
35
  /**
36
- * Reset card: wipe user data, set password to "000000".
36
+ * Reset card: wipe mnemonic data and set a new password.
37
37
  * @param password – current card password (required if protection is enabled).
38
+ * @param newPassword – password to set after reset.
39
+ * @param onCardIdentified – callback when card is identified.
38
40
  */
39
- export declare function resetCard(password?: string, onCardIdentified?: () => void): Promise<NfcResult>;
41
+ export declare function resetCard(password: string | undefined, newPassword: string, onCardIdentified?: () => void): Promise<NfcResult>;
package/dist/writer.js CHANGED
@@ -77,13 +77,14 @@ async function writePage(page, data) {
77
77
  await (0, nfc_core_1.transceive)([constants_1.CMD_WRITE, page, ...data]);
78
78
  }
79
79
  /**
80
- * Write data to user memory (pages 0x08–0x27).
80
+ * Write data to mnemonic area (pages 0x08–0x24).
81
+ * Does NOT touch the nickname area (pages 0x25–0x27).
81
82
  * iOS: inserts small delays and periodic keep-alive reads.
82
83
  */
83
84
  async function writeUserMemory(data) {
84
- const buffer = new Uint8Array(constants_1.USER_MEMORY_SIZE);
85
- buffer.set(data, 0);
86
- const totalPages = constants_1.USER_PAGE_END - constants_1.USER_PAGE_START + 1;
85
+ const buffer = new Uint8Array(constants_1.MNEMONIC_MEMORY_SIZE);
86
+ buffer.set(data.slice(0, constants_1.MNEMONIC_MEMORY_SIZE), 0);
87
+ const totalPages = constants_1.MNEMONIC_PAGE_END - constants_1.USER_PAGE_START + 1;
87
88
  for (let i = 0; i < totalPages; i++) {
88
89
  const page = constants_1.USER_PAGE_START + i;
89
90
  const offset = i * constants_1.PAGE_SIZE;
@@ -303,7 +304,6 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
303
304
  return { code: types_1.ResultCode.NFC_CONNECT_FAILED, success: false };
304
305
  }
305
306
  try {
306
- const entropyResult = mnemonicToEntropyWithCRC(newMnemonic);
307
307
  try {
308
308
  const n = await (0, nfc_core_1.decrementRetryCountInSession)();
309
309
  if (typeof n === 'number')
@@ -316,11 +316,13 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
316
316
  (0, nfc_core_1.releaseNfcLock)();
317
317
  return (0, types_1.nfcResultRetryCountExhausted)();
318
318
  }
319
+ // Communication failure — counter was not decremented, continue to auth
319
320
  }
320
321
  const oldKey = (0, crypto_1.passwordToAesKey)(oldPassword);
321
322
  await (0, nfc_core_1.authenticate)(oldKey);
322
323
  try {
323
324
  await (0, nfc_core_1.writeRetryCountInSession)(constants_1.DEFAULT_PIN_RETRY_COUNT);
325
+ retryCountAfterPreDecrement = constants_1.DEFAULT_PIN_RETRY_COUNT;
324
326
  }
325
327
  catch { /* non-fatal */ }
326
328
  onCardIdentified?.();
@@ -350,8 +352,9 @@ async function updateCard(oldPassword, newPassword, newMnemonic, onCardIdentifie
350
352
  }
351
353
  }
352
354
  }
353
- await disableAuth();
355
+ const entropyResult = mnemonicToEntropyWithCRC(newMnemonic);
354
356
  await writeUserMemory(entropyResult.data);
357
+ await disableAuth();
355
358
  const newKey = (0, crypto_1.passwordToAesKey)(newPassword);
356
359
  const aesKeyHex = (0, utils_1.bytesToHex)(newKey);
357
360
  await writeAesKey(newKey);
@@ -418,11 +421,13 @@ async function updatePassword(oldPassword, newPassword, onCardIdentified) {
418
421
  (0, nfc_core_1.releaseNfcLock)();
419
422
  return (0, types_1.nfcResultRetryCountExhausted)();
420
423
  }
424
+ // Communication failure — counter was not decremented, continue to auth
421
425
  }
422
426
  const oldKey = (0, crypto_1.passwordToAesKey)(oldPassword);
423
427
  await (0, nfc_core_1.authenticate)(oldKey);
424
428
  try {
425
429
  await (0, nfc_core_1.writeRetryCountInSession)(constants_1.DEFAULT_PIN_RETRY_COUNT);
430
+ retryCountAfterPreDecrement = constants_1.DEFAULT_PIN_RETRY_COUNT;
426
431
  }
427
432
  catch { /* non-fatal */ }
428
433
  onCardIdentified?.();
@@ -498,10 +503,12 @@ async function writeUserNickname(password, nickname, onCardIdentified) {
498
503
  }
499
504
  }
500
505
  /**
501
- * Reset card: wipe user data, set password to "000000".
506
+ * Reset card: wipe mnemonic data and set a new password.
502
507
  * @param password – current card password (required if protection is enabled).
508
+ * @param newPassword – password to set after reset.
509
+ * @param onCardIdentified – callback when card is identified.
503
510
  */
504
- async function resetCard(password, onCardIdentified) {
511
+ async function resetCard(password, newPassword, onCardIdentified) {
505
512
  try {
506
513
  await (0, nfc_core_1.acquireNfcLock)();
507
514
  }
@@ -531,12 +538,14 @@ async function resetCard(password, onCardIdentified) {
531
538
  (0, nfc_core_1.releaseNfcLock)();
532
539
  return (0, types_1.nfcResultRetryCountExhausted)();
533
540
  }
541
+ // Communication failure — counter was not decremented, continue to auth
534
542
  }
535
543
  const aesKey = (0, crypto_1.passwordToAesKey)(password);
536
544
  try {
537
545
  await (0, nfc_core_1.authenticate)(aesKey);
538
546
  try {
539
547
  await (0, nfc_core_1.writeRetryCountInSession)(constants_1.DEFAULT_PIN_RETRY_COUNT);
548
+ retryCountAfterPreDecrement = constants_1.DEFAULT_PIN_RETRY_COUNT;
540
549
  }
541
550
  catch { /* non-fatal */ }
542
551
  }
@@ -567,11 +576,11 @@ async function resetCard(password, onCardIdentified) {
567
576
  }
568
577
  onCardIdentified?.();
569
578
  }
570
- // Wipe user memory
571
- await writeUserMemory(new Uint8Array(constants_1.USER_MEMORY_SIZE));
572
- // Set default password "000000"
573
- const defaultKey = (0, crypto_1.passwordToAesKey)('000000');
574
- await writeAesKey(defaultKey);
579
+ // Wipe mnemonic data (nickname is preserved)
580
+ await writeUserMemory(new Uint8Array(constants_1.MNEMONIC_MEMORY_SIZE));
581
+ // Set new password
582
+ const resetKey = (0, crypto_1.passwordToAesKey)(newPassword);
583
+ await writeAesKey(resetKey);
575
584
  // Ensure protection is disabled
576
585
  try {
577
586
  await disableAuth();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ukeyfe/react-native-nfc-litecard",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
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",
@@ -28,6 +28,6 @@
28
28
  "files": [
29
29
  "dist",
30
30
  "README.md",
31
- "README.en.md"
31
+ "README.zh.md"
32
32
  ]
33
33
  }