Получить UID из Mifare Ultralight с SCL010
Я хочу получить UID тега Mifare Ultralight NFC. В Java у меня есть этот код:
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
System.out.println("Terminals: " + terminals);
CardTerminal terminal = terminals.get(0);
Card card = terminal.connect("*");
System.out.println("card: " + card);
CardChannel channel = card.getBasicChannel();
ResponseAPDU answer = channel.transmit(new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x00));
byte[] uid = answer.getBytes();
проблема в том, что я получаю два байта, а не UID. В чем проблема? Это АИУ правильно?
2 ответов
команды вы используете не то, что вы могли бы ожидать.
правильная команда APDU для получения идентификатора UID/серийного номера/перечисления с этим считывателем:
+------+------+------+------+------+
| CLA | INS | P1 | P2 | Le |
+------+------+------+------+------+
| 0xFF | 0xCA | 0x00 | 0x00 | 0x00 |
+------+------+------+------+------+
однако используемый вами конструктор определяется как:
public CommandAPDU(int cla, int ins, int p1, int p2, int ne);
поэтому с
new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 0x00)
вы создаете C-APDU со следующими параметрами CLA = 0xFF
, INS = 0xCA
, P1 = 0x00
, P2 = 0x00
. До сих пор это то же самое, что и выше APDU. Но последний параметр Ne = 0x00
. Ne = 0
означает, что число ожидаемых байтов ответа равно нулю (тогда как Le = 0 означает, что число ожидаемых байтов ответа равно (до) 256).
это приводит к эффективному созданию следующего случая-1 APDU:
+------+------+------+------+
| CLA | INS | P1 | P2 |
+------+------+------+------+
| 0xFF | 0xCA | 0x00 | 0x00 |
+------+------+------+------+
таким образом, самое большее, вы получите 2-байтовое слово статуса в качестве ответа (либо с указанием успеха с 0x90 0x00
или указание ошибки с кодом состояния, например 0x6X 0xXX
).
таким образом, вы можете использовать массив байтов для формирования APDU:
new CommandAPDU(new byte[] { (byte)0xFF, (byte)0xCA, (byte)0x00, (byte)0x00, (byte)0x00 } )
или вы можете указать правильное значение для Ne
:
new CommandAPDU(0xFF, 0xCA, 0x00, 0x00, 256)
import java.nio.ByteBuffer;
import java.util.List;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
public class Read {
public Read() {
try {
CardTerminal terminal = null;
// show the list of available terminals
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
String readerName = "";
for (int i = 0; i < terminals.size(); i++) {
readerName = terminals.get(i).toString()
.substring(terminals.get(i).toString().length() - 2);
//terminal = terminals.get(i);
if (readerName.equalsIgnoreCase(" 0")) {
terminal = terminals.get(i);
}
}
// Establish a connection with the card
System.out.println("Waiting for a card..");
if(terminal==null)
return;
terminal.waitForCardPresent(0);
Card card = terminal.connect("T=0");
CardChannel channel = card.getBasicChannel();
// Start with something simple, read UID, kinda like Hello World!
byte[] baReadUID = new byte[5];
baReadUID = new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00,
(byte) 0x00, (byte) 0x00 };
System.out.println("UID: " + send(baReadUID, channel));
// If successfull, the output will end with 9000
// OK, now, the real work
} catch (Exception ex) {
ex.printStackTrace();
}
}
public String send(byte[] cmd, CardChannel channel) {
String res = "";
byte[] baResp = new byte[258];
ByteBuffer bufCmd = ByteBuffer.wrap(cmd);
ByteBuffer bufResp = ByteBuffer.wrap(baResp);
// output = The length of the received response APDU
int output = 0;
try {
output = channel.transmit(bufCmd, bufResp);
}` catch (CardException ex) {
ex.printStackTrace();
}`
for (int i = 0; i < output; i++) {
res += String.format("%02X", baResp[i]);
// The result is formatted as a hexadecimal integer
}
return res;
}
public static void main(String[] args) {
new Read();
}
}
после прочтения этого кода для чтения и записи используйте следующие команды.
и читать со страницы: 04 на страницу: 07 команда:
read_four_to_seven = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x05, (byte) 0x0D4, (byte) 0x40, (byte) 0x01,
(byte) 0x30, (byte) 0x04, (byte) 0x07 };
System.out.println("Read : " + send(read_four_to_seven, channel));
напишите на странице 04:
Write_Page_Four = new byte[] { (byte) 0xFF, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x15, (byte) 0xD4, (byte) 0x40,
(byte) 0x01, (byte) 0xA0, (byte) 0x04, (byte) 0x4D,
(byte) 0x65, (byte) 0x73, (byte) 0x75, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00 };
System.out.println("Read : " + send(Write_Page_Four, channel));