@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.zh.md CHANGED
@@ -2,44 +2,46 @@
2
2
 
3
3
  [English](./README.md) | 中文
4
4
 
5
- React Native NFC read/write library for **MIFARE Ultralight AES** (MF0AES(H)20), designed for LiteCard mnemonic storage.
5
+ React Native NFC 读写库,适用于 **MIFARE Ultralight AES**(MF0AES(H)20),专为 LiteCard 助记词存储设计。
6
6
 
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.
7
+ > **设计原则**:库只返回状态码(`code`)和数据(`data`),**不**提供面向用户的提示文案。调用方应根据 `NfcStatusCode` 自行映射本地化字符串。
8
8
 
9
- ## Features
9
+ ## 功能概览
10
10
 
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 |
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()` | 清除助记词数据,设置新密码,保持保护开启 |
23
+ | 卡片版本 | `getCardVersion()` | 读取卡片产品版本信息(无需认证) |
24
+ | 真伪校验 | `readOriginality()` | 读取 ECC 原厂签名,验证 NXP 正品 |
23
25
 
24
- ## Installation
26
+ ## 安装
25
27
 
26
28
  ```bash
27
29
  npm install @ukeyfe/react-native-nfc-litecard
28
30
  ```
29
31
 
30
- ### Peer Dependencies
32
+ ### 对等依赖
31
33
 
32
- This library requires the following peer dependencies:
34
+ 本库需要以下对等依赖:
33
35
 
34
36
  ```bash
35
37
  npm install react-native react-native-nfc-manager
36
38
  ```
37
39
 
38
- ## Quick Start
40
+ ## 快速开始
39
41
 
40
42
  ```typescript
