forked from queengooborg/Bambu-Lab-RFID-Library
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrepair.py
More file actions
79 lines (58 loc) · 2.42 KB
/
repair.py
File metadata and controls
79 lines (58 loc) · 2.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# -*- coding: utf-8 -*-
# Python script to repair any Bambu Lab RFID tag dumps without keys
# Created for https://github.com/queengooborg/Bambu-Lab-RFID-Library
# Written by Vinyl Da.i'gyu-Kazotetsu (www.queengoob.org), 2026
# Requires: pycryptodome
import sys
from pathlib import Path
from Crypto.Protocol.KDF import HKDF
from Crypto.Hash import SHA256
from parse import BYTES_PER_BLOCK, BLOCKS_PER_SECTOR, TOTAL_SECTORS, TOTAL_BYTES
INVALID_KEYS = [b"\xFF" * 6, b"\x00" * 6]
# Function copied from https://github.com/queengooborg/Bambu-Lab-RFID-Tag-Guide/blob/main/deriveKeys.py
def kdf(uid):
salt = bytes([0x9a,0x75,0x9c,0xf2,0xc4,0xf7,0xca,0xff,0x22,0x2c,0xb9,0x76,0x9b,0x41,0xbc,0x96])
return HKDF(uid, 6, salt, SHA256, 16, context=b"RFID-A\0") + HKDF(uid, 6, salt, SHA256, 16, context=b"RFID-B\0")
def sector_trailer_offset(sector):
block_index = sector * BLOCKS_PER_SECTOR + 3
return block_index * BYTES_PER_BLOCK
def extract_uid(dump):
return dump[0:4]
def is_invalid_key(key):
return bytes(key) in INVALID_KEYS
def repair_keys_in_place(path):
dump_bytes = path.read_bytes()
if len(dump_bytes) not in TOTAL_BYTES:
raise ValueError(f"{path} is not a 1K MIFARE Classic dump")
dump = bytearray(dump_bytes)
uid = extract_uid(dump)
print(f"\nFile : {path}")
print(f"UID : {uid.hex()}")
keys = kdf(uid)
if len(keys) != 32:
raise ValueError("KDF did not return 32 keys")
changes = 0
for sector in range(TOTAL_SECTORS):
trailer = sector_trailer_offset(sector)
key_a = dump[trailer : trailer + 6]
key_b = dump[trailer + 10 : trailer + 16]
derived_a = keys[sector]
derived_b = keys[16 + sector]
if is_invalid_key(key_a):
dump[trailer : trailer + 6] = derived_a
changes += 1
print(f" Sector {sector:02d} Key A repaired → {derived_a.hex()}")
if is_invalid_key(key_b):
dump[trailer + 10 : trailer + 16] = derived_b
changes += 1
print(f" Sector {sector:02d} Key B repaired → {derived_b.hex()}")
if changes:
path.write_bytes(dump)
print(f"\n{changes} key(s) repaired — file updated in place.")
else:
print("\nNo repairs needed — file left unchanged.")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: repair.py <dumpfile>")
sys.exit(1)
repair_keys_in_place(Path(sys.argv[1]))