docs(rfid): Add multi-protocol RFID system planning & review

Created comprehensive planning for adding multiple RFID protocols with
different security levels and attack capabilities.

Planning Documents:
- 00_IMPLEMENTATION_SUMMARY.md: Complete implementation guide (14h estimate)
- 01_TECHNICAL_DESIGN.md: Protocol specs, data models, UI design
- 02_IMPLEMENTATION_PLAN.md: Detailed file-by-file implementation plan
- CRITICAL_REVIEW.md: Pre-implementation review with 12 improvements

Protocol System (Simplified from Original):
 EM4100 (low security) - Instant clone, already implemented
 MIFARE Classic (medium) - Requires key attacks (Darkside/Nested/Dictionary)
 MIFARE DESFire (high) - UID only, forces physical theft
 HID Prox - Removed (too similar to EM4100, saves 2h)

Key Features:
- Protocol detection with color-coded security levels
- MIFARE key cracking minigames (30s Darkside, 10s Nested, instant Dictionary)
- Ink integration for conditional interactions based on card protocol
- Dual format support (no migration needed)
- UID-only emulation for DESFire with acceptsUIDOnly door property

Review Improvements Applied:
- Merged "attack mode" into clone mode (simpler state machine)
- Removed firmware upgrade system (can add later)
- Dual format card data support instead of migration (safer)
- Added error handling for unsupported protocols
- Added cleanup for background attacks
- Documented required Ink variables

Time Estimate: 14 hours (down from 19h)
- Phase 1: Protocol Foundation (3h)
- Phase 2: Protocol Detection & UI (3h)
- Phase 3: MIFARE Attack System (5h)
- Phase 4: Ink Integration (2h)
- Phase 5: Door Integration & Testing (1h)

Next Steps: Begin implementation starting with Phase 1
This commit is contained in:
Z. Cliffe Schreuders
2025-11-15 23:48:15 +00:00
parent 0210a12c64
commit d697eef3ca
4 changed files with 3957 additions and 0 deletions

View File

