keyfabe 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -29
- package/dist/commands/clone.js +17 -12
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/delete.js +3 -3
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/doctor.js +3 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/export.js +2 -2
- package/dist/commands/import.js +1 -1
- package/dist/commands/list.js +2 -2
- package/dist/commands/read.js +29 -27
- package/dist/commands/read.js.map +1 -1
- package/dist/commands/rename.js +4 -4
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/setup.js +4 -3
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/show.js +4 -4
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/write.js +12 -5
- package/dist/commands/write.js.map +1 -1
- package/dist/index.js +20 -17
- package/dist/index.js.map +1 -1
- package/dist/lib/card-ops.d.ts +1 -0
- package/dist/lib/card-ops.js +58 -43
- package/dist/lib/card-ops.js.map +1 -1
- package/dist/lib/constants.d.ts +20 -0
- package/dist/lib/constants.js +28 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/display.d.ts +1 -0
- package/dist/lib/display.js +4 -1
- package/dist/lib/display.js.map +1 -1
- package/dist/lib/parsers.d.ts +1 -0
- package/dist/lib/parsers.js +25 -2
- package/dist/lib/parsers.js.map +1 -1
- package/dist/lib/prompts.js +1 -1
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# keyfabe
|
|
2
2
|
|
|
3
|
-
A TypeScript CLI tool that wraps the Proxmark3 client to provide an ergonomic
|
|
3
|
+
A TypeScript CLI tool that wraps the Proxmark3 client to provide an ergonomic RFID tag cloning workflow.
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="demo.gif" alt="keyfabe demo" width="800" />
|
|
7
|
+
</p>
|
|
4
8
|
|
|
5
9
|
## What it does
|
|
6
10
|
|
|
7
11
|
- Automates the multi-step read/detect/clone/verify process into a single guided flow
|
|
8
12
|
- Detects and surfaces common problems (device not found, firmware mismatch, antenna issues)
|
|
9
|
-
- Stores cloned
|
|
13
|
+
- Stores cloned tag identities for later re-use
|
|
10
14
|
- Walks you through flashing Iceman firmware on a stock Proxmark3 Easy
|
|
11
|
-
- Export/import
|
|
15
|
+
- Export/import tag identities for backup and sharing
|
|
12
16
|
|
|
13
17
|
## Prerequisites
|
|
14
18
|
|
|
@@ -35,7 +39,12 @@ npx keyfabe
|
|
|
35
39
|
|
|
36
40
|
## Usage
|
|
37
41
|
|
|
42
|
+
Running `keyfabe` with no arguments launches an interactive wizard menu that guides you through all available actions.
|
|
43
|
+
|
|
38
44
|
```sh
|
|
45
|
+
# launch interactive wizard
|
|
46
|
+
keyfabe
|
|
47
|
+
|
|
39
48
|
# check device connection, firmware, and antenna health
|
|
40
49
|
keyfabe doctor
|
|
41
50
|
|
|
@@ -45,23 +54,23 @@ keyfabe setup
|
|
|
45
54
|
# guided interactive clone flow (read original → write to blank)
|
|
46
55
|
keyfabe clone
|
|
47
56
|
|
|
48
|
-
# read and identify a
|
|
57
|
+
# read and identify a tag without cloning
|
|
49
58
|
keyfabe read
|
|
50
59
|
|
|
51
|
-
# write a previously-saved identity to a blank
|
|
52
|
-
keyfabe write
|
|
60
|
+
# write a previously-saved identity to a blank tag
|
|
61
|
+
keyfabe write [name]
|
|
53
62
|
|
|
54
63
|
# list saved identities
|
|
55
64
|
keyfabe list
|
|
56
65
|
|
|
57
66
|
# show details of a saved identity
|
|
58
|
-
keyfabe show
|
|
67
|
+
keyfabe show [name]
|
|
59
68
|
|
|
60
69
|
# rename a saved identity
|
|
61
|
-
keyfabe rename
|
|
70
|
+
keyfabe rename [old-name] [new-name]
|
|
62
71
|
|
|
63
72
|
# delete a saved identity
|
|
64
|
-
keyfabe delete
|
|
73
|
+
keyfabe delete [name]
|
|
65
74
|
|
|
66
75
|
# export all saved identities as JSON
|
|
67
76
|
keyfabe export > fobs.json
|
|
@@ -70,6 +79,8 @@ keyfabe export > fobs.json
|
|
|
70
79
|
keyfabe import fobs.json
|
|
71
80
|
```
|
|
72
81
|
|
|
82
|
+
Commands that take `[name]` arguments are fully optional — when omitted, you'll get an interactive tag picker.
|
|
83
|
+
|
|
73
84
|
## Commands
|
|
74
85
|
|
|
75
86
|
### `keyfabe doctor`
|
|
@@ -82,47 +93,51 @@ Interactive wizard for flashing Iceman firmware to a stock Proxmark3 Easy. Handl
|
|
|
82
93
|
|
|
83
94
|
### `keyfabe clone`
|
|
84
95
|
|
|
85
|
-
Guided clone flow: reads the original
|
|
96
|
+
Guided clone flow: reads the original tag (LF and HF), writes the ID to a blank card, and verifies the readback. Optionally saves the identity for later use.
|
|
86
97
|
|
|
87
98
|
### `keyfabe read`
|
|
88
99
|
|
|
89
|
-
Reads and identifies whatever
|
|
100
|
+
Reads and identifies whatever tag is on the antenna. Searches LF first, then falls back to HF. Supports EM410x, HID Prox, MIFARE Classic, MIFARE Ultralight, MIFARE DESFire, and ISO 14443-A. Optionally saves the identity.
|
|
90
101
|
|
|
91
|
-
### `keyfabe write
|
|
102
|
+
### `keyfabe write [name]`
|
|
92
103
|
|
|
93
|
-
Writes a previously-saved identity to a blank
|
|
104
|
+
Writes a previously-saved identity to a blank tag. Without a name, presents an interactive picker.
|
|
94
105
|
|
|
95
106
|
### `keyfabe list`
|
|
96
107
|
|
|
97
|
-
Lists all saved
|
|
108
|
+
Lists all saved tag identities from `~/.keyfabe/fobs.json`.
|
|
98
109
|
|
|
99
|
-
### `keyfabe show
|
|
110
|
+
### `keyfabe show [name]`
|
|
100
111
|
|
|
101
|
-
Displays full details of a saved
|
|
112
|
+
Displays full details of a saved tag identity (type, ID, encoding, save date). Without a name, presents an interactive picker.
|
|
102
113
|
|
|
103
|
-
### `keyfabe rename
|
|
114
|
+
### `keyfabe rename [old-name] [new-name]`
|
|
104
115
|
|
|
105
|
-
Renames a saved
|
|
116
|
+
Renames a saved tag identity. Missing arguments are prompted interactively.
|
|
106
117
|
|
|
107
|
-
### `keyfabe delete
|
|
118
|
+
### `keyfabe delete [name]`
|
|
108
119
|
|
|
109
|
-
Deletes a saved
|
|
120
|
+
Deletes a saved tag identity. Without a name, presents an interactive picker.
|
|
110
121
|
|
|
111
122
|
### `keyfabe export`
|
|
112
123
|
|
|
113
|
-
Exports all saved
|
|
124
|
+
Exports all saved tag identities as JSON to stdout. Pipe to a file for backup: `keyfabe export > fobs.json`.
|
|
114
125
|
|
|
115
126
|
### `keyfabe import <file>`
|
|
116
127
|
|
|
117
|
-
Imports
|
|
128
|
+
Imports tag identities from a JSON file. New names are added, existing names are updated.
|
|
118
129
|
|
|
119
130
|
## Supported Card Types
|
|
120
131
|
|
|
121
|
-
| Type | Read | Clone | Notes |
|
|
122
|
-
|
|
123
|
-
| EM410x | yes | yes | Most common LF keyfob |
|
|
124
|
-
| HID Prox | yes | yes | Uses `lf hid clone` |
|
|
125
|
-
|
|
|
132
|
+
| Type | Frequency | Read | Clone | Notes |
|
|
133
|
+
|------|-----------|------|-------|-------|
|
|
134
|
+
| EM410x | LF (125 kHz) | yes | yes | Most common LF keyfob |
|
|
135
|
+
| HID Prox | LF (125 kHz) | yes | yes | Uses `lf hid clone` |
|
|
136
|
+
| MIFARE Classic 1K/4K | HF (13.56 MHz) | yes | yes | Uses `hf mf csetuid` (magic card required) |
|
|
137
|
+
| MIFARE Ultralight | HF (13.56 MHz) | yes | no | Read-only support |
|
|
138
|
+
| MIFARE DESFire | HF (13.56 MHz) | yes | no | Read-only support |
|
|
139
|
+
| ISO 14443-A | HF (13.56 MHz) | yes | no | Generic HF detection |
|
|
140
|
+
| T55x7 | LF (125 kHz) | detect | n/a | Target writable card |
|
|
126
141
|
|
|
127
142
|
## Development
|
|
128
143
|
|
|
@@ -144,7 +159,7 @@ src/
|
|
|
144
159
|
commands/
|
|
145
160
|
doctor.ts # device health check
|
|
146
161
|
setup.ts # firmware flash wizard
|
|
147
|
-
read.ts # read
|
|
162
|
+
read.ts # read tag
|
|
148
163
|
clone.ts # guided clone flow
|
|
149
164
|
write.ts # write saved identity
|
|
150
165
|
list.ts # list saved identities
|
|
@@ -158,7 +173,8 @@ src/
|
|
|
158
173
|
firmware.ts # build/flash subprocess helpers
|
|
159
174
|
parsers.ts # parse pm3 output (card type, ID, voltages)
|
|
160
175
|
store.ts # read/write ~/.keyfabe/fobs.json
|
|
161
|
-
|
|
176
|
+
constants.ts # shared card type and pm3 command constants
|
|
177
|
+
card-ops.ts # search, write-and-verify logic shared by commands
|
|
162
178
|
display.ts # shared display helpers and constants
|
|
163
179
|
prompts.ts # interactive user prompts
|
|
164
180
|
```
|
package/dist/commands/clone.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
-
import { writeAndVerify } from "../lib/card-ops.js";
|
|
2
|
+
import { searchCard, writeAndVerify } from "../lib/card-ops.js";
|
|
3
|
+
import { cardFrequency } from "../lib/constants.js";
|
|
3
4
|
import { printCardInfo, printDoctorHint } from "../lib/display.js";
|
|
4
|
-
import {
|
|
5
|
-
import { Pm3Error, pm3Exec, requireDevice } from "../lib/pm3.js";
|
|
5
|
+
import { Pm3Error, requireDevice } from "../lib/pm3.js";
|
|
6
6
|
import { promptName, waitForEnter } from "../lib/prompts.js";
|
|
7
7
|
import { saveFob } from "../lib/store.js";
|
|
8
8
|
const MAX_READ_RETRIES = 3;
|
|
@@ -10,22 +10,21 @@ const READ_RETRY_DELAY = 2000;
|
|
|
10
10
|
export async function clone() {
|
|
11
11
|
if (!(await requireDevice()))
|
|
12
12
|
return false;
|
|
13
|
-
p.intro("
|
|
13
|
+
p.intro("Clone Tag");
|
|
14
14
|
// Step 1: Read original
|
|
15
|
-
await waitForEnter("Place your original
|
|
15
|
+
await waitForEnter("Place your original tag on the antenna.");
|
|
16
16
|
let card = null;
|
|
17
17
|
for (let attempt = 1; attempt <= MAX_READ_RETRIES; attempt++) {
|
|
18
18
|
const s = p.spinner();
|
|
19
19
|
s.start(`Reading original (attempt ${attempt}/${MAX_READ_RETRIES})...`);
|
|
20
20
|
try {
|
|
21
|
-
|
|
22
|
-
card = parseLfSearch(stdout);
|
|
21
|
+
card = await searchCard();
|
|
23
22
|
if (card) {
|
|
24
|
-
s.stop("Original
|
|
23
|
+
s.stop("Original tag read");
|
|
25
24
|
break;
|
|
26
25
|
}
|
|
27
|
-
s.stop("No
|
|
28
|
-
p.log.error("No
|
|
26
|
+
s.stop("No tag detected.");
|
|
27
|
+
p.log.error("No tag detected.");
|
|
29
28
|
}
|
|
30
29
|
catch (err) {
|
|
31
30
|
if (err instanceof Pm3Error) {
|
|
@@ -46,12 +45,18 @@ export async function clone() {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
if (!card) {
|
|
49
|
-
p.log.error("Failed to read original
|
|
48
|
+
p.log.error("Failed to read original tag after all attempts.");
|
|
50
49
|
return false;
|
|
51
50
|
}
|
|
52
51
|
printCardInfo(card);
|
|
53
52
|
// Step 2: Write to blank
|
|
54
|
-
|
|
53
|
+
const freq = cardFrequency(card.type);
|
|
54
|
+
if (freq === "LF") {
|
|
55
|
+
await waitForEnter("Remove original and place a blank T55x7 tag on the antenna.");
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
await waitForEnter("Remove original and place the target tag on the antenna.");
|
|
59
|
+
}
|
|
55
60
|
const success = await writeAndVerify(card);
|
|
56
61
|
if (success) {
|
|
57
62
|
p.log.success("Clone successful!");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/commands/clone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/commands/clone.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/delete.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
-
import { printFobNotFound } from "../lib/display.js";
|
|
2
|
+
import { printFobNotFound, printNoSavedTags } from "../lib/display.js";
|
|
3
3
|
import { confirm, selectFob } from "../lib/prompts.js";
|
|
4
4
|
import { loadFobs, removeFob } from "../lib/store.js";
|
|
5
5
|
export async function deleteFob(name) {
|
|
6
6
|
if (!name) {
|
|
7
7
|
const fobs = await loadFobs();
|
|
8
8
|
if (fobs.length === 0) {
|
|
9
|
-
|
|
9
|
+
printNoSavedTags();
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
|
-
name = await selectFob(fobs, "Which
|
|
12
|
+
name = await selectFob(fobs, "Which tag to delete?");
|
|
13
13
|
}
|
|
14
14
|
const shouldDelete = await confirm(`Delete "${name}"?`);
|
|
15
15
|
if (!shouldDelete) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAa;IACzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,gBAAgB,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAChC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
+
import { Pm3Cmd } from "../lib/constants.js";
|
|
3
4
|
import { HF_VOLTAGE_THRESHOLD, LF_VOLTAGE_THRESHOLD, printBrewInstall } from "../lib/display.js";
|
|
4
5
|
import { parseHwStatus, parseHwTune } from "../lib/parsers.js";
|
|
5
6
|
import { detectPort, Pm3Error, pm3Exec } from "../lib/pm3.js";
|
|
@@ -18,7 +19,7 @@ export async function doctor() {
|
|
|
18
19
|
const s = p.spinner();
|
|
19
20
|
s.start("Checking device communication...");
|
|
20
21
|
try {
|
|
21
|
-
const { stdout } = await pm3Exec(
|
|
22
|
+
const { stdout } = await pm3Exec(Pm3Cmd.HW_STATUS);
|
|
22
23
|
const status = parseHwStatus(stdout);
|
|
23
24
|
if (status.isStockFirmware) {
|
|
24
25
|
s.stop("Stock firmware detected.");
|
|
@@ -52,7 +53,7 @@ export async function doctor() {
|
|
|
52
53
|
const tuneSpinner = p.spinner();
|
|
53
54
|
tuneSpinner.start("Checking antenna tuning...");
|
|
54
55
|
try {
|
|
55
|
-
const { stdout } = await pm3Exec(
|
|
56
|
+
const { stdout } = await pm3Exec(Pm3Cmd.HW_TUNE);
|
|
56
57
|
const tune = parseHwTune(stdout);
|
|
57
58
|
tuneSpinner.stop("Antenna tuning complete");
|
|
58
59
|
const lfColor = tune.lfVoltage >= LF_VOLTAGE_THRESHOLD ? chalk.green : chalk.red;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,MAAM;IACxB,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAElC,oBAAoB;IACpB,MAAM,IAAI,GAAG,MAAM,UAAU,EAAE,CAAC;IAChC,IAAI,IAAI,EAAE,CAAC;QACP,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACJ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,yBAAyB;IACzB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC5C,IAAI,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/export.js
CHANGED
|
@@ -2,12 +2,12 @@ import { loadFobs } from "../lib/store.js";
|
|
|
2
2
|
export async function exportFobs() {
|
|
3
3
|
const fobs = await loadFobs();
|
|
4
4
|
if (fobs.length === 0) {
|
|
5
|
-
console.error("No saved
|
|
5
|
+
console.error("No saved tags to export.");
|
|
6
6
|
return false;
|
|
7
7
|
}
|
|
8
8
|
// Output clean JSON to stdout for piping
|
|
9
9
|
process.stdout.write(`${JSON.stringify(fobs, null, 2)}\n`);
|
|
10
|
-
console.error(`Exported ${fobs.length}
|
|
10
|
+
console.error(`Exported ${fobs.length} tag(s).`);
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
13
|
//# sourceMappingURL=export.js.map
|
package/dist/commands/import.js
CHANGED
|
@@ -29,7 +29,7 @@ export async function importFile(filePath) {
|
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
31
|
if (!validateFobs(data)) {
|
|
32
|
-
p.log.error("Invalid format. Expected an array of
|
|
32
|
+
p.log.error("Invalid format. Expected an array of tag objects with name, type, id, and savedAt.");
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
const { added, updated } = await importFobs(data);
|
package/dist/commands/list.js
CHANGED
|
@@ -7,7 +7,7 @@ export async function list(options = {}) {
|
|
|
7
7
|
return true;
|
|
8
8
|
}
|
|
9
9
|
if (fobs.length === 0) {
|
|
10
|
-
p.log.info("No saved
|
|
10
|
+
p.log.info("No saved tags. Use `keyfabe read` or `keyfabe clone` to save one.");
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
13
|
const hasEncoding = fobs.some((f) => f.encoding);
|
|
@@ -32,7 +32,7 @@ export async function list(options = {}) {
|
|
|
32
32
|
row += date;
|
|
33
33
|
rows.push(row);
|
|
34
34
|
}
|
|
35
|
-
p.note(`${header}\n${rows.join("\n")}`, `Saved
|
|
35
|
+
p.note(`${header}\n${rows.join("\n")}`, `Saved Tags (${fobs.length})`);
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
38
|
//# sourceMappingURL=list.js.map
|
package/dist/commands/read.js
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
+
import { searchCard } from "../lib/card-ops.js";
|
|
2
3
|
import { printCardInfo, printDoctorHint } from "../lib/display.js";
|
|
3
|
-
import {
|
|
4
|
-
import { Pm3Error, pm3Exec, requireDevice } from "../lib/pm3.js";
|
|
4
|
+
import { Pm3Error, requireDevice } from "../lib/pm3.js";
|
|
5
5
|
import { promptName } from "../lib/prompts.js";
|
|
6
6
|
import { saveFob } from "../lib/store.js";
|
|
7
7
|
export async function read() {
|
|
8
8
|
if (!(await requireDevice()))
|
|
9
9
|
return false;
|
|
10
|
-
p.intro("Read
|
|
11
|
-
let card = null;
|
|
10
|
+
p.intro("Read Tag");
|
|
12
11
|
const s = p.spinner();
|
|
13
|
-
s.start("Searching for
|
|
12
|
+
s.start("Searching for tag...");
|
|
14
13
|
try {
|
|
15
|
-
const
|
|
16
|
-
|
|
14
|
+
const card = await searchCard();
|
|
15
|
+
if (!card) {
|
|
16
|
+
s.stop("No tag detected. Make sure the tag is flat against the antenna.");
|
|
17
|
+
p.log.error("No tag detected. Make sure the tag is flat against the antenna.");
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
s.stop("Tag detected");
|
|
21
|
+
printCardInfo(card);
|
|
22
|
+
// Prompt to save
|
|
23
|
+
const name = await promptName();
|
|
24
|
+
if (name) {
|
|
25
|
+
await saveFob({
|
|
26
|
+
name,
|
|
27
|
+
type: card.type,
|
|
28
|
+
id: card.id,
|
|
29
|
+
encoding: card.encoding,
|
|
30
|
+
savedAt: new Date().toISOString(),
|
|
31
|
+
});
|
|
32
|
+
p.log.success(`Saved as "${name}".`);
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
17
35
|
}
|
|
18
36
|
catch (err) {
|
|
19
37
|
if (err instanceof Pm3Error) {
|
|
@@ -22,28 +40,12 @@ export async function read() {
|
|
|
22
40
|
if (err.message.includes("not found")) {
|
|
23
41
|
printDoctorHint();
|
|
24
42
|
}
|
|
25
|
-
return false;
|
|
26
43
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
44
|
+
else {
|
|
45
|
+
s.stop("Search failed.");
|
|
46
|
+
p.log.error("Search failed.");
|
|
47
|
+
}
|
|
31
48
|
return false;
|
|
32
49
|
}
|
|
33
|
-
s.stop("Card detected");
|
|
34
|
-
printCardInfo(card);
|
|
35
|
-
// Prompt to save
|
|
36
|
-
const name = await promptName();
|
|
37
|
-
if (name) {
|
|
38
|
-
await saveFob({
|
|
39
|
-
name,
|
|
40
|
-
type: card.type,
|
|
41
|
-
id: card.id,
|
|
42
|
-
encoding: card.encoding,
|
|
43
|
-
savedAt: new Date().toISOString(),
|
|
44
|
-
});
|
|
45
|
-
p.log.success(`Saved as "${name}".`);
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
48
50
|
}
|
|
49
51
|
//# sourceMappingURL=read.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/commands/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/commands/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,IAAI;IACtB,IAAI,CAAC,CAAC,MAAM,aAAa,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAEpB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAChC,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,CAAC,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAC1E,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;YAC/E,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACvB,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpB,iBAAiB;QACjB,MAAM,IAAI,GAAG,MAAM,UAAU,EAAE,CAAC;QAChC,IAAI,IAAI,EAAE,CAAC;YACP,MAAM,OAAO,CAAC;gBACV,IAAI;gBACJ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;YACH,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzB,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACpC,eAAe,EAAE,CAAC;YACtB,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACzB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}
|
package/dist/commands/rename.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
-
import { printFobNotFound } from "../lib/display.js";
|
|
2
|
+
import { printFobNotFound, printNoSavedTags } from "../lib/display.js";
|
|
3
3
|
import { selectFob } from "../lib/prompts.js";
|
|
4
4
|
import { loadFobs, renameFob } from "../lib/store.js";
|
|
5
5
|
function handleCancel(value) {
|
|
@@ -12,10 +12,10 @@ export async function rename(oldName, newName) {
|
|
|
12
12
|
if (!oldName) {
|
|
13
13
|
const fobs = await loadFobs();
|
|
14
14
|
if (fobs.length === 0) {
|
|
15
|
-
|
|
15
|
+
printNoSavedTags();
|
|
16
16
|
return false;
|
|
17
17
|
}
|
|
18
|
-
oldName = await selectFob(fobs, "Which
|
|
18
|
+
oldName = await selectFob(fobs, "Which tag to rename?");
|
|
19
19
|
}
|
|
20
20
|
if (!newName) {
|
|
21
21
|
const value = await p.text({ message: "New name", placeholder: "e.g. front-door" });
|
|
@@ -28,7 +28,7 @@ export async function rename(oldName, newName) {
|
|
|
28
28
|
return false;
|
|
29
29
|
}
|
|
30
30
|
if (result === "name-taken") {
|
|
31
|
-
p.log.error(`A
|
|
31
|
+
p.log.error(`A tag named "${newName}" already exists. Delete it first or choose a different name.`);
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
34
|
p.log.success(`Renamed "${oldName}" to "${newName}".`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rename.js","sourceRoot":"","sources":["../../src/commands/rename.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"rename.js","sourceRoot":"","sources":["../../src/commands/rename.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtD,SAAS,YAAY,CAAC,KAAc;IAChC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAgB,EAAE,OAAgB;IAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,gBAAgB,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACpF,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,GAAG,KAAe,CAAC;IAC9B,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,OAAiB,CAAC,CAAC;IAE3D,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QACzB,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC1B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;QAC1B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,OAAO,+DAA+D,CAAC,CAAC;QACpG,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,OAAO,SAAS,OAAO,IAAI,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
+
import { Pm3Cmd } from "../lib/constants.js";
|
|
2
3
|
import { printBrewInstall } from "../lib/display.js";
|
|
3
4
|
import { buildFirmware, checkInstalled, execCommand, findBrewCache, flashFirmware, waitForDevice, } from "../lib/firmware.js";
|
|
4
5
|
import { parseHwStatus, parseHwTune } from "../lib/parsers.js";
|
|
@@ -39,7 +40,7 @@ export async function setup() {
|
|
|
39
40
|
const diagSpinner = p.spinner();
|
|
40
41
|
diagSpinner.start("Running hw status...");
|
|
41
42
|
try {
|
|
42
|
-
const { stdout } = await pm3Exec(
|
|
43
|
+
const { stdout } = await pm3Exec(Pm3Cmd.HW_STATUS);
|
|
43
44
|
const status = parseHwStatus(stdout);
|
|
44
45
|
if (status.connected) {
|
|
45
46
|
diagSpinner.stop("Firmware is already working.");
|
|
@@ -135,7 +136,7 @@ export async function setup() {
|
|
|
135
136
|
const verifySpinner = p.spinner();
|
|
136
137
|
verifySpinner.start("Checking communication...");
|
|
137
138
|
try {
|
|
138
|
-
const { stdout } = await pm3Exec(
|
|
139
|
+
const { stdout } = await pm3Exec(Pm3Cmd.HW_STATUS);
|
|
139
140
|
const status = parseHwStatus(stdout);
|
|
140
141
|
if (!status.connected) {
|
|
141
142
|
verifySpinner.stop("Communication still failing after flash.");
|
|
@@ -152,7 +153,7 @@ export async function setup() {
|
|
|
152
153
|
const tuneSpinner = p.spinner();
|
|
153
154
|
tuneSpinner.start("Checking antenna tuning...");
|
|
154
155
|
try {
|
|
155
|
-
const { stdout } = await pm3Exec(
|
|
156
|
+
const { stdout } = await pm3Exec(Pm3Cmd.HW_TUNE);
|
|
156
157
|
const tune = parseHwTune(stdout);
|
|
157
158
|
tuneSpinner.stop("Antenna check complete");
|
|
158
159
|
p.log.success(`LF antenna: ${tune.lfVoltage.toFixed(2)}V (125 kHz)`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACH,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,KAAK;IACvB,CAAC,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAEpC,wBAAwB;IACxB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC9B,gBAAgB,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;QACxF,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEjC,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;IACvD,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC5C,gBAAgB,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAEtC,MAAM,IAAI,GAAG,MAAM,UAAU,EAAE,CAAC;IAChC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAEjC,iCAAiC;IACjC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IAEnD,MAAM,WAAW,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAChC,WAAW,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,IAAI,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/show.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
-
import { printFobNotFound } from "../lib/display.js";
|
|
2
|
+
import { printFobNotFound, printNoSavedTags } from "../lib/display.js";
|
|
3
3
|
import { selectFob } from "../lib/prompts.js";
|
|
4
4
|
import { getFob, loadFobs } from "../lib/store.js";
|
|
5
5
|
export async function show(name) {
|
|
6
6
|
if (!name) {
|
|
7
7
|
const fobs = await loadFobs();
|
|
8
8
|
if (fobs.length === 0) {
|
|
9
|
-
|
|
9
|
+
printNoSavedTags();
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
|
-
name = await selectFob(fobs, "Which
|
|
12
|
+
name = await selectFob(fobs, "Which tag to show?");
|
|
13
13
|
}
|
|
14
14
|
const fob = await getFob(name);
|
|
15
15
|
if (!fob) {
|
|
@@ -23,7 +23,7 @@ export async function show(name) {
|
|
|
23
23
|
...(fob.encoding ? [`Encoding: ${fob.encoding}`] : []),
|
|
24
24
|
`Saved: ${fob.savedAt.slice(0, 10)}`,
|
|
25
25
|
];
|
|
26
|
-
p.note(lines.join("\n"), "
|
|
26
|
+
p.note(lines.join("\n"), "Tag Details");
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
29
|
//# sourceMappingURL=show.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAa;IACpC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,gBAAgB,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GAAG;QACV,aAAa,GAAG,CAAC,IAAI,EAAE;QACvB,aAAa,GAAG,CAAC,IAAI,EAAE;QACvB,aAAa,GAAG,CAAC,EAAE,EAAE;QACrB,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,aAAa,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;KAC1C,CAAC;IACF,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
package/dist/commands/write.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { writeAndVerify } from "../lib/card-ops.js";
|
|
3
|
-
import {
|
|
3
|
+
import { cardFrequency } from "../lib/constants.js";
|
|
4
|
+
import { printFobNotFound, printNoSavedTags } from "../lib/display.js";
|
|
4
5
|
import { requireDevice } from "../lib/pm3.js";
|
|
5
6
|
import { selectFob, waitForEnter } from "../lib/prompts.js";
|
|
6
7
|
import { getFob, loadFobs } from "../lib/store.js";
|
|
7
8
|
export async function write(name) {
|
|
8
|
-
p.intro("Write
|
|
9
|
+
p.intro("Write Tag");
|
|
9
10
|
if (!name) {
|
|
10
11
|
const fobs = await loadFobs();
|
|
11
12
|
if (fobs.length === 0) {
|
|
12
|
-
|
|
13
|
+
printNoSavedTags();
|
|
13
14
|
return false;
|
|
14
15
|
}
|
|
15
|
-
name = await selectFob(fobs, "Which
|
|
16
|
+
name = await selectFob(fobs, "Which tag identity to write?");
|
|
16
17
|
}
|
|
17
18
|
const fob = await getFob(name);
|
|
18
19
|
if (!fob) {
|
|
@@ -22,7 +23,13 @@ export async function write(name) {
|
|
|
22
23
|
if (!(await requireDevice()))
|
|
23
24
|
return false;
|
|
24
25
|
p.log.info(`Writing "${fob.name}" (${fob.type} ${fob.id})`);
|
|
25
|
-
|
|
26
|
+
const freq = cardFrequency(fob.type);
|
|
27
|
+
if (freq === "LF") {
|
|
28
|
+
await waitForEnter("Place a blank T55x7 tag on the antenna.");
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
await waitForEnter("Place the target tag on the antenna.");
|
|
32
|
+
}
|
|
26
33
|
const success = await writeAndVerify({ type: fob.type, id: fob.id, encoding: fob.encoding });
|
|
27
34
|
if (success) {
|
|
28
35
|
p.outro("Write successful!");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAa;IACrC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAErB,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,gBAAgB,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,aAAa,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAChB,MAAM,YAAY,CAAC,yCAAyC,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACJ,MAAM,YAAY,CAAC,sCAAsC,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE7F,IAAI,OAAO,EAAE,CAAC;QACV,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ function withExitCode(fn) {
|
|
|
19
19
|
process.exitCode = 1;
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
program.name("keyfabe").description("CLI tool for Proxmark3
|
|
22
|
+
program.name("keyfabe").description("CLI tool for Proxmark3 tag cloning").version("0.1.0");
|
|
23
23
|
program.action(withExitCode(async () => {
|
|
24
24
|
if (!process.stdout.isTTY) {
|
|
25
25
|
program.help();
|
|
@@ -29,10 +29,10 @@ program.action(withExitCode(async () => {
|
|
|
29
29
|
const action = await p.select({
|
|
30
30
|
message: "What would you like to do?",
|
|
31
31
|
options: [
|
|
32
|
-
{ value: "clone", label: "Clone a
|
|
33
|
-
{ value: "read", label: "Read a
|
|
34
|
-
{ value: "write", label: "Write a saved identity", hint: "write to blank
|
|
35
|
-
{ value: "list", label: "List saved
|
|
32
|
+
{ value: "clone", label: "Clone a tag", hint: "read + write + verify" },
|
|
33
|
+
{ value: "read", label: "Read a tag", hint: "identify and save" },
|
|
34
|
+
{ value: "write", label: "Write a saved identity", hint: "write to blank tag" },
|
|
35
|
+
{ value: "list", label: "List saved tags" },
|
|
36
36
|
{ value: "doctor", label: "Health check", hint: "diagnose device" },
|
|
37
37
|
{ value: "setup", label: "Firmware setup", hint: "flash Iceman firmware" },
|
|
38
38
|
],
|
|
@@ -62,38 +62,41 @@ program
|
|
|
62
62
|
.command("doctor")
|
|
63
63
|
.description("Check device connection, firmware, and antenna health")
|
|
64
64
|
.action(withExitCode(doctor));
|
|
65
|
-
program.command("read").description("Read and identify a
|
|
66
|
-
program
|
|
65
|
+
program.command("read").description("Read and identify a tag on the antenna").action(withExitCode(read));
|
|
66
|
+
program
|
|
67
|
+
.command("clone")
|
|
68
|
+
.description("Interactive guided clone flow (read + write + verify)")
|
|
69
|
+
.action(withExitCode(clone));
|
|
67
70
|
program
|
|
68
71
|
.command("write")
|
|
69
|
-
.description("Write a previously-saved identity to a blank
|
|
70
|
-
.argument("[name]", "name of the saved
|
|
72
|
+
.description("Write a previously-saved identity to a blank tag")
|
|
73
|
+
.argument("[name]", "name of the saved tag identity")
|
|
71
74
|
.action(withExitCode(write));
|
|
72
75
|
program
|
|
73
76
|
.command("list")
|
|
74
|
-
.description("List all saved
|
|
77
|
+
.description("List all saved tag identities")
|
|
75
78
|
.option("--json", "output as JSON")
|
|
76
79
|
.action(withExitCode(list));
|
|
77
80
|
program
|
|
78
81
|
.command("show")
|
|
79
|
-
.description("Show details of a saved
|
|
80
|
-
.argument("[name]", "name of the saved
|
|
82
|
+
.description("Show details of a saved tag identity")
|
|
83
|
+
.argument("[name]", "name of the saved tag identity")
|
|
81
84
|
.action(withExitCode(show));
|
|
82
85
|
program
|
|
83
86
|
.command("rename")
|
|
84
|
-
.description("Rename a saved
|
|
87
|
+
.description("Rename a saved tag identity")
|
|
85
88
|
.argument("[old-name]", "current name")
|
|
86
89
|
.argument("[new-name]", "new name")
|
|
87
90
|
.action(withExitCode(rename));
|
|
88
91
|
program
|
|
89
92
|
.command("delete")
|
|
90
|
-
.description("Delete a saved
|
|
91
|
-
.argument("[name]", "name of the saved
|
|
93
|
+
.description("Delete a saved tag identity")
|
|
94
|
+
.argument("[name]", "name of the saved tag identity")
|
|
92
95
|
.action(withExitCode(deleteFob));
|
|
93
|
-
program.command("export").description("Export all saved
|
|
96
|
+
program.command("export").description("Export all saved tag identities as JSON").action(withExitCode(exportFobs));
|
|
94
97
|
program
|
|
95
98
|
.command("import")
|
|
96
|
-
.description("Import
|
|
99
|
+
.description("Import tag identities from a JSON file")
|
|
97
100
|
.argument("<file>", "path to JSON file")
|
|
98
101
|
.action(withExitCode(importFile));
|
|
99
102
|
program.command("setup").description("Flash Iceman firmware to a stock Proxmark3 Easy").action(withExitCode(setup));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,SAAS,YAAY,CAAC,EAAwC;IAC1D,OAAO,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;QAC5B,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IAClC,CAAC,CAAC;AACN,CAAC;AAED,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/card-ops.d.ts
CHANGED
package/dist/lib/card-ops.js
CHANGED
|
@@ -1,54 +1,75 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
+
import { CardType, cardFrequency, Pm3Cmd } from "./constants.js";
|
|
2
3
|
import { printDoctorHint } from "./display.js";
|
|
3
|
-
import { parseCloneResult, parseLfSearch, parseT55xxDetect } from "./parsers.js";
|
|
4
|
+
import { parseCloneResult, parseHfSearch, parseLfSearch, parseT55xxDetect } from "./parsers.js";
|
|
4
5
|
import { Pm3Error, pm3Exec } from "./pm3.js";
|
|
6
|
+
export async function searchCard() {
|
|
7
|
+
const { stdout: lfOut } = await pm3Exec(Pm3Cmd.LF_SEARCH);
|
|
8
|
+
const lfCard = parseLfSearch(lfOut);
|
|
9
|
+
if (lfCard)
|
|
10
|
+
return lfCard;
|
|
11
|
+
const { stdout: hfOut } = await pm3Exec(Pm3Cmd.HF_SEARCH);
|
|
12
|
+
return parseHfSearch(hfOut);
|
|
13
|
+
}
|
|
5
14
|
function cloneCommand(card) {
|
|
6
15
|
switch (card.type) {
|
|
7
|
-
case
|
|
16
|
+
case CardType.EM410x:
|
|
8
17
|
return `lf em 410x clone --id ${card.id}`;
|
|
9
|
-
case
|
|
18
|
+
case CardType.HID_PROX:
|
|
10
19
|
return `lf hid clone -r ${card.id}`;
|
|
20
|
+
case CardType.MIFARE_CLASSIC_1K:
|
|
21
|
+
case CardType.MIFARE_CLASSIC_4K:
|
|
22
|
+
return `hf mf csetuid ${card.id}`;
|
|
11
23
|
default:
|
|
12
24
|
throw new Error(`Unsupported card type: ${card.type}`);
|
|
13
25
|
}
|
|
14
26
|
}
|
|
15
27
|
function verifyCommand(card) {
|
|
16
28
|
switch (card.type) {
|
|
17
|
-
case
|
|
18
|
-
return
|
|
19
|
-
case
|
|
20
|
-
return
|
|
29
|
+
case CardType.EM410x:
|
|
30
|
+
return Pm3Cmd.LF_EM_410X_READER;
|
|
31
|
+
case CardType.HID_PROX:
|
|
32
|
+
return Pm3Cmd.LF_HID_READER;
|
|
21
33
|
default:
|
|
22
|
-
return
|
|
34
|
+
return Pm3Cmd.HF_SEARCH;
|
|
23
35
|
}
|
|
24
36
|
}
|
|
37
|
+
function stopWithError(spinner, message) {
|
|
38
|
+
spinner.stop(message);
|
|
39
|
+
p.log.error(message);
|
|
40
|
+
}
|
|
25
41
|
export async function writeAndVerify(card) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const t55 = parseT55xxDetect(stdout);
|
|
32
|
-
if (!t55) {
|
|
33
|
-
detectSpinner.stop("Card is not a writable T55x7. Use a blank T55x7 fob.");
|
|
34
|
-
p.log.error("Card is not a writable T55x7. Use a blank T55x7 fob.");
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
detectSpinner.stop(`Writable card detected (${t55.chipType})`);
|
|
42
|
+
const freq = cardFrequency(card.type);
|
|
43
|
+
// HF cards other than MIFARE Classic are not yet supported
|
|
44
|
+
if (freq === "HF" && card.type !== CardType.MIFARE_CLASSIC_1K && card.type !== CardType.MIFARE_CLASSIC_4K) {
|
|
45
|
+
p.log.error(`Writing ${card.type} cards is not yet supported.`);
|
|
46
|
+
return false;
|
|
38
47
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
// Detect T55x7 (LF only)
|
|
49
|
+
if (freq === "LF") {
|
|
50
|
+
const detectSpinner = p.spinner();
|
|
51
|
+
detectSpinner.start("Detecting writable card...");
|
|
52
|
+
try {
|
|
53
|
+
const { stdout } = await pm3Exec(Pm3Cmd.LF_T55XX_DETECT);
|
|
54
|
+
const t55 = parseT55xxDetect(stdout);
|
|
55
|
+
if (!t55) {
|
|
56
|
+
stopWithError(detectSpinner, "Card is not a writable T55x7. Use a blank T55x7 tag.");
|
|
57
|
+
return false;
|
|
45
58
|
}
|
|
59
|
+
detectSpinner.stop(`Writable card detected (${t55.chipType})`);
|
|
46
60
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
catch (err) {
|
|
62
|
+
if (err instanceof Pm3Error) {
|
|
63
|
+
stopWithError(detectSpinner, err.message);
|
|
64
|
+
if (err.message.includes("not found")) {
|
|
65
|
+
printDoctorHint();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
stopWithError(detectSpinner, "Failed to detect writable card.");
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
50
72
|
}
|
|
51
|
-
return false;
|
|
52
73
|
}
|
|
53
74
|
// Clone
|
|
54
75
|
const cloneSpinner = p.spinner();
|
|
@@ -58,23 +79,20 @@ export async function writeAndVerify(card) {
|
|
|
58
79
|
const { stdout } = await pm3Exec(cmd);
|
|
59
80
|
const result = parseCloneResult(stdout);
|
|
60
81
|
if (!result.success) {
|
|
61
|
-
cloneSpinner
|
|
62
|
-
p.log.error("Write command did not confirm success.");
|
|
82
|
+
stopWithError(cloneSpinner, "Write command did not confirm success.");
|
|
63
83
|
return false;
|
|
64
84
|
}
|
|
65
85
|
cloneSpinner.stop("Card data written");
|
|
66
86
|
}
|
|
67
87
|
catch (err) {
|
|
68
88
|
if (err instanceof Pm3Error) {
|
|
69
|
-
cloneSpinner
|
|
70
|
-
p.log.error(err.message);
|
|
89
|
+
stopWithError(cloneSpinner, err.message);
|
|
71
90
|
if (err.message.includes("not found")) {
|
|
72
91
|
printDoctorHint();
|
|
73
92
|
}
|
|
74
93
|
}
|
|
75
94
|
else {
|
|
76
|
-
cloneSpinner
|
|
77
|
-
p.log.error("Failed to write card data.");
|
|
95
|
+
stopWithError(cloneSpinner, "Failed to write card data.");
|
|
78
96
|
}
|
|
79
97
|
return false;
|
|
80
98
|
}
|
|
@@ -84,27 +102,24 @@ export async function writeAndVerify(card) {
|
|
|
84
102
|
try {
|
|
85
103
|
const cmd = verifyCommand(card);
|
|
86
104
|
const { stdout } = await pm3Exec(cmd);
|
|
87
|
-
const readback = parseLfSearch(stdout);
|
|
105
|
+
const readback = freq === "LF" ? parseLfSearch(stdout) : parseHfSearch(stdout);
|
|
88
106
|
if (readback && readback.id === card.id) {
|
|
89
107
|
verifySpinner.stop("Verification passed — IDs match");
|
|
90
108
|
return true;
|
|
91
109
|
}
|
|
92
110
|
const msg = `Verification failed — readback ID ${readback?.id ?? "not found"} doesn't match ${card.id}. Try again.`;
|
|
93
|
-
verifySpinner
|
|
94
|
-
p.log.error(msg);
|
|
111
|
+
stopWithError(verifySpinner, msg);
|
|
95
112
|
return false;
|
|
96
113
|
}
|
|
97
114
|
catch (err) {
|
|
98
115
|
if (err instanceof Pm3Error) {
|
|
99
|
-
verifySpinner
|
|
100
|
-
p.log.error(err.message);
|
|
116
|
+
stopWithError(verifySpinner, err.message);
|
|
101
117
|
if (err.message.includes("not found")) {
|
|
102
118
|
printDoctorHint();
|
|
103
119
|
}
|
|
104
120
|
}
|
|
105
121
|
else {
|
|
106
|
-
verifySpinner
|
|
107
|
-
p.log.error("Verification readback failed.");
|
|
122
|
+
stopWithError(verifySpinner, "Verification readback failed.");
|
|
108
123
|
}
|
|
109
124
|
return false;
|
|
110
125
|
}
|
package/dist/lib/card-ops.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-ops.js","sourceRoot":"","sources":["../../src/lib/card-ops.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAiB,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"card-ops.js","sourceRoot":"","sources":["../../src/lib/card-ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const CardType: {
|
|
2
|
+
readonly EM410x: "EM410x";
|
|
3
|
+
readonly HID_PROX: "HID Prox";
|
|
4
|
+
readonly MIFARE_CLASSIC_1K: "MIFARE Classic 1K";
|
|
5
|
+
readonly MIFARE_CLASSIC_4K: "MIFARE Classic 4K";
|
|
6
|
+
readonly MIFARE_ULTRALIGHT: "MIFARE Ultralight";
|
|
7
|
+
readonly MIFARE_DESFIRE: "MIFARE DESFire";
|
|
8
|
+
readonly ISO_14443A: "ISO 14443-A";
|
|
9
|
+
};
|
|
10
|
+
export type CardTypeName = (typeof CardType)[keyof typeof CardType];
|
|
11
|
+
export declare function cardFrequency(type: string): "LF" | "HF";
|
|
12
|
+
export declare const Pm3Cmd: {
|
|
13
|
+
readonly LF_SEARCH: "lf search";
|
|
14
|
+
readonly HF_SEARCH: "hf search";
|
|
15
|
+
readonly LF_T55XX_DETECT: "lf t55xx detect";
|
|
16
|
+
readonly LF_EM_410X_READER: "lf em 410x reader";
|
|
17
|
+
readonly LF_HID_READER: "lf hid reader";
|
|
18
|
+
readonly HW_STATUS: "hw status";
|
|
19
|
+
readonly HW_TUNE: "hw tune";
|
|
20
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const CardType = {
|
|
2
|
+
EM410x: "EM410x",
|
|
3
|
+
HID_PROX: "HID Prox",
|
|
4
|
+
MIFARE_CLASSIC_1K: "MIFARE Classic 1K",
|
|
5
|
+
MIFARE_CLASSIC_4K: "MIFARE Classic 4K",
|
|
6
|
+
MIFARE_ULTRALIGHT: "MIFARE Ultralight",
|
|
7
|
+
MIFARE_DESFIRE: "MIFARE DESFire",
|
|
8
|
+
ISO_14443A: "ISO 14443-A",
|
|
9
|
+
};
|
|
10
|
+
export function cardFrequency(type) {
|
|
11
|
+
switch (type) {
|
|
12
|
+
case CardType.EM410x:
|
|
13
|
+
case CardType.HID_PROX:
|
|
14
|
+
return "LF";
|
|
15
|
+
default:
|
|
16
|
+
return "HF";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export const Pm3Cmd = {
|
|
20
|
+
LF_SEARCH: "lf search",
|
|
21
|
+
HF_SEARCH: "hf search",
|
|
22
|
+
LF_T55XX_DETECT: "lf t55xx detect",
|
|
23
|
+
LF_EM_410X_READER: "lf em 410x reader",
|
|
24
|
+
LF_HID_READER: "lf hid reader",
|
|
25
|
+
HW_STATUS: "hw status",
|
|
26
|
+
HW_TUNE: "hw tune",
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACpB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,iBAAiB,EAAE,mBAAmB;IACtC,iBAAiB,EAAE,mBAAmB;IACtC,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,UAAU,EAAE,aAAa;CACnB,CAAC;AAIX,MAAM,UAAU,aAAa,CAAC,IAAY;IACtC,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,QAAQ,CAAC,MAAM,CAAC;QACrB,KAAK,QAAQ,CAAC,QAAQ;YAClB,OAAO,IAAI,CAAC;QAChB;YACI,OAAO,IAAI,CAAC;IACpB,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IAClB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,eAAe,EAAE,iBAAiB;IAClC,iBAAiB,EAAE,mBAAmB;IACtC,aAAa,EAAE,eAAe;IAC9B,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,SAAS;CACZ,CAAC"}
|
package/dist/lib/display.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export declare const BREW_INSTALL_CMD = "brew tap rfidresearchgroup/proxmark3 &&
|
|
|
5
5
|
export declare function printBrewInstall(): void;
|
|
6
6
|
export declare function printCardInfo(card: CardInfo): void;
|
|
7
7
|
export declare function printDoctorHint(): void;
|
|
8
|
+
export declare function printNoSavedTags(): void;
|
|
8
9
|
export declare function printFobNotFound(name: string): void;
|
package/dist/lib/display.js
CHANGED
|
@@ -15,7 +15,10 @@ export function printCardInfo(card) {
|
|
|
15
15
|
export function printDoctorHint() {
|
|
16
16
|
p.log.warn("Run `keyfabe doctor` to diagnose your setup.");
|
|
17
17
|
}
|
|
18
|
+
export function printNoSavedTags() {
|
|
19
|
+
p.log.warn("No saved tags. Use `keyfabe read` or `keyfabe clone` first.");
|
|
20
|
+
}
|
|
18
21
|
export function printFobNotFound(name) {
|
|
19
|
-
p.log.error(`No saved
|
|
22
|
+
p.log.error(`No saved tag named "${name}". Use \`keyfabe list\` to see saved tags.`);
|
|
20
23
|
}
|
|
21
24
|
//# sourceMappingURL=display.js.map
|
package/dist/lib/display.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAGpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,gEAAgE,CAAC;AAEjG,MAAM,UAAU,gBAAgB;IAC5B,CAAC,CAAC,IAAI,CAAC,gBAAgB,EAAE,0BAA0B,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAc;IACxC,MAAM,KAAK,GAAG,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,EAAE,aAAa,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe;IAC3B,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IACzC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,uBAAuB,IAAI,4CAA4C,CAAC,CAAC;AACzF,CAAC"}
|
|
1
|
+
{"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAGpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,gEAAgE,CAAC;AAEjG,MAAM,UAAU,gBAAgB;IAC5B,CAAC,CAAC,IAAI,CAAC,gBAAgB,EAAE,0BAA0B,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAc;IACxC,MAAM,KAAK,GAAG,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,EAAE,aAAa,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe;IAC3B,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC5B,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IACzC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,uBAAuB,IAAI,4CAA4C,CAAC,CAAC;AACzF,CAAC"}
|
package/dist/lib/parsers.d.ts
CHANGED
|
@@ -23,4 +23,5 @@ export declare function parseHwStatus(output: string): HwStatus;
|
|
|
23
23
|
export declare function parseHwTune(output: string): HwTune;
|
|
24
24
|
export declare function parseLfSearch(output: string): CardInfo | null;
|
|
25
25
|
export declare function parseT55xxDetect(output: string): T55xxInfo | null;
|
|
26
|
+
export declare function parseHfSearch(output: string): CardInfo | null;
|
|
26
27
|
export declare function parseCloneResult(output: string): CloneResult;
|
package/dist/lib/parsers.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CardType } from "./constants.js";
|
|
1
2
|
export function parseHwStatus(output) {
|
|
2
3
|
const isStockFirmware = output.includes("unknown command");
|
|
3
4
|
const connected = !isStockFirmware && !output.includes("cannot communicate") && !output.includes("ERROR");
|
|
@@ -22,7 +23,7 @@ export function parseLfSearch(output) {
|
|
|
22
23
|
if (emMatch) {
|
|
23
24
|
const encodingMatch = output.match(/RF\/(\d+)/);
|
|
24
25
|
return {
|
|
25
|
-
type:
|
|
26
|
+
type: CardType.EM410x,
|
|
26
27
|
id: emMatch[1].toUpperCase(),
|
|
27
28
|
encoding: encodingMatch ? `RF/${encodingMatch[1]}` : undefined,
|
|
28
29
|
};
|
|
@@ -31,7 +32,7 @@ export function parseLfSearch(output) {
|
|
|
31
32
|
const hidMatch = output.match(/HID\s*Prox\s*(?:TAG\s*)?ID\s*[:\s]*([0-9A-Fa-f]+)/i);
|
|
32
33
|
if (hidMatch) {
|
|
33
34
|
return {
|
|
34
|
-
type:
|
|
35
|
+
type: CardType.HID_PROX,
|
|
35
36
|
id: hidMatch[1].toUpperCase(),
|
|
36
37
|
};
|
|
37
38
|
}
|
|
@@ -51,6 +52,28 @@ export function parseT55xxDetect(output) {
|
|
|
51
52
|
passwordSet,
|
|
52
53
|
};
|
|
53
54
|
}
|
|
55
|
+
export function parseHfSearch(output) {
|
|
56
|
+
// Extract UID — formats: "UID: AB CD EF 01" or "UID: ABCDEF01" or "UID[4]: AB CD EF 01"
|
|
57
|
+
const uidMatch = output.match(/UID\s*(?:\[\d+\])?\s*[:=]\s*([0-9A-Fa-f]{2}(?:\s+[0-9A-Fa-f]{2})*)/i);
|
|
58
|
+
if (!uidMatch)
|
|
59
|
+
return null;
|
|
60
|
+
const uid = uidMatch[1].replace(/\s+/g, "").toUpperCase();
|
|
61
|
+
// Determine card type from SAK, ATQA, or text
|
|
62
|
+
let type = CardType.ISO_14443A;
|
|
63
|
+
if (/MIFARE\s*Classic.*4K/i.test(output)) {
|
|
64
|
+
type = CardType.MIFARE_CLASSIC_4K;
|
|
65
|
+
}
|
|
66
|
+
else if (/MIFARE\s*Classic/i.test(output)) {
|
|
67
|
+
type = CardType.MIFARE_CLASSIC_1K;
|
|
68
|
+
}
|
|
69
|
+
else if (/MIFARE\s*Ultralight|NTAG/i.test(output)) {
|
|
70
|
+
type = CardType.MIFARE_ULTRALIGHT;
|
|
71
|
+
}
|
|
72
|
+
else if (/MIFARE\s*DESFire/i.test(output)) {
|
|
73
|
+
type = CardType.MIFARE_DESFIRE;
|
|
74
|
+
}
|
|
75
|
+
return { type, id: uid };
|
|
76
|
+
}
|
|
54
77
|
export function parseCloneResult(output) {
|
|
55
78
|
const hasError = /error/i.test(output) && !/errorrate/i.test(output);
|
|
56
79
|
const hasDone = /done/i.test(output) || /written/i.test(output) || /cloned/i.test(output);
|
package/dist/lib/parsers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/prompts.js
CHANGED
|
@@ -20,7 +20,7 @@ export async function promptName() {
|
|
|
20
20
|
const trimmed = value.trim();
|
|
21
21
|
return trimmed || null;
|
|
22
22
|
}
|
|
23
|
-
export async function selectFob(fobs, message = "Select a
|
|
23
|
+
export async function selectFob(fobs, message = "Select a tag") {
|
|
24
24
|
const value = await p.select({
|
|
25
25
|
message,
|
|
26
26
|
options: fobs.map((f) => ({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keyfabe",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CLI tool for Proxmark3
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "CLI tool for Proxmark3 RFID tag cloning",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -13,12 +13,18 @@
|
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=20"
|
|
15
15
|
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/edobry/keyfabe.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/edobry/keyfabe",
|
|
16
21
|
"keywords": [
|
|
17
22
|
"proxmark3",
|
|
18
23
|
"rfid",
|
|
24
|
+
"nfc",
|
|
25
|
+
"mifare",
|
|
19
26
|
"keyfob",
|
|
20
|
-
"clone"
|
|
21
|
-
"nfc"
|
|
27
|
+
"clone"
|
|
22
28
|
],
|
|
23
29
|
"scripts": {
|
|
24
30
|
"dev": "tsx src/index.ts",
|