41
43
  import {
42
- ResultCode,
44
+ NfcStatusCode,
43
45
  checkCard,
44
46
  readMnemonic,
45
47
  initializeCard,
@@ -50,261 +52,293 @@ import {
50
52
  resetCard,
51
53
  readMnemonicRetryCount,
52
54
  resetRetryCountTo10,
55
+ getCardVersion,
56
+ readOriginality,
53
57
  } from '@ukeyfe/react-native-nfc-litecard';
54
58
  ```
55
59
 
56
- ## API Reference
60
+ ## API 文档
57
61
 
58
62
  ### `checkCard(password?, onCardIdentified?)`
59
63
 
60
- Detect card status (empty / has data).
64
+ 检测卡片状态(空卡 / 有数据)。
61
65
 
62
- **Without password (quick probe):**
66
+ **无密码(快速探测):**
63
67
  ```typescript
64
68
  const result = await checkCard();
65
- if (result.code === ResultCode.CHECK_EMPTY) {
66
- // Empty card ready to initialize
67
- } else if (result.code === ResultCode.CHECK_HAS_DATA) {
68
- // Has data (or read-protected, cannot determine)
69
+ if (result.code === NfcStatusCode.CHECK_EMPTY) {
70
+ // 空卡可以初始化
71
+ } else if (result.code === NfcStatusCode.CHECK_HAS_DATA) {
72
+ // 有数据(或已读保护,无法确定)
69
73
  }
70
74
  ```
71
75
 
72
- **With password (authenticated deep check, for read-protected cards):**
76
+ **有密码(认证后深度检测,适用于读保护卡):**
73
77
  ```typescript
74
78
  const result = await checkCard('password');
75
- if (result.code === ResultCode.CHECK_EMPTY) {
76
- // Empty card ready to write
77
- } else if (result.code === ResultCode.CHECK_HAS_DATA) {
78
- // Valid mnemonic backup exists, type: result.data?.type
79
- } else if (result.code === ResultCode.AUTH_WRONG_PASSWORD) {
80
- // Wrong password
79
+ if (result.code === NfcStatusCode.CHECK_EMPTY) {
80
+ // 空卡可以写入
81
+ } else if (result.code === NfcStatusCode.CHECK_HAS_DATA) {
82
+ // 已有合法助记词备份,类型:result.data?.type
83
+ } else if (result.code === NfcStatusCode.AUTH_WRONG_PASSWORD) {
84
+ // 密码错误
81
85
  }
82
86
  ```
83
87
 
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”. |
88
+ **参数:**
89
+ | 参数 | 类型 | 必填 | 说明 |
90
+ |------|------|------|------|
91
+ | `password` | `string` | | 卡片保护密码。不传时直接读取(适合未加密卡片);传入时先进行 AES 认证,再读取全量数据并 CRC16 校验(适合读保护卡,结果更准确)。 |
92
+ | `onCardIdentified` | `() => void` | | NFC 会话建立后回调,可用于 UI 提示如"已检测到卡片"。 |
89
93
 
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 |
94
+ **返回状态码:**
95
+ | 状态码 | 含义 |
96
+ |--------|------|
97
+ | `NfcStatusCode.CHECK_EMPTY` (10104) | 空卡无助记词数据 |
98
+ | `NfcStatusCode.CHECK_HAS_DATA` (10105) | 卡片有数据。传入密码时,`data.type` 包含助记词类型(如 `"12 words (128-bit)"`)。 |
99
+ | `NfcStatusCode.AUTH_WRONG_PASSWORD` (40002) | 密码错误(仅在传入密码时可能出现) |
100
+ | `NfcStatusCode.NFC_CONNECT_FAILED` (40001) | NFC 连接失败未贴卡或设备不支持 |
97
101
 
98
102
  ---
99
103
 
100
104
  ### `readMnemonic(password, onCardIdentified?)`
101
105
 
102
- Read the mnemonic (password authentication required). The retry counter is decremented before authentication and reset to 10 after a successful authentication.
106
+ 读取助记词(需密码认证)。认证前自动递减重试计数器,认证成功后重置为 10
103
107
 
104
108
  ```typescript
105
109
  const result = await readMnemonic('your-password');
106
110
  if (result.success) {
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
+ console.log('助记词:', result.data?.mnemonic);
112
+ console.log('类型:', result.data?.type); // "12 words (128-bit)"
113
+ console.log('昵称:', result.data?.nickname);
114
+ console.log('重试次数:', result.data?.retryCount);
111
115
  }
112
116
  ```
113
117
 
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) |
118
+ **参数:**
119
+ | 参数 | 类型 | 必填 | 说明 |
120
+ |------|------|------|------|
121
+ | `password` | `string` | | 卡片保护密码,用于 AES-128 认证 |
122
+ | `onCardIdentified` | `() => void` | | 认证成功、开始读取前回调,可用于 UI 提示如"正在读取"。 |
123
+
124
+ **返回 `data` 字段:**
125
+ | 字段 | 类型 | 说明 |
126
+ |------|------|------|
127
+ | `mnemonic` | `string` | BIP-39 助记词(如 `"abandon abandon ... about"`) |
128
+ | `type` | `string` | 助记词类型(如 `"12 words (128-bit)"`、`"24 words (256-bit)"`) |
129
+ | `entropyHex` | `string` | 熵的十六进制字符串 |
130
+ | `rawBytes` | `string` | 卡上原始数据的十六进制字符串(类型 + 熵) |
131
+ | `nickname` | `string` | 用户昵称(如卡上已设置) |
132
+ | `retryCount` | `number` | 认证成功后的重试次数(正常为 10 |
129
133
 
130
134
  ---
131
135
 
132
- ### `initializeCard(mnemonic, password, onCardIdentified?)`
136
+ ### `initializeCard(mnemonic, newPassword, defaultPassword, onCardIdentified?)`
133
137
 
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.
138
+ 初始化卡片:用出厂默认密码认证,写入助记词,设置新密码。卡片必须已启用 AES 保护(出厂默认)。
135
139
 
136
140
  ```typescript
137
141
  const result = await initializeCard(
138
142
  'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
139
- 'your-password'
143
+ 'your-password',
144
+ '000000' // 出厂默认密码
140
145
  );
141
- if (result.code === ResultCode.INIT_SUCCESS) {
142
- console.log('Initialization successful');
146
+ if (result.code === NfcStatusCode.INIT_SUCCESS) {
147
+ console.log('初始化成功');
143
148
  }
144
149
  ```
145
150
 
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”. |
151
+ **参数:**
152
+ | 参数 | 类型 | 必填 | 说明 |
153
+ |------|------|------|------|
154
+ | `mnemonic` | `string` | | BIP-39 助记词,支持 12/15/18/21/24 个词。库会转为熵 + CRC16 写入卡片。 |
155
+ | `newPassword` | `string` | | 新保护密码,用于派生 AES-128 密钥写入卡片。 |
156
+ | `defaultPassword` | `string` | | 卡片当前(出厂默认)密码,用于认证。 |
157
+ | `onCardIdentified` | `() => void` | 否 | 认证成功、开始写入前回调,可用于 UI 提示如"正在写入"。 |
152
158
 
153
159
  ---
154
160
 
155
161
  ### `updateCard(oldPassword, newPassword, newMnemonic, onCardIdentified?, options?)`
156
162
 
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.
163
+ 更新卡片:使用旧密码认证后,写入新助记词和新密码。认证前自动递减重试计数器。
158
164
 
159
165
  ```typescript
160
166
  const result = await updateCard('old-password', 'new-password', 'new mnemonic words ...');
161
- if (result.code === ResultCode.WRITE_SUCCESS) {
162
- console.log('Update successful');
167
+ if (result.code === NfcStatusCode.WRITE_SUCCESS) {
168
+ console.log('更新成功');
163
169
  }
164
170
  ```
165
171
 
166
- **Pre-check for existing backup:**
172
+ **预检查已有备份:**
167
173
 
168
174
  ```typescript
169
175
  const result = await updateCard('old-password', 'new-password', 'mnemonic ...', undefined, {
170
176
  precheckExistingMnemonic: true,
171
177
  });
172
- if (result.code === ResultCode.PRECHECK_HAS_BACKUP) {
173
- // Card already has a valid mnemonic backup; write was skipped
174
- console.log('Backup exists, type:', result.data?.type);
175
- } else if (result.code === ResultCode.WRITE_SUCCESS) {
176
- console.log('Write successful');
178
+ if (result.code === NfcStatusCode.PRECHECK_HAS_BACKUP) {
179
+ // 卡片已有合法助记词备份,跳过写入
180
+ console.log('已有备份,类型:', result.data?.type);
181
+ } else if (result.code === NfcStatusCode.WRITE_SUCCESS) {
182
+ console.log('写入成功');
177
183
  }
178
184
  ```
179
185
 
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. |
186
+ **参数:**
187
+ | 参数 | 类型 | 必填 | 说明 |
188
+ |------|------|------|------|
189
+ | `oldPassword` | `string` | | 当前卡片密码,用于 AES 认证 |
190
+ | `newPassword` | `string` | | 新密码,写入后卡片使用此密码保护 |
191
+ | `newMnemonic` | `string` | | BIP-39 助记词(12/15/18/21/24 个词) |
192
+ | `onCardIdentified` | `() => void` | | 认证成功后回调,可用于 UI 提示如"正在写入"。 |
193
+ | `options.precheckExistingMnemonic` | `boolean` | | `true` 时,认证后先读取卡片数据并校验 CRC16,若已有合法助记词则返回 `PRECHECK_HAS_BACKUP`,不执行写入。 |
188
194
 
189
195
  ---
190
196
 
191
197
  ### `updatePassword(oldPassword, newPassword, onCardIdentified?)`
192
198
 
193
- Change the password only; mnemonic data on the card is unchanged. The retry counter is decremented automatically before authentication.
199
+ 仅修改密码,卡片上的助记词数据不变。认证前自动递减重试计数器。
194
200
 
195
201
  ```typescript
196
202
  const result = await updatePassword('old-password', 'new-password');
197
- if (result.code === ResultCode.UPDATE_PASSWORD_SUCCESS) {
198
- console.log('Password updated');
203
+ if (result.code === NfcStatusCode.UPDATE_PASSWORD_SUCCESS) {
204
+ console.log('密码修改成功');
199
205
  }
200
206
  ```
201
207
 
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 |
208
+ **参数:**
209
+ | 参数 | 类型 | 必填 | 说明 |
210
+ |------|------|------|------|
211
+ | `oldPassword` | `string` | | 当前卡片密码,用于 AES 认证 |
212
+ | `newPassword` | `string` | | 新密码,修改后卡片使用此密码 |
213
+ | `onCardIdentified` | `() => void` | | 认证成功后回调 |
208
214
 
209
215
  ---
210
216
 
211
217
  ### `writeUserNickname(password, nickname, onCardIdentified?)`
212
218
 
213
- Write a user nickname to the card. The nickname is UTF-8 encoded, max 12 bytes (longer input is truncated).
219
+ 写入用户昵称。昵称以 UTF-8 编码,最大 12 字节(超出部分截断)。
214
220
 
215
221
  ```typescript
216
222
  const result = await writeUserNickname('your-password', 'MyCard');
217
- if (result.code === ResultCode.WRITE_NICKNAME_SUCCESS) {
218
- console.log('Nickname written');
223
+ if (result.code === NfcStatusCode.WRITE_NICKNAME_SUCCESS) {
224
+ console.log('昵称写入成功');
219
225
  }
220
226
  ```
221
227
 
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 |
228
+ **参数:**
229
+ | 参数 | 类型 | 必填 | 说明 |
230
+ |------|------|------|------|
231
+ | `password` | `string` | | 卡片保护密码,用于 AES 认证 |
232
+ | `nickname` | `string` | | 用户昵称;UTF-8 最大 12 字节(约 4 个中文字符或 12 个英文字母) |
233
+ | `onCardIdentified` | `() => void` | | 认证成功后回调 |
228
234
 
229
235
  ---
230
236
 
231
237
  ### `readUserNickname(password?, onCardIdentified?)`
232
238
 
233
- Read the user nickname from the card.
239
+ 读取卡片上的用户昵称。
234
240
 
235
241
  ```typescript
236
242
  const result = await readUserNickname('your-password');
237
243
  if (result.success) {
238
- console.log('Nickname:', result.data?.nickname);
244
+ console.log('昵称:', result.data?.nickname);
239
245
  }
240
246
  ```
241
247
 
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 |
248
+ **参数:**
249
+ | 参数 | 类型 | 必填 | 说明 |
250
+ |------|------|------|------|
251
+ | `password` | `string` | | 卡片密码。读保护启用时(`PROT=1`)必填,否则可选。 |
252
+ | `onCardIdentified` | `() => void` | | 认证成功后回调 |
247
253
 
248
254
  ---
249
255
 
250
256
  ### `resetCard(password, newPassword, onCardIdentified?)`
251
257
 
252
- Reset the card: wipe mnemonic data, set a new password, and disable read/write protection. Nickname is preserved.
258
+ 重置卡片:清除助记词数据,设置新密码,关闭读写保护。昵称保留不变。
253
259
 
254
260
  ```typescript
255
261
  const result = await resetCard('old-password', 'new-password');
256
- if (result.code === ResultCode.RESET_SUCCESS) {
257
- console.log('Reset successful');
262
+ if (result.code === NfcStatusCode.RESET_SUCCESS) {
263
+ console.log('重置成功');
258
264
  }
259
265
  ```
260
266
 
261
- > ⚠️ This operation is irreversible; mnemonic data on the card is permanently erased.
267
+ > ⚠️ 此操作不可逆,卡片上的助记词数据将被永久擦除。
262
268
 
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 |
269
+ **参数:**
270
+ | 参数 | 类型 | 必填 | 说明 |
271
+ |------|------|------|------|
272
+ | `password` | `string \| undefined` | | 当前卡片密码。卡片已保护时必填,否则传 `undefined`。认证前自动递减重试计数器。 |
273
+ | `newPassword` | `string` | | 重置后要设置的密码。 |
274
+ | `onCardIdentified` | `() => void` | | 认证成功后回调 |
269
275
 
270
276
  ---
271
277
 
272
278
  ### `readMnemonicRetryCount(onCardIdentified?)`
273
279
 
274
- Read the PIN retry counter on the card. No password authentication is required (the counter page is outside the protected area).
280
+ 读取卡片上的 PIN 重试计数器。无需密码认证(计数器页面在保护区域之外)。
275
281
 
276
282
  ```typescript
277
283
  const result = await readMnemonicRetryCount();
278
284
  if (result.success) {
279
- console.log('Remaining retries:', result.data?.retryCount);
285
+ console.log('剩余重试次数:', result.data?.retryCount);
280
286
  }
281
287
  ```
282
288
 
283
- **Parameters:**
284
- | Parameter | Type | Required | Description |
285
- |-----------|------|----------|-------------|
286
- | `onCardIdentified` | `() => void` | No | Called after the NFC session is established |
289
+ **参数:**
290
+ | 参数 | 类型 | 必填 | 说明 |
291
+ |------|------|------|------|
292
+ | `onCardIdentified` | `() => void` | | NFC 会话建立后回调 |
287
293
 
288
294
  ---
289
295
 
290
296
  ### `resetRetryCountTo10(onCardIdentified?)`
291
297
 
292
- Reset the PIN retry counter to its default value (10). No password authentication is required.
298
+ PIN 重试计数器重置为默认值(10)。无需密码认证。
293
299
 
294
300
  ```typescript
295
301
  const result = await resetRetryCountTo10();
296
302
  ```
297
303
 
298
- **Parameters:**
299
- | Parameter | Type | Required | Description |
300
- |-----------|------|----------|-------------|
301
- | `onCardIdentified` | `() => void` | No | Called after the NFC session is established |
304
+ **参数:**
305
+ | 参数 | 类型 | 必填 | 说明 |
306
+ |------|------|------|------|
307
+ | `onCardIdentified` | `() => void` | | NFC 会话建立后回调 |
302
308
 
303
309
  ---
304
310
 
305
- ### NFC Lock Management
311
+ ### `getCardVersion(onCardIdentified?)`
306
312
 
307
- For app-level NFC session lifecycle management:
313
+ 读取卡片产品版本信息。无需密码认证。
314
+
315
+ ```typescript
316
+ const result = await getCardVersion();
317
+ if (result.success) {
318
+ console.log('厂商:', result.data?.version?.vendorId); // 0x04 = NXP
319
+ console.log('类型:', result.data?.version?.productType); // 0x03 = Ultralight
320
+ console.log('版本:', result.data?.version?.majorVersion); // 0x04 = AES
321
+ }
322
+ ```
323
+
324
+ ---
325
+
326
+ ### `readOriginality(onCardIdentified?)`
327
+
328
+ 读取 ECC 原厂签名,验证卡片是否为 NXP 正品。无需密码认证。
329
+
330
+ ```typescript
331
+ const result = await readOriginality();
332
+ if (result.success) {
333
+ console.log('签名:', result.data?.signature); // 96 字符 hex 字符串
334
+ }
335
+ ```
336
+
337
+ ---
338
+
339
+ ### NFC 锁管理
340
+
341
+ 用于应用层 NFC 会话生命周期管理:
308
342
 
309
343
  ```typescript
310
344
  import {
@@ -315,22 +349,22 @@ import {
315
349
  } from '@ukeyfe/react-native-nfc-litecard';
316
350
  ```
317
351
 
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) |
352
+ | 方法 | 说明 |
353
+ |------|------|
354
+ | `isNfcOperationLocked()` | 检查 NFC 操作锁是否被持有 |
355
+ | `releaseNfcOperationLock()` | 强制释放锁(用于页面卸载时) |
356
+ | `markNfcOperationCancelledByCleanup()` | 标记当前操作被清理中断 |
357
+ | `consumeNfcOperationCancelledByCleanup()` | 消费清理标志(返回是否被设置过) |
324
358
 
325
- ## NfcResult Structure
359
+ ## NfcResult 结构
326
360
 
327
- All APIs return a unified `NfcResult`:
361
+ 所有 API 返回统一的 `NfcResult`:
328
362
 
329
363
  ```typescript
330
364
  interface NfcResult {
331
- code: number; // Status code compare against ResultCode
332
- success: boolean; // Whether the operation succeeded
333
- data?: { // Optional data, only present for some operations
365
+ code: number; // 状态码 NfcStatusCode 比较
366
+ success: boolean; // 操作是否成功
367
+ data?: { // 可选数据,仅部分操作返回
334
368
  mnemonic?: string;
335
369
  type?: string;
336
370
  entropyHex?: string;
@@ -343,120 +377,123 @@ interface NfcResult {
343
377
  }
344
378
  ```
345
379
 
346
- ## Error Handling Example
380
+ ## 错误处理示例
347
381
 
348
382
  ```typescript
349
- import { ResultCode, readMnemonic } from '@ukeyfe/react-native-nfc-litecard';
383
+ import { NfcStatusCode, readMnemonic } from '@ukeyfe/react-native-nfc-litecard';
350
384
 
351
385
  const result = await readMnemonic('password');
352
386
 
353
387
  switch (result.code) {
354
- case ResultCode.READ_SUCCESS:
355
- console.log('Read successful:', result.data?.mnemonic);
388
+ case NfcStatusCode.READ_SUCCESS:
389
+ console.log('读取成功:', result.data?.mnemonic);
356
390
  break;
357
- case ResultCode.AUTH_WRONG_PASSWORD:
358
- alert('Wrong password');
391
+ case NfcStatusCode.AUTH_WRONG_PASSWORD:
392
+ alert('密码错误');
359
393
  break;
360
- case ResultCode.NFC_CONNECT_FAILED:
361
- alert('NFC connection failed, please re-tap the card');
394
+ case NfcStatusCode.NFC_CONNECT_FAILED:
395
+ alert('NFC 连接失败,请重新贴卡');
362
396
  break;
363
- case ResultCode.NFC_USER_CANCELED:
364
- // iOS user cancelled handle silently
397
+ case NfcStatusCode.NFC_USER_CANCELED:
398
+ // iOS 用户取消静默处理
365
399
  break;
366
- case ResultCode.READ_TIMEOUT:
367
- alert('Read timeout remove and re-tap the card');
400
+ case NfcStatusCode.READ_TIMEOUT:
401
+ alert('读取超时请移开卡片后重新贴卡');
368
402
  break;
369
- case ResultCode.RETRY_COUNT_EXHAUSTED:
370
- alert('Retry count exhausted card is locked');
403
+ case NfcStatusCode.RETRY_COUNT_EXHAUSTED:
404
+ alert('重试次数已耗尽卡片已锁定');
371
405
  break;
372
406
  default:
373
- alert('Operation failed');
407
+ alert('操作失败');
374
408
  }
375
409
  ```
376
410
 
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:
411
+ ## 状态码
412
+
413
+ ### 成功码
414
+
415
+ | 常量 | | 说明 |
416
+ |------|------|------|
417
+ | `READ_SUCCESS` | 10102 | 助记词读取成功 |
418
+ | `READ_NICKNAME_SUCCESS` | 10103 | 昵称读取成功 |
419
+ | `CHECK_EMPTY` | 10104 | 空卡 |
420
+ | `CHECK_HAS_DATA` | 10105 | 卡片有数据 |
421
+ | `READ_RETRY_COUNT_SUCCESS` | 10106 | 重试次数读取成功 |
422
+ | `GET_VERSION_SUCCESS` | 10107 | 卡片版本读取成功 |
423
+ | `READ_SIG_SUCCESS` | 10108 | 原厂签名读取成功 |
424
+ | `INIT_SUCCESS` | 10201 | 初始化成功 |
425
+ | `WRITE_SUCCESS` | 10203 | 写入/更新成功 |
426
+ | `UPDATE_PASSWORD_SUCCESS` | 10204 | 密码修改成功 |
427
+ | `WRITE_NICKNAME_SUCCESS` | 10205 | 昵称写入成功 |
428
+ | `RESET_SUCCESS` | 10206 | 卡片重置成功 |
429
+ | `PRECHECK_HAS_BACKUP` | 10207 | 卡片已有合法备份,跳过写入 |
430
+
431
+ ### 错误码
432
+
433
+ | 常量 | | 说明 |
434
+ |------|------|------|
435
+ | `NFC_CONNECT_FAILED` | 40001 | NFC 连接失败 |
436
+ | `AUTH_WRONG_PASSWORD` | 40002 | 密码错误 |
437
+ | `AUTH_INVALID_RESPONSE` | 40003 | 认证响应无效 |
438
+ | `AUTH_VERIFY_FAILED` | 40004 | 认证校验失败 |
439
+ | `READ_FAILED` | 40005 | 读取失败 |
440
+ | `WRITE_FAILED` | 40006 | 写入失败 |
441
+ | `INVALID_MNEMONIC` | 40007 | 助记词无效 |
442
+ | `UNSUPPORTED_MNEMONIC_LENGTH` | 40008 | 不支持的助记词长度 |
443
+ | `INVALID_CARD_DATA` | 40009 | 卡片数据无效 |
444
+ | `UNKNOWN_ERROR` | 40010 | 未知错误 |
445
+ | `NFC_USER_CANCELED` | 40011 | 用户取消 NFC 扫描(iOS) |
446
+ | `READ_TIMEOUT` | 40012 | 读取超时 |
447
+ | `NFC_LOCK_TIMEOUT` | 40013 | NFC 锁超时 |
448
+ | `CRC16_CHECK_FAILED` | 40014 | CRC16 校验失败 |
449
+ | `RETRY_COUNT_EXHAUSTED` | 40015 | PIN 重试次数耗尽,卡片已锁定 |
450
+
451
+ ## 存储格式
452
+
453
+ 卡片使用熵压缩方式存储 BIP-39 助记词:
418
454
 
419
455
  ```
420
- [type 1B] [entropy 16-32B] [CRC16 2B]
456
+ [类型 1B] [ 16-32B] [CRC16 2B]
421
457
  ```
422
458
 
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) |
459
+ | 类型 | 助记词长度 | 熵大小 |
460
+ |------|-----------|--------|
461
+ | 0x01 | 12 个词 | 16 字节(128 位) |
462
+ | 0x02 | 15 个词 | 20 字节(160 位) |
463
+ | 0x03 | 18 个词 | 24 字节(192 位) |
464
+ | 0x04 | 21 个词 | 28 字节(224 位) |
465
+ | 0x05 | 24 个词 | 32 字节(256 位) |
430
466
 
431
- ## Security
467
+ ## 安全性
432
468
 
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)
469
+ - **AES-128 硬件级双向认证**(3-pass
470
+ - **SHA-256 密钥派生**:密码 → SHA-256 → 取前 16 字节作为 AES 密钥
471
+ - **CRC16-Modbus 校验和**:数据完整性校验
472
+ - **CMAC 安全消息**:认证后所有命令附带 AES-CMAC(NIST 800-38B)防篡改
473
+ - **PIN 重试计数器**:密码错误时自动递减,认证成功后重置为 10
474
+ - **安全随机数**:认证使用 `crypto.getRandomValues()`(需要 Hermes ≥ 0.72 或 `react-native-get-random-values` polyfill)
438
475
 
439
- ## Project Structure
476
+ ## 项目结构
440
477
 
441
478
  ```
442
479
  src/
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
480
+ ├── index.ts # 公共 API 导出
481
+ ├── constants.ts # 共享常量(页地址、NFC 指令、助记词类型)
482
+ ├── types.ts # 统一 NfcStatusCode、NfcResult 接口、错误映射
483
+ ├── crypto.ts # AES 加解密、密钥派生、安全随机数
484
+ ├── utils.ts # CRC16、十六进制转换、数组工具
485
+ ├── nfc-core.ts # NFC 锁、transceive、认证、重试计数器
486
+ ├── reader.ts # 读取 API
487
+ └── writer.ts # 写入 API
451
488
  ```
452
489
 
453
- ## Platform Support
490
+ ## 平台支持
454
491
 
455
- | Platform | Technology | Requirements |
456
- |----------|-----------|--------------|
457
- | iOS | MifareIOS | iPhone 7 or later |
458
- | Android | NfcA | NFC-capable device |
492
+ | 平台 | 技术 | 要求 |
493
+ |------|------|------|
494
+ | iOS | MifareIOS | iPhone 7 及以上 |
495
+ | Android | NfcA | 支持 NFC 的设备 |
459
496
 
460
- ## License
497
+ ## 许可证
461
498
 
462
499
  MIT