keyfabe 0.3.0 → 0.4.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 CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  A TypeScript CLI tool that wraps the Proxmark3 client to provide an ergonomic keyfob cloning workflow.
4
4
 
5
+ <p align="center">
6
+ <img src="demo.gif" alt="keyfabe demo" width="800" />
7
+ </p>
8
+
5
9
  ## What it does
6
10
 
7
11
  - Automates the multi-step read/detect/clone/verify process into a single guided flow
@@ -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
 
@@ -49,19 +58,19 @@ keyfabe clone
49
58
  keyfabe read
50
59
 
51
60
  # write a previously-saved identity to a blank fob
52
- keyfabe write <name>
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 <name>
67
+ keyfabe show [name]
59
68
 
60
69
  # rename a saved identity
61
- keyfabe rename <old-name> <new-name>
70
+ keyfabe rename [old-name] [new-name]
62
71
 
63
72
  # delete a saved identity
64
- keyfabe delete <name>
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 fob picker.
83
+
73
84
  ## Commands
74
85
 
75
86
  ### `keyfabe doctor`
@@ -88,25 +99,25 @@ Guided clone flow: reads the original fob, detects a blank T55x7, writes the ID,
88
99
 
89
100
  Reads and identifies whatever fob is on the antenna. Supports EM410x and HID Prox. Optionally saves the identity.
90
101
 
91
- ### `keyfabe write <name>`
102
+ ### `keyfabe write [name]`
92
103
 
93
- Writes a previously-saved identity to a blank T55x7 fob.
104
+ Writes a previously-saved identity to a blank T55x7 fob. Without a name, presents an interactive picker.
94
105
 
95
106
  ### `keyfabe list`
96
107
 
97
108
  Lists all saved fob identities from `~/.keyfabe/fobs.json`.
98
109
 
99
- ### `keyfabe show <name>`
110
+ ### `keyfabe show [name]`
100
111
 
101
- Displays full details of a saved fob identity (type, ID, encoding, save date).
112
+ Displays full details of a saved fob identity (type, ID, encoding, save date). Without a name, presents an interactive picker.
102
113
 
103
- ### `keyfabe rename <old-name> <new-name>`
114
+ ### `keyfabe rename [old-name] [new-name]`
104
115
 
105
- Renames a saved fob identity.
116
+ Renames a saved fob identity. Missing arguments are prompted interactively.
106
117
 
107
- ### `keyfabe delete <name>`
118
+ ### `keyfabe delete [name]`
108
119
 
109
- Deletes a saved fob identity.
120
+ Deletes a saved fob identity. Without a name, presents an interactive picker.
110
121
 
111
122
  ### `keyfabe export`
112
123
 
@@ -1,7 +1,7 @@
1
1
  import * as p from "@clack/prompts";
2
2
  import { writeAndVerify } from "../lib/card-ops.js";
3
3
  import { printCardInfo, printDoctorHint } from "../lib/display.js";
4
- import { parseLfSearch } from "../lib/parsers.js";
4
+ import { parseHfSearch, parseLfSearch } from "../lib/parsers.js";
5
5
  import { Pm3Error, pm3Exec, requireDevice } from "../lib/pm3.js";
6
6
  import { promptName, waitForEnter } from "../lib/prompts.js";
7
7
  import { saveFob } from "../lib/store.js";
@@ -45,9 +45,32 @@ export async function clone() {
45
45
  await new Promise((r) => setTimeout(r, READ_RETRY_DELAY));
46
46
  }
47
47
  }
48
+ // If LF search failed, try HF
48
49
  if (!card) {
49
- p.log.error("Failed to read original card after all attempts.");
50
- return false;
50
+ const hfSpinner = p.spinner();
51
+ hfSpinner.start("No LF card found, trying HF...");
52
+ try {
53
+ const { stdout } = await pm3Exec("hf search");
54
+ const hfCard = parseHfSearch(stdout);
55
+ if (hfCard) {
56
+ hfSpinner.stop("HF card detected");
57
+ printCardInfo(hfCard);
58
+ p.log.warn(`HF card cloning (${hfCard.type}) is not yet supported. Only LF keyfobs (EM410x, HID Prox) can be cloned.`);
59
+ return false;
60
+ }
61
+ }
62
+ catch (err) {
63
+ if (err instanceof Pm3Error) {
64
+ hfSpinner.stop(err.message);
65
+ }
66
+ else {
67
+ hfSpinner.stop("HF search failed.");
68
+ }
69
+ }
70
+ if (!card) {
71
+ p.log.error("Failed to read original card after all attempts.");
72
+ return false;
73
+ }
51
74
  }