@@ -0,0 +1,708 @@
# RFID Protocols & Interactions - Technical Design
## Overview
Add support for multiple RFID protocols with different security levels and capabilities. Each protocol has realistic constraints based on real-world RFID technology, enabling different attack vectors and gameplay strategies.
## Protocol Specifications
### Protocol Definitions
Based on real-world RFID technology used in access control systems:
```javascript
const RFID_PROTOCOLS = {
'EM4100': {
name: 'EM-Micro EM4100',
frequency: '125kHz',
security: 'low',
readOnly: true,
capabilities: {
read: true,
clone: true,
write: false,
emulate: true,
bruteforce: false // Too many combinations
},
description: 'Legacy low-frequency card. Read-only, easily cloned.',
vulnerabilities: ['Clone attack', 'Replay attack'],
hexLength: 10, // 5 bytes
color: '#FF6B6B' // Red for low security
},
'HID_Prox': {
name: 'HID Prox II',
frequency: '125kHz',
security: 'medium-low',
readOnly: true,
capabilities: {
read: true,
clone: true,
write: false,
emulate: true,
bruteforce: false
},
description: 'Common corporate badge. Read-only, proprietary format.',
vulnerabilities: ['Clone attack', 'Replay attack'],
hexLength: 12, // 6 bytes (26-bit format)
color: '#FFA500' // Orange for medium-low
},
'MIFARE_Classic': {
name: 'MIFARE Classic 1K',
frequency: '13.56MHz',
security: 'medium',
readOnly: false,
capabilities: {
read: 'with-keys', // Need auth keys
clone: 'with-keys',
write: 'with-keys',
emulate: true,
bruteforce: true // Weak crypto, can crack keys
},
description: 'Encrypted NFC card. Requires authentication keys.',
vulnerabilities: ['Darkside attack', 'Nested attack', 'Hardnested attack'],
sectors: 16,
keysPerSector: 2, // Key A and Key B
hexLength: 8, // UID is 4 bytes
color: '#4ECDC4' // Teal for medium
},
'MIFARE_DESFire': {
name: 'MIFARE DESFire EV2',
frequency: '13.56MHz',
security: 'high',
readOnly: false,
capabilities: {
read: false, // Encrypted, can't read without master key
clone: false, // Can't clone - uses mutual authentication
write: false, // Can't write without master key
emulate: 'uid-only', // Can only emulate UID, not full card
bruteforce: false // Strong crypto (3DES/AES)
},
description: 'High-security encrypted NFC. Nearly impossible to clone.',
vulnerabilities: ['Physical theft only'],
hexLength: 14, // 7-byte UID
color: '#95E1D3' // Light green for high security
}
};
```
## Data Model Changes
### Card Data Structure
**Current** (EM4100 only):
```javascript
{
type: "keycard",
name: "Employee Badge",
rfid_hex: "01AB34CD56",
rfid_facility: 1,
rfid_card_number: 43981,
rfid_protocol: "EM4100",
key_id: "employee_badge"
}
```
**Enhanced** (all protocols):
```javascript
{
type: "keycard",
name: "Employee Badge",
rfid_protocol: "EM4100", // or HID_Prox, MIFARE_Classic, MIFARE_DESFire
key_id: "employee_badge",
// Protocol-specific data (only relevant fields per protocol)
rfid_data: {
// EM4100 / HID Prox
hex: "01AB34CD56",
facility: 1,
cardNumber: 43981,
// MIFARE Classic (if applicable)
uid: "AB12CD34",
sectors: {
0: { keyA: "FFFFFFFFFFFF", keyB: null }, // Default key
1: { keyA: "A1B2C3D4E5F6", keyB: "123456789ABC" }, // Custom keys
// ... more sectors
},
// MIFARE DESFire (if applicable)
uid: "04AB12CD3456E0",
masterKeyKnown: false, // Can't clone without this
// Clone quality (for cloned cards)
isClone: false,
cloneQuality: 100, // 0-100, affects reliability
clonedFrom: null // Original card ID
},
observations: "Standard employee access badge."
}
```
### RFID Cloner Data Structure
```javascript
{
type: "rfid_cloner",
name: "Flipper Zero",
// Firmware capabilities (can be upgraded in-game)
firmware: {
version: "1.0",
protocols: ['EM4100', 'HID_Prox'], // Unlocks MIFARE support later
attacks: ['read', 'clone', 'emulate'] // Unlocks 'bruteforce' later
},
saved_cards: [
// Array of card data objects
],
// Cracking progress (for MIFARE Classic key attacks)
activeAttacks: {
"security_badge_uid_AB12CD34": {
type: "darkside_attack",
protocol: "MIFARE_Classic",
progress: 45, // 0-100%
sector: 3,
foundKeys: {
0: { keyA: "FFFFFFFFFFFF" },
1: { keyA: "A1B2C3D4E5F6" }
}
}
},
x: 350,
y: 250,
takeable: true,
observations: "Portable multi-tool for pentesters. Can read and emulate RFID cards."
}
```
## Flipper Zero Operations by Protocol
### EM4100 / HID Prox Operations
**1. Read**
- Instant read, shows all data
- No authentication needed
- UI: Standard reading screen (already implemented)
**2. Clone**
- Instant clone, perfect copy
- UI: Progress bar → Card data → Save
**3. Emulate**
- Perfect emulation
- UI: Emulation screen (already implemented)
### MIFARE Classic Operations
**1. Read (requires keys)**
```
Decision Tree:
├─ Has all keys for all sectors?
│ ├─ Yes → Read full card data
│ └─ No → Show partial data, offer key attack
└─ Has NO keys?
└─ Offer Darkside/Nested attack to crack keys
```
**2. Clone (requires keys)**
- Can only clone sectors where keys are known
- Partial clones possible (some sectors locked)
**3. Key Attacks**
- **Darkside Attack**: Crack keys from scratch (~30 seconds realistic)
- **Nested Attack**: Crack remaining keys if you have one key (~10 seconds)
- **Dictionary Attack**: Try common keys (instant check)
**4. Write**
- Modify card data in writable sectors
- Useful for:
- Changing balance on payment cards
- Modifying access permissions
- Writing cloned data to blank cards
**5. Emulate**
- Can emulate if keys are known
- UI shows which sectors are available
### MIFARE DESFire Operations
**1. Read**
- Can only read UID (no encryption keys)
- Cannot read application data
**2. UID Emulation**
- Can emulate UID only
- Some systems check UID only (lower security)
- Higher security systems use encrypted challenge-response (emulation fails)
**3. No Clone/Write**
- Strong encryption prevents cloning
- Game design: These cards must be physically stolen or access granted through social engineering
## UI Design
### Protocol Detection Screen
New screen when reading a card for the first time:
```
╔════════════════════════════════════╗
║ FLIPPER ZERO ⚡ 100% ║
╠════════════════════════════════════╣
║ ║
║ RFID > Read ║
║ ║
║ Detecting... ║
║ ║
║ ┌────────────────────────────────┐║
║ │ 📡 │║
║ │ │║
║ │ [Progress Bar 65%] │║
║ └────────────────────────────────┘║
║ ║
║ Scanning frequencies... ║
║ 125kHz: No response ║
║ 13.56MHz: Card detected! ║
║ ║
╚════════════════════════════════════╝
```
### Protocol Info Screen
After detection:
```
╔════════════════════════════════════╗
║ FLIPPER ZERO ⚡ 100% ║
╠════════════════════════════════════╣
║ ║
║ RFID > Read > Info ║
║ ║
║ ┌────────────────────────────────┐║
║ │ MIFARE Classic 1K │║
║ │ ────────────────── │║
║ │ Freq: 13.56MHz │║
║ │ Security: Medium │║
║ │ UID: AB 12 CD 34 │║
║ └────────────────────────────────┘║
║ ║
║ This card uses encryption. ║
║ Authentication keys required. ║
║ ║
║ > Read (requires keys) ║
║ Crack Keys ║
║ Try Dictionary ║
║ Cancel ║
║ ║
╚════════════════════════════════════╝
```
### Key Cracking Screen (MIFARE Classic)
```
╔════════════════════════════════════╗
║ FLIPPER ZERO ⚡ 95% ║
╠════════════════════════════════════╣
║ ║
║ RFID > Darkside Attack ║
║ ║
║ Security Badge ║
║ UID: AB 12 CD 34 ║
║ ║
║ ┌────────────────────────────────┐║
║ │ Cracking Sector 3... │║
║ │ ████████████░░░░░░░░ 65% │║
║ └────────────────────────────────┘║
║ ║
║ Keys Found: ║
║ Sector 0: FF FF FF FF FF FF ✓ ║
║ Sector 1: A1 B2 C3 D4 E5 F6 ✓ ║
║ Sector 2: 12 34 56 78 9A BC ✓ ║
║ Sector 3: Cracking... ║
║ ║
║ Don't move card... ║
║ ║
╚════════════════════════════════════╝
```
### Card Data Screen with Protocol-Specific Fields
**EM4100:**
```
╔════════════════════════════════════╗
║ RFID > Read ║
║ ║
║ EM-Micro EM4100 ║
║ ║
║ HEX: 01 AB 34 CD 56 ║
║ Facility: 1 ║
║ Card: 43981 ║
║ Checksum: 0xD6 ║
║ DEZ 8: 00043981 ║
║ ║
║ [Save] [Cancel] ║
╚════════════════════════════════════╝
```
**MIFARE Classic (with keys):**
```
╔════════════════════════════════════╗
║ RFID > Read ║
║ ║
║ MIFARE Classic 1K ║
║ ║
║ UID: AB 12 CD 34 ║
║ SAK: 08 ║
║ ATQA: 00 04 ║
║ ║
║ Sectors: 16 ║
║ Keys Known: 16/16 ✓ ║
║ ║
║ Readable: Yes ║
║ Writable: Yes ║
║ Clonable: Yes ║
║ ║
║ [Save] [View Data] [Cancel] ║
╚════════════════════════════════════╝
```
**MIFARE DESFire (limited):**
```
╔════════════════════════════════════╗
║ RFID > Read ║
║ ║
║ MIFARE DESFire EV2 ║
║ ║
║ UID: 04 AB 12 CD 34 56 E0 ║
║ SAK: 20 ║
║ ATQA: 03 44 ║
║ ║
║ ⚠️ High Security ║
║ ║
║ This card uses 3DES encryption. ║
║ Full clone: Not possible ║
║ UID emulation: Possible ║
║ ║
║ Some systems only check UID and ║
║ don't use encryption properly. ║
║ ║
║ [Save UID] [Cancel] ║
╚════════════════════════════════════╝
```
## Ink Integration
### Exposing Card Protocol Info to Ink
When NPC conversation starts, sync card protocol information:
```javascript
// In person-chat-conversation.js, extend syncItemsToInk()
syncCardProtocolsToInk() {
if (!this.inkEngine || !this.npc || !this.npc.itemsHeld) return;
// Find all keycards held by NPC
const keycards = this.npc.itemsHeld.filter(item => item.type === 'keycard');
keycards.forEach((card, index) => {
const protocol = card.rfid_protocol || 'EM4100';
const prefix = index === 0 ? 'card' : `card${index + 1}`;
// Set variables for this card
this.inkEngine.setVariable(`${prefix}_protocol`, protocol);
this.inkEngine.setVariable(`${prefix}_name`, card.name);
this.inkEngine.setVariable(`${prefix}_security`, RFID_PROTOCOLS[protocol].security);
this.inkEngine.setVariable(`${prefix}_clonable`, RFID_PROTOCOLS[protocol].capabilities.clone === true);
});
}
```
### Ink Variable Usage
```ink
VAR card_protocol = ""
VAR card_name = ""
VAR card_security = ""
VAR card_clonable = false
=== guard_conversation ===
# speaker:npc
I've got my security badge right here on my lanyard.
{card_protocol == "EM4100":
-> easy_clone
}
{card_protocol == "MIFARE_Classic":
-> needs_key_attack
}
{card_protocol == "MIFARE_DESFire":
-> impossible_clone
}
=== easy_clone ===
+ [Subtly scan the badge]
# clone_keycard:{card_name}|{card_hex}
You discretely position your Flipper near their badge.
-> cloned
=== needs_key_attack ===
+ [Scan the badge]
You scan the badge but it's encrypted...
# start_mifare_attack:{card_name}|{card_uid}
Your Flipper starts a Darkside attack.
-> wait_for_crack
+ [Ask to borrow it for a minute]
-> borrow_card_choice
=== impossible_clone ===
+ [Try to scan the badge]
# speaker:player
You position your Flipper near their badge.
# speaker:npc
You can only capture the UID. This card uses strong encryption - you can't clone it without the master key.
# save_uid_only:{card_name}|{card_uid}
-> uid_saved
+ [Ask if you can borrow it]
This is your only option. You'll need the physical card.
-> borrow_card_choice
```
### New Ink Tags
#### `# start_mifare_attack:CardName|UID`
Starts a MIFARE Classic key cracking attack in the background.
```javascript
case 'start_mifare_attack':
if (param) {
const [cardName, uid] = param.split('|');
// Check for Flipper
const cloner = window.inventory.items.find(item =>
item?.scenarioData?.type === 'rfid_cloner'
);
if (!cloner) {
result.message = '⚠️ Need RFID cloner';
break;
}
// Check firmware supports MIFARE
if (!cloner.scenarioData.firmware.protocols.includes('MIFARE_Classic')) {
result.message = '⚠️ Firmware upgrade needed for MIFARE attacks';
break;
}
// Start background attack
startMIFAREAttack(cardName, uid, cloner);
result.success = true;
result.message = `🔓 Started Darkside attack on ${cardName}`;
}
break;
```
#### `# check_attack_complete:CardUID`
Check if background attack finished (can use in conditional choice):
```ink
=== wait_for_crack ===
# speaker:npc
So anyway, as I was saying about the weekend plans...
{check_attack_complete(card_uid):
+ [Your Flipper vibrates - attack complete!]
# speaker:player
(Your Flipper successfully cracked the keys!)
# clone_mifare:{card_name}|{card_uid}
-> cloned
- else:
+ [Continue chatting]
-> keep_waiting
}
```
#### `# clone_mifare:CardName|UID`
Clone a MIFARE card (requires keys to be cracked first):
```javascript
case 'clone_mifare':
if (param) {
const [cardName, uid] = param.split('|');
const cloner = window.inventory.items.find(item =>
item?.scenarioData?.type === 'rfid_cloner'
);
// Check if we have the keys
const attack = cloner?.scenarioData?.activeAttacks?.[`uid_${uid}`];
if (!attack || attack.progress < 100) {
result.message = '⚠️ Keys not yet cracked';
break;
}
// Launch RFID minigame in clone mode with MIFARE data
window.pendingConversationReturn = {
npcId: window.currentConversationNPCId,
type: window.currentConversationMinigameType || 'person-chat'
};
window.startRFIDMinigame(null, null, {
mode: 'clone',
protocol: 'MIFARE_Classic',
cardToClone: {
name: cardName,
rfid_protocol: 'MIFARE_Classic',
rfid_data: {
uid: uid,
sectors: attack.foundKeys
},
type: 'keycard',
key_id: `cloned_${uid.toLowerCase()}`
}
});
}
break;
```
#### `# save_uid_only:CardName|UID`
Save only UID for DESFire cards (can't clone full card):
```javascript
case 'save_uid_only':
if (param) {
const [cardName, uid] = param.split('|');
window.pendingConversationReturn = {
npcId: window.currentConversationNPCId,
type: window.currentConversationMinigameType || 'person-chat'
};
window.startRFIDMinigame(null, null, {
mode: 'clone',
protocol: 'MIFARE_DESFire',
uidOnly: true,
cardToClone: {
name: cardName + " (UID Only)",
rfid_protocol: 'MIFARE_DESFire',
rfid_data: {
uid: uid,
masterKeyKnown: false
},
type: 'keycard',
key_id: `uid_${uid.toLowerCase()}`,
observations: "⚠️ UID only - may not work on secure readers"
}
});
}
break;
```
## Implementation Phases
This feature can be implemented incrementally:
### Phase 1: Protocol Data Model (Foundation)
1. Add RFID_PROTOCOLS constant
2. Update card data structure to support rfid_data
3. Update cloner to support firmware capabilities
4. Backward compatibility for existing EM4100 cards
### Phase 2: Protocol Detection & Display
1. Add protocol detection logic in rfid-data.js
2. Create protocol info UI screen
3. Update card data display to show protocol-specific fields
4. Color coding by security level
### Phase 3: MIFARE Classic Support
1. Implement key attack minigame screens
2. Add background attack system
3. Add dictionary attack (common keys)
4. Partial clone support (some sectors)
### Phase 4: MIFARE DESFire Support
1. UID-only save functionality
2. Emulation with warning messages
3. Physical theft/social engineering paths
### Phase 5: Ink Integration
1. Extend syncItemsToInk for protocol variables
2. Implement new Ink tags
3. Add conditional attack options
4. Create example scenarios
### Phase 6: HID Prox Support
1. Add HID-specific data format
2. Facility code + card number extraction
3. UI for HID cards
## Testing Plan
### Unit Tests
- Protocol detection from card data
- Capability checks per protocol
- Key cracking simulation
- UID extraction
### Integration Tests
- Clone EM4100 (should work instantly)
- Clone HID Prox (should work instantly)
- Attempt clone MIFARE Classic without keys (should fail/offer attack)
- Attack MIFARE Classic (should eventually succeed)
- Attempt clone DESFire (should only get UID)
- Emulate UID-only DESFire against simple reader (should work)
- Emulate UID-only DESFire against secure reader (should fail)
### Scenario Tests
Create test scenarios for each protocol:
- `test-rfid-em4100.json` (current)
- `test-rfid-hid-prox.json`
- `test-rfid-mifare-classic.json`
- `test-rfid-mifare-desfire.json`
## Backward Compatibility
Existing EM4100 cards continue to work:
```javascript
// Old format (still works)
{
type: "keycard",
rfid_hex: "01AB34CD56",
rfid_facility: 1,
rfid_card_number: 43981,
rfid_protocol: "EM4100"
}
// Automatically migrated to:
{
type: "keycard",
rfid_protocol: "EM4100",
rfid_data: {
hex: "01AB34CD56",
facility: 1,
cardNumber: 43981
}
}
```
Migration happens transparently when cards are loaded.
## Performance Considerations
- Protocol detection: Instant (client-side lookup)
- Key attacks: Simulated with setTimeout (no real crypto)
- Background attacks: Store in gameState, check on game loop
- No actual network calls or heavy computation

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,526 @@
# RFID Protocols Implementation Plan - Critical Review
**Review Date**: Current Session
**Reviewer**: Claude (Self-Review)
**Status**: Pre-Implementation Analysis
## Executive Summary
The implementation plan is **comprehensive and technically sound**, but has several areas that can be **simplified and improved** for better development efficiency and gameplay value. This review identifies 12 key improvements organized by priority.
## High Priority Issues
### Issue #1: HID Prox Adds Minimal Gameplay Value
**Problem**: HID Prox is nearly identical to EM4100 from a gameplay perspective:
- Both are 125kHz read-only cards
- Both clone instantly
- Only difference is hex length (10 vs 12 chars)
- Both have same vulnerabilities and capabilities
**Impact**: Development time spent on HID Prox doesn't add meaningful gameplay variety.
**Recommendation**: **Remove HID Prox from initial implementation**.
- Focus on three distinct protocols: EM4100 (easy), MIFARE Classic (medium), MIFARE DESFire (hard)
- Can add HID Prox later if needed (it's trivial to add)
- Saves ~2 hours of implementation and testing time
**Updated Protocol Set**:
```javascript
const RFID_PROTOCOLS = {
'EM4100': 'low', // Always works
'MIFARE_Classic': 'medium', // Requires key attacks
'MIFARE_DESFire': 'high' // UID only, physical theft needed
};
```
---
### Issue #2: Attack Mode vs Clone Mode Confusion
**Problem**: Plan introduces separate "attack" mode:
```javascript
if (this.mode === 'attack') {
this.ui.createAttackInterface();
}
```
This creates confusion:
- What's the difference between attack mode and clone mode?
- After attack succeeds, do you still need to clone?
- Two separate code paths for similar functionality
**Recommendation**: **Merge attack into clone mode**.
**Better Flow**:
```
Clone Mode Start
├─ Detect protocol
├─ EM4100? → Read & Clone instantly
├─ MIFARE Classic?
│ ├─ Has keys? → Read & Clone
│ └─ No keys? → Show attack options → Run attack → Then clone
└─ MIFARE DESFire? → Save UID only
```
**Implementation**:
```javascript
// In clone mode
if (this.mode === 'clone') {
const protocol = this.detectProtocol(this.cardToClone);
if (protocol === 'MIFARE_Classic') {
const hasKeys = this.hasAllKeys(this.cardToClone);
if (!hasKeys) {
// Show protocol info with attack options
this.ui.showProtocolInfo(this.cardToClone);
// User clicks "Darkside Attack"
// Attack runs in same minigame instance
// After attack completes, show card data and save
} else {
// Has keys, proceed to clone normally
this.ui.showReadingScreen();
}
}
}
```
Simplifies state machine and makes flow more intuitive.
---
### Issue #3: Incomplete Firmware Upgrade System
**Problem**: Plan mentions firmware but doesn't implement it:
```javascript
firmware: {
version: "1.0",
protocols: ["EM4100", "HID_Prox"],
attacks: ["read", "clone", "emulate"]
}
```
But no code for:
- How to upgrade firmware
- Where to find upgrades
- What triggers availability
**Recommendation**: **Either fully implement or remove firmware system**.
**Option A - Remove (Simpler)**:
- All protocols always available
- Flipper Zero in game has latest firmware pre-installed
- Saves implementation time
**Option B - Full Implementation** (if player progression needed):
```javascript
// Firmware upgrade item in scenario
{
"type": "firmware_update",
"name": "Flipper Firmware v1.2 (MIFARE Support)",
"upgrades_protocols": ["MIFARE_Classic"],
"upgrades_attacks": ["darkside", "nested"]
}
// In interactions.js - when using firmware update
if (item.type === 'firmware_update') {
const cloner = getFlipperFromInventory();
cloner.firmware.protocols.push(...item.upgrades_protocols);
cloner.firmware.attacks.push(...item.upgrades_attacks);
showMessage("Firmware updated!");
}
```
**Recommendation**: Use Option A for initial implementation. Add firmware upgrades later if progression system is needed.
---
### Issue #4: Card Data Migration Incomplete
**Problem**: Migration only handles EM4100:
```javascript
if (protocol === 'EM4100' || protocol === 'HID_Prox') {
return {
...cardData,
rfid_data: {
hex: cardData.rfid_hex,
// ...
}
};
}
return cardData; // What about other protocols?
```
**Recommendation**: **Complete migration for all protocols or use simpler approach**.
**Better Approach** - Dual Format Support:
```javascript
// Support both old and new formats transparently
getRFIDHex(cardData) {
// New format
if (cardData.rfid_data?.hex) {
return cardData.rfid_data.hex;
}
// Old format (backward compat)
if (cardData.rfid_hex) {
return cardData.rfid_hex;
}
return null;
}
getRFIDUID(cardData) {
if (cardData.rfid_data?.uid) {
return cardData.rfid_data.uid;
}
return null;
}
```
No migration needed - just read from either location. Simpler and safer.
---
### Issue #5: Protocol Detection in Clone Mode Not Addressed
**Problem**: Plan shows protocol detection for reading cards, but what about clone mode?
When clone mode starts with `cardToClone` parameter:
```javascript
window.startRFIDMinigame(null, null, {
mode: 'clone',
cardToClone: someCard
});
```
The card already has data - no need to "detect" protocol. But UI flow unclear.
**Recommendation**: **Clarify clone mode initialization**.
```javascript
// In rfid-minigame.js init()
if (this.mode === 'clone') {
if (this.cardToClone) {
const protocol = this.cardToClone.rfid_protocol || 'EM4100';
if (protocol === 'MIFARE_Classic') {
// Check if keys are available
const keysKnown = this.cardToClone.rfid_data?.sectors ?
Object.keys(this.cardToClone.rfid_data.sectors).length : 0;
if (keysKnown === 0) {
// No keys - show protocol info with attack options
this.ui.showProtocolInfo(this.cardToClone);
} else {
// Has keys - start reading/cloning
this.ui.showReadingScreen();
}
} else {
// EM4100 or DESFire - start reading immediately
this.ui.showReadingScreen();
}
}
}
```
---
## Medium Priority Issues
### Issue #6: Ink Variables Require Declaration
**Problem**: Plan shows setting Ink variables:
```javascript
this.inkEngine.setVariable('card_protocol', protocol);
```
But Ink variables must be declared in the .ink file first:
```ink
VAR card_protocol = ""
VAR card_uid = ""
VAR card_security = ""
```
If variable isn't declared, setVariable will silently fail or throw.
**Recommendation**: **Document Ink variable requirements**.
**Add to Technical Design**:
```markdown
### Required Ink Variables
For protocol integration to work, the following variables must be declared in NPC .ink files:
```ink
// Card protocol variables (for NPCs with keycards)
VAR card_protocol = "" // "EM4100", "MIFARE_Classic", "MIFARE_DESFire"
VAR card_name = "" // Card display name
VAR card_hex = "" // For EM4100
VAR card_uid = "" // For MIFARE
VAR card_security = "" // "low", "medium", "high"
VAR card_clonable = false // Can this card be instantly cloned?
// For NPCs with multiple cards
VAR card2_protocol = ""
VAR card2_name = ""
// etc.
```
If variables aren't declared, protocol info won't be available to Ink conditionals.
```
---
### Issue #7: Background Attacks Need Cleanup
**Problem**: Active attacks stored in array:
```javascript
this.activeAttacks = [];
```
But no cleanup when:
- Minigame is closed mid-attack
- Player navigates away
- Game is saved/loaded
**Recommendation**: **Add cleanup and persistence**.
```javascript
// In rfid-attacks.js
cleanup() {
// Cancel all active attacks
this.activeAttacks.forEach(attack => {
if (attack.interval) {
clearInterval(attack.interval);
}
});
this.activeAttacks = [];
}
// Store in window for persistence
saveState() {
return {
activeAttacks: this.activeAttacks.map(a => ({
type: a.type,
uid: a.uid,
cardName: a.cardName,
startTime: a.startTime,
foundKeys: a.foundKeys,
currentSector: a.currentSector
}))
};
}
restoreState(state) {
// Restore attacks and resume progress
// (implementation details)
}
```
---
### Issue #8: No Error Handling for Unsupported Protocols
**Problem**: What if cloner firmware doesn't support protocol?
```javascript
// User tries to clone MIFARE Classic
// But cloner firmware only supports ['EM4100']
```
Plan doesn't handle this case.
**Recommendation**: **Add firmware check before starting minigame**.
```javascript
// In chat-helpers.js clone_keycard tag
const cloner = window.inventory.items.find(item =>
item?.scenarioData?.type === 'rfid_cloner'
);
const cardProtocol = cardData.rfid_protocol || 'EM4100';
// Check firmware support
if (cloner.scenarioData.firmware) {
const supported = cloner.scenarioData.firmware.protocols || [];
if (!supported.includes(cardProtocol)) {
result.message = `⚠️ Flipper firmware doesn't support ${cardProtocol}`;
if (ui) ui.showNotification(result.message, 'warning');
break;
}
}
// Proceed with clone...
```
---
### Issue #9: DESFire UID Emulation Success Rate Not Defined
**Problem**: Plan says DESFire UID emulation works on "some systems" but doesn't define which.
```markdown
Some systems only check UID and don't use encryption properly.
```
How does game determine if emulation succeeds?
**Recommendation**: **Add door-level property for UID-only acceptance**.
```json
{
"locked": true,
"lockType": "rfid",
"requires": "ceo_keycard",
"acceptsUIDOnly": false // NEW: True for low-security readers
}
```
```javascript
// In unlock-system.js RFID case
if (lockRequirements.lockType === 'rfid') {
const cardId = lockRequirements.requires;
// Check if using DESFire UID-only emulation
if (card.rfid_protocol === 'MIFARE_DESFire' &&
!card.rfid_data.masterKeyKnown) {
// Check if door accepts UID-only
if (!lockRequirements.acceptsUIDOnly) {
showError("This reader requires full card authentication");
return false;
}
// UID matches?
if (card.key_id === cardId || card.rfid_data.uid === requiredUID) {
unlock();
}
}
}
```
---
## Low Priority Issues
### Issue #10: CSS Color Accessibility
**Problem**: Color-coding security levels:
```javascript
color: '#FF6B6B' // Red for low security
color: '#95E1D3' // Light green for high security
```
Red/green color blindness (~8% of males) makes this hard to distinguish.
**Recommendation**: **Add icons in addition to colors**.
```javascript
security: 'low',
color: '#FF6B6B',
icon: '⚠️' // Warning triangle
security: 'high',
color: '#95E1D3',
icon: '🔒' // Lock icon
```
---
### Issue #11: No Tests for Protocol-Specific Code
**Problem**: Plan mentions testing scenarios but no unit tests for:
- Protocol detection logic
- Capability checks
- Key validation
- Data migration
**Recommendation**: Add testing section (can defer to later).
---
### Issue #12: Attack Duration Magic Numbers
**Problem**: Hard-coded timings:
```javascript
const duration = 30000; // 30 seconds
```
Should be constants for easy tuning.
**Recommendation**:
```javascript
const ATTACK_DURATIONS = {
darkside: 30000, // 30 sec - crack from scratch
nested: 10000, // 10 sec - crack with known key
dictionary: 0 // Instant
};
```
---
## Simplified Implementation Approach
Based on review, here's a streamlined approach:
### Phase 1: Core Three Protocols (MVP)
1. EM4100 (easy) - Current implementation
2. MIFARE Classic (medium) - Add key attacks
3. MIFARE DESFire (hard) - UID only
Skip HID Prox initially.
### Phase 2: Protocol Detection & UI
1. Add RFID_PROTOCOLS constant
2. Update card data display (dual format support)
3. Add protocol info screen
4. Color-code security levels
### Phase 3: MIFARE Attacks (in clone mode)
1. Add MIFAREAttackManager
2. Dictionary attack (instant)
3. Darkside attack (30 sec animation)
4. Nested attack (10 sec animation)
5. Integrate into clone flow (not separate mode)
### Phase 4: Ink Integration
1. Sync protocol variables
2. Add start_mifare_attack tag
3. Add save_uid_only tag
4. Document required Ink variables
### Phase 5: Testing
1. Test scenarios for each protocol
2. Integration tests
3. Backward compatibility tests
## Recommended Changes Summary
| Change | Priority | Time Saved/Impact |
|--------|----------|-------------------|
| Remove HID Prox | High | -2h development |
| Merge attack into clone mode | High | Clearer UX, -1h dev |
| Remove firmware system initially | High | -2h development |
| Dual format support (no migration) | High | Simpler, safer |
| Add firmware check before clone | Medium | Prevents errors |
| Define acceptsUIDOnly for doors | Medium | Clear DESFire rules |
| Add Ink variable documentation | Medium | Prevent confusion |
| Add attack cleanup/persistence | Medium | Prevent bugs |
| Use timing constants | Low | Better maintainability |
| Add security icons | Low | Better accessibility |
**Total Time Saved**: ~5 hours
**Total Clarity Improved**: Significant
## Conclusion
The original plan is solid but can be **streamlined by 25%** while improving clarity:
- Remove HID Prox (minimal gameplay value)
- Merge attack mode into clone mode (simpler state machine)
- Skip firmware system initially (can add later)
- Use dual format support instead of migration (safer)
- Add missing error handling (firmware checks, UID acceptance)
**Recommendation**: Update implementation plan with these improvements before beginning development.