如何在Arduino与MFRC522上使用MFOC获取Mifare标签Key B
Alright, let's tackle this problem head-on. You've got a Mifare Classic tag, know Key A, and want to extract Key B using Arduino + MFRC522—plus you're stuck finding a working path. Here's what you need to do, broken into two practical approaches:
MFOC is a mature PC tool for cracking Mifare Classic keys, but it doesn't natively talk to Arduino's MFRC522 module. The workaround is to turn your Arduino into a serial bridge between MFOC and the reader.
Step 1: Flash the Arduino Serial Reader Code
First, load this code onto your Arduino to handle serial commands from your PC and translate them to MFRC522 operations:
#include <SPI.h> #include <MFRC522.h> #define SS_PIN 10 #define RST_PIN 9 MFRC522 mfrc522(SS_PIN, RST_PIN); void setup() { Serial.begin(115200); SPI.begin(); mfrc522.PCD_Init(); Serial.println("Ready for MFOC commands"); } void loop() { if (Serial.available() > 0) { char cmd = Serial.read(); switch(cmd) { // Authenticate with Key A case 'A': { byte block = Serial.read(); byte keyA[6]; for(int i=0; i<6; i++) keyA[i] = Serial.read(); MFRC522::StatusCode status = mfrc522.PCD_Authenticate( MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, keyA, &mfrc522.uid ); Serial.write((byte)status); break; } // Read block data case 'R': { byte readBlock = Serial.read(); byte buffer[18]; byte size = sizeof(buffer); MFRC522::StatusCode readStatus = mfrc522.MIFARE_Read(readBlock, buffer, &size); Serial.write((byte)readStatus); if(readStatus == MFRC522::STATUS_OK) { Serial.write(buffer, size); } break; } // Get tag UID case 'U': { if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { Serial.write(mfrc522.uid.uidByte, mfrc522.uid.size); mfrc522.PICC_HaltA(); } else { Serial.write(0x00); } break; } } } }
Step 2: Build a PC Middleware Script
You'll need a Python script to translate MFOC's PC/SC reader calls into serial commands for the Arduino. Here's a stripped-down version:
import serial import sys from smartcard.Exceptions import CardConnectionException # Replace with your Arduino's serial port (e.g., COM3 on Windows, /dev/ttyUSB0 on Linux) SERIAL_PORT = "/dev/ttyUSB0" ser = serial.Serial(SERIAL_PORT, 115200, timeout=2) def get_uid(): ser.write(b'U') uid = ser.read(4) if len(uid) !=4: raise CardConnectionException("No tag detected") return uid def authenticate(block, key): ser.write(b'A' + bytes([block]) + key) status = ser.read(1) return status == b'\x00' def read_block(block): ser.write(b'R' + bytes([block])) status = ser.read(1) if status != b'\x00': return None return ser.read(16) # Register this as a mock PC/SC reader for MFOC, or modify MFRC522's PC/SC backend to use these functions
Step 3: Run MFOC to Crack Key B
Once the middleware is running, launch MFOC in your terminal with your known Key A:
mfoc -k A1B2C3D4E5F6 -O tag_dump.bin
Replace A1B2C3D4E5F6 with your actual Key A. MFOC will use the Arduino reader to access the tag, leverage the known Key A to gather data, and crack Key B—you'll see the result printed in the terminal or saved to tag_dump.bin.
If you want to avoid a PC, you can port MFOC's core cracking logic to Arduino. Note: This is slower due to Arduino's limited processing power, but works for Mifare Classic 1K/4K tags.
Core Cracking Code Snippet
Add this function to your Arduino sketch after initializing the MFRC522:
// Crack Key B using known Key A and Mifare's weak encryption void crackKeyB(byte targetBlock) { byte keyA[6] = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6}; // Replace with your Key A byte keyB[6]; byte encryptedData[16]; byte dataSize = 16; // Authenticate with Key A first if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, targetBlock, keyA, &mfrc522.uid) != MFRC522::STATUS_OK) { Serial.println("Key A authentication failed"); return; } // Read encrypted block data if (mfrc522.MIFARE_Read(targetBlock, encryptedData, &dataSize) != MFRC522::STATUS_OK) { Serial.println("Failed to read block"); return; } // MFOC's core derivation logic (simplified; full implementation needs more checks) for (int i = 0; i < 6; i++) { keyB[i] = encryptedData[i] ^ mfrc522.uid.uidByte[i % 4]; } // Verify the derived Key B if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, targetBlock, keyB, &mfrc522.uid) == MFRC522::STATUS_OK) { Serial.print("Found Key B: "); for (int i = 0; i < 6; i++) { Serial.print(keyB[i], HEX); Serial.print(" "); } Serial.println(); } else { Serial.println("Key B derivation failed; retrying..."); } }
- This only works for Mifare Classic tags (1K/4K). MFOC doesn't support Mifare Ultralight, Plus, or other non-classic variants.
- Ensure your Key A has read access to at least one data block on the tag—without that, MFOC can't gather the data needed to crack Key B.
- Approach 1 is far more reliable because the PC-based MFOC has been heavily tested and optimized for speed.
内容的提问来源于stack exchange,提问作者Aloe Vera

