Hoy voy a escribir sobre cómo clonar una tarjeta RFID con Arduino.
Como no me olvido de lo que escribo una vez, lo dejo aquí a modo de repaso.

1. Estructura interna de datos de una tarjeta RFID
La tarjeta RFID típica es una tarjeta MIFARE Classic 1K.
La estructura de memoria de esta tarjeta es la siguiente.
- Total 1024 bytes (1KB)
- 16 Sectores (0~15)
- Cada Sector tiene 4 Bloques (Block 0~3)
- Cada Bloque tiene 16 bytesCada sector tiene la siguiente estructura.
Sector n
├── Block 0 (Data or UID block)
├── Block 1 (Data)
├── Block 2 (Data)
└── Block 3 (Sector Trailer: Key A, Access Bits, Key B)Entre estos sectores, el que tiene el significado más importante es el primer dato del sector 0.
Ahí es donde se almacena el UID.

2. UID
Es la abreviatura de Unique IDentifier, y se refiere al número de identificación único asignado a cada tarjeta RFID (por ejemplo: tarjeta de transporte, tarjeta de acceso, tarjeta de estudiante, etc.).
En el caso de una persona, cumple un papel similar al número de documento de identidad.
El UID se almacena en los primeros 4 bytes dentro del Block 0 del Sector 0.
[ UID0 | UID1 | UID2 | UID3 | BCC | Manufacturer Data… ]Cuando una máquina RFID lee una tarjeta, lo primero que lee es esta parte.
Con esto se lleva a cabo la identificación de la tarjeta.

3. Tarjeta CUID
Lo importante es que el UID de una MIFARE Classic 1K original queda fijado en fábrica.
En los chips originales de NXP el UID se almacena en la ROM y no puede modificarse por ningún método.
Por lo tanto, con un lector de tarjetas normal o con el MFRC522 no es posible modificar el UID.

Sin embargo, en el mercado existen tarjetas en las que es posible cambiar el UID, y a este tipo de tarjetas se les llama CUID (también conocidas como tarjetas mágicas).
La C del principio significa Changeable.
Su aspecto externo es igual al de una MIFARE Classic 1K, pero el chip interno es diferente de la siguiente manera.
① Gen1A (compatible con UID/Backdoor)
Soporta los comandos de backdoor 0x40 / 0x43
Proporciona un comando específico para cambiar el UID
Se puede cambiar con MFRC522 + la función MIFARE_SetUid() de la librería de Arduino
② CUID / Gen2 (Block 0 Writable)
No tiene comandos de backdoor
En su lugar, está diseñada para poder sobrescribir el Block 0 (el sector donde está el UID) mediante una escritura normal (WRITE)
Es posible cambiar el UID si el MFRC522 acepta el comando MIFARE_Write(0…)
Pero no todos los CUID funcionan así. Si el MFRC522 no lo soporta, se necesita PN532/ACR122U
4. Clonar una tarjeta RFID con Arduino
Ahora que ya conocemos el principio, el método para clonar una tarjeta RFID con Arduino es sencillo.
Solo hay que clonar el UID.
Primero conecta el Arduino como se muestra a continuación.

Signal | MFRC522 Pin | Arduino Uno / 101 | Arduino Mega | Arduino Nano v3 | Arduino Leonardo / Micro | Arduino Pro Micro |
|---|---|---|---|---|---|---|
RST / Reset | RST | 9 | 5 | D9 | RESET / ICSP-5 | RST |
SPI SS | SDA (SS) | 10 | 53 | D10 | 10 | 10 |
SPI MOSI | MOSI | 11 / ICSP-4 | 51 | D11 | ICSP-4 | 16 |
SPI MISO | MISO | 12 / ICSP-1 | 50 | D12 | ICSP-1 | 14 |
SPI SCK | SCK | 13 / ICSP-3 | 52 | D13 | ICSP-3 | 15 |
Luego, en el IDE de Arduino, busca e instala la librería MFRC522.

Ahora ve a Archivo -> Ejemplos -> MFRC522 y selecciona ReadNUID.

Después de subir ese código, primero lee el valor del UID.
El UID suele estar formado por 4 valores hexadecimales.
F5 5F 36 80Si has obtenido un UID como el de arriba, el UID que se va a subir es el siguiente.
El 0x delante del número significa que ese número está en hexadecimal.
0xF5 0x5F 0x36 0x805. Problemas y solución
Quería resolverlo fácilmente con el ejemplo ChangeUID, pero seguía fallando.
El backdoor 0x40 daba continuamente timeout.
Resultó que mi tarjeta era Gen2, así que solo tenía que acceder al sector 0 y reemplazar el UID.
El código es el siguiente.
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9
#define SS_PIN 10
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
// Nuevo UID que se quiere poner (4 bytes)
byte newUid[4] = { 0xF5, 0x5F, 0x36, 0x80 }; // Ejemplo
void setup() {
Serial.begin(9600);
while (!Serial) {}
SPI.begin();
mfrc522.PCD_Init();
Serial.println(F("Ejemplo de escritura directa del UID en el Block 0 de una tarjeta CUID"));
// Configurar clave por defecto FF..FF
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
}
void loop() {
// Esperar nueva tarjeta
if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.print(F("UID actual de la tarjeta: "));
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i], HEX);
Serial.print(" ");
}
Serial.println();
// === 1. Autenticar Sector 0 (Block 0) ===
byte block = 0; // Block 0
MFRC522::StatusCode status;
status = mfrc522.PCD_Authenticate(
MFRC522::PICC_CMD_MF_AUTH_KEY_A,
block,
&key,
&(mfrc522.uid)
);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Fallo de autenticación: "));
Serial.println(mfrc522.GetStatusCodeName(status));
goto HALT;
}
// === 2. Leer el contenido actual del Block 0 para conservar la parte del fabricante ===
byte block0[18]; // 16 bytes + información de tamaño
byte size = sizeof(block0);
status = mfrc522.MIFARE_Read(0, block0, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Fallo al leer Block 0: "));
Serial.println(mfrc522.GetStatusCodeName(status));
goto HALT;
}
// block0[0..3] = UID original
// block0[4] = BCC (XOR de los 4 bytes del UID)
// block0[5..15]= datos del fabricante, etc.
// === 3. Calcular nuevo UID + BCC y sobrescribir ===
byte bcc = newUid[0] ^ newUid[1] ^ newUid[2] ^ newUid[3];
block0[0] = newUid[0];
block0[1] = newUid[1];
block0[2] = newUid[2];
block0[3] = newUid[3];
block0[4] = bcc;
// Si dejamos block0[5..15] tal cual, se mantiene la información del fabricante
status = mfrc522.MIFARE_Write(0, block0, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Fallo al escribir en Block 0: "));
Serial.println(mfrc522.GetStatusCodeName(status));
goto HALT;
}
Serial.println(F("Escritura del nuevo UID completada. Retira la tarjeta y vuelve a acercarla."));
HALT:
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
delay(1000);
} 6. Conclusión
En esta ocasión he llegado a entender bien cómo usar el módulo RFID.
Si buscas por ahí, verás proyectos que abren puertas usando una tarjeta llave, y parece que algo así también se podría implementar fácilmente.
Quiero probar a aplicarlo de diversas maneras.
Por cierto, si con este método la tarjeta sigue sin ser reconocida, es muy probable que se trate de un problema de frecuencia (13,56 MHz, 125 kHz, etc.).
Si tienes alguna pregunta, déjala en los comentarios.
댓글을 불러오는 중...