52
75
  printCardInfo(card);
53
76
  // Step 2: Write to blank
@@ -1 +1 @@
1
- {"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/commands/clone.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/commands/clone.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import * as p from "@clack/prompts";
2
2
  import { printCardInfo, printDoctorHint } from "../lib/display.js";
3
- import { parseLfSearch } from "../lib/parsers.js";
3
+ import { parseHfSearch, parseLfSearch } from "../lib/parsers.js";
4
4
  import { Pm3Error, pm3Exec, requireDevice } from "../lib/pm3.js";
5
5
  import { promptName } from "../lib/prompts.js";
6
6
  import { saveFob } from "../lib/store.js";
@@ -26,11 +26,33 @@ export async function read() {
26
26
  }
27
27
  }
28
28
  if (!card) {
29
- s.stop("No card detected. Make sure the fob is flat against the antenna.");
30
- p.log.error("No card detected. Make sure the fob is flat against the antenna.");
31
- return false;
29
+ s.stop("No LF card found, trying HF...");
30
+ const hf = p.spinner();
31
+ hf.start("Searching for card (HF)...");
32
+ try {
33
+ const { stdout } = await pm3Exec("hf search");
34
+ card = parseHfSearch(stdout);
35
+ }
36
+ catch (err) {
37
+ if (err instanceof Pm3Error) {
38
+ hf.stop(err.message);
39
+ p.log.error(err.message);
40
+ if (err.message.includes("not found")) {
41
+ printDoctorHint();
42
+ }
43
+ return false;
44
+ }
45
+ }
46
+ if (!card) {
47
+ hf.stop("No card detected. Make sure the card is flat against the antenna.");
48
+ p.log.error("No card detected. Make sure the card is flat against the antenna.");
49
+ return false;
50
+ }
51
+ hf.stop("Card detected");
52
+ }
53
+ else {
54
+ s.stop("Card detected");
32
55
  }
33
- s.stop("Card detected");
34
56
  printCardInfo(card);
35
57
  // Prompt to save
36
58
  const name = await promptName();
@@ -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,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACjE,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,WAAW,CAAC,CAAC;IAErB,IAAI,IAAI,GAAqC,IAAI,CAAC;IAElD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IACtC,IAAI,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACjC,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;YACD,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,CAAC,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAC3E,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACxB,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,iBAAiB;IACjB,MAAM,IAAI,GAAG,MAAM,UAAU,EAAE,CAAC;IAChC,IAAI,IAAI,EAAE,CAAC;QACP,MAAM,OAAO,CAAC;YACV,IAAI;YACJ,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;QACH,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/commands/read.ts"],"names":[],"mappings":"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"}
@@ -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;
@@ -51,6 +51,28 @@ export function parseT55xxDetect(output) {
51
51
  passwordSet,
52
52
  };
53
53
  }
54
+ export function parseHfSearch(output) {
55
+ // Extract UID — formats: "UID: AB CD EF 01" or "UID: ABCDEF01" or "UID[4]: AB CD EF 01"
56
+ const uidMatch = output.match(/UID\s*(?:\[\d+\])?\s*[:=]\s*([0-9A-Fa-f]{2}(?:\s+[0-9A-Fa-f]{2})*)/i);
57
+ if (!uidMatch)
58
+ return null;
59
+ const uid = uidMatch[1].replace(/\s+/g, "").toUpperCase();
60
+ // Determine card type from SAK, ATQA, or text
61
+ let type = "ISO 14443-A";
62
+ if (/MIFARE\s*Classic.*4K/i.test(output)) {
63
+ type = "MIFARE Classic 4K";
64
+ }
65
+ else if (/MIFARE\s*Classic/i.test(output)) {
66
+ type = "MIFARE Classic 1K";
67
+ }
68
+ else if (/MIFARE\s*Ultralight|NTAG/i.test(output)) {
69
+ type = "MIFARE Ultralight";
70
+ }
71
+ else if (/MIFARE\s*DESFire/i.test(output)) {
72
+ type = "MIFARE DESFire";
73
+ }
74
+ return { type, id: uid };
75
+ }
54
76
  export function parseCloneResult(output) {
55
77
  const hasError = /error/i.test(output) && !/errorrate/i.test(output);
56
78
  const hasDone = /done/i.test(output) || /written/i.test(output) || /cloned/i.test(output);
@@ -1 +1 @@
1
- {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyfabe",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI tool for Proxmark3 keyfob cloning",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -13,6 +13,11 @@
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",