[英]ACR122 and javax.smartcardio for nfc
I am a student and as part of my internship I am looking to make an applet that lets me read a nfc tag from the ACR122 reader. 我是一名学生,作为实习的一部分,我希望制作一个能使我从ACR122阅读器读取nfc标签的小程序。 I use the package javax.smartcardio.
我使用包javax.smartcardio。 However, I can not read the data found on the tag or even the uid.
但是,我无法读取在标签甚至uid上找到的数据。 the transmit methode returns me many data that I do not really understand ... and completely random.
传输方法向我返回了许多我不太了解的数据,而且完全是随机的。 I think not spend good hexadecimal values in my CommandAPDU object.
我认为不要在CommandAPDU对象中使用好的十六进制值。
The code for the run method of my thread: 我的线程的run方法的代码:
http://pastebin.com/u6m0jArd http://pastebin.com/u6m0jArd
Here are the results: 结果如下:
ResponseAPDU : ResponseAPDU: 2 bytes, SW=6300 ResponseAPDU:ResponseAPDU:2字节,SW = 6300
ResponseAPDU getBytes: [B@5c12c55c ResponseAPDU getBytes:[B @ 5c12c55c
ResponseAPDU getData: [B@6c63e398 ResponseAPDU getData:[B @ 6c63e398
ResponseAPDU : ResponseAPDU: 2 bytes, SW=6300 ResponseAPDU:ResponseAPDU:2字节,SW = 6300
ResponseAPDU getBytes: [B@5c12c55c ResponseAPDU getBytes:[B @ 5c12c55c
ResponseAPDU getData: [B@6c63e39 ResponseAPDU getData:[B @ 6c63e39
UPDATE 更新
right now I can read Data on the card but only when they are empty, when I write on it with another application (like GoToTag) I can't authenticate a block. 现在,我可以读取卡上的数据,但是只有当它们为空时,当我使用其他应用程序(例如GoToTag)在其上写入数据时,我才能对块进行身份验证。 Moreover I can't write on it neither.
而且我也不能写。
Here is my code to read: 这是我要阅读的代码:
if(MyReader.waitForCardPresent(0))
{
if(!Lu)
System.out.println("détectée");
card = MyReader.connect("*");
if(card != null)
{
if(!Lu)
{
System.out.println("Carte connectée");
System.out.println("ATR: " + arrayToHex(((ATR) card.getATR()).getBytes()));
}
ch = card.getBasicChannel();
/*Get UID*/
byte[] ApduArrayUID = {
(byte) 0xff,
(byte) 0xca,
(byte) 0x00,
(byte) 0x00,
(byte) 0x00
};
/*Iso Card*/
byte[] ApduArrayISO = {
(byte) 0xff,
(byte) 0xca,
(byte) 0x01,
(byte) 0x00,
(byte) 0x00
};
/* load Authentification */
byte[] ApduArrayLoadAuth= {
(byte) 0xff, //Class
(byte) 0x82, //INS
(byte) 0x00,//emplacement volatile du lecteur
(byte) 0x00, //emplacement sur le lecteur
(byte) 0x06, //LC
(byte) 0xff, // Valeur de la clé sur 6 bytes
(byte) 0xff,
(byte) 0xff,
(byte) 0xff,
(byte) 0xff,
(byte) 0xff
};
/*Authentication du Block 00h*/
byte[] ApduArrayAuth = {
(byte) 0xff,// Class
(byte) 0x86, //INS
(byte) 0x00,//P1
(byte) 0x00,//P2
(byte) 0x05,//LC
//Authentication Data bytes
(byte) 0x01, //Version
(byte) 0x00, // Byte 2
(byte) 0x00,//Block number
(byte) 0x60,// Clé de type A
(byte) 0x00 //Emplacement de la clé
};
/*Read Block 1*/
byte[] ApduArrayRead = {
(byte) 0xff, //Class
(byte) 0xb0,//INS
(byte) 0x00,//P1
(byte) 0x00,//P2 = Block number
(byte) 0x10, // Le = Number of bytes to read
};
/***** UID *****/
CommandAPDU GetDataUID = new CommandAPDU(ApduArrayUID);
ResponseAPDU CardApduResponseUID = ch.transmit(GetDataUID);
//nfc.AfficheUID(byteToString(CardApduResponseUID.getBytes()));
if(CardApduResponseUID.getSW() == 36864)
{
String Uid=byteToString(CardApduResponseUID.getBytes());
if(! Uid.equals(UidCourant))// Si une nouvelle carte les blocks mémoire ne sont pas authentifié
{
Auth=false;
Lu=false;
}
else
{
Auth=true; Lu=true;
}
UidCourant= byteToString(CardApduResponseUID.getBytes());
uid.setText(UidCourant);
if(!Lu)
System.out.println("UID : "+UidCourant);
}
/***** Charger authentification *****/
//System.out.println("UID response: " + byteToString(CardApduResponseUID.getBytes()));
if(!Charge)
{
System.out.println("Chargement de l'authentification dans le lecteur ");
CommandAPDU GetDataLoadAuth = new CommandAPDU(ApduArrayLoadAuth);
ResponseAPDU CardApduResponse = ch.transmit(GetDataLoadAuth);
if(CardApduResponse.getSW() == 36864) // 90 00h = success
{
Charge=true;
System.out.println("Chargement authentification réussie :" );
}
}
if(Charge)
{
if(!Auth)
{
/******* authentification du block 00h*********/
System.out.println("Authentification d'un block");
CommandAPDU GetDataAuth = new CommandAPDU(ApduArrayAuth);
ResponseAPDU CardApduResponseAuth = ch.transmit(GetDataAuth);
System.out.println("ResponseAPDU auth : "+ CardApduResponseAuth);
if(CardApduResponseAuth.getSW() == 36864)
{
Auth=true;
System.out.println("Authentification d'un block réussie ! ");
}
else
System.out.println("Impossible d'authentifier le block :'(");
}
if(Auth && !Lu) // si l'authentification est faite et qu'on a pas encore Lu, on lit
{
/*Lecture du block 0x00*/
System.out.println("Lecture d'un block");
CommandAPDU GetDataRead = new CommandAPDU(ApduArrayRead);
ResponseAPDU CardApduResponseRead = ch.transmit(GetDataRead);
System.out.println("ResponseAPDU auth : "+ CardApduResponseRead);
if(CardApduResponseRead.getSW() == 36864)
{
System.out.println("Read response: " + byteToString(CardApduResponseRead.getBytes()));
Lu=true;
}
}
}
card.disconnect(true);
}
else
System.out.println("Carte non connectée");
}
Here is my code to write: 这是我要编写的代码:
while(!isStop())
{
try
{
uid.setText("");
if(MyReader.waitForCardPresent(0))
{
if(!Lu)
System.out.println("détectée");
card = MyReader.connect("*");
if(card != null)
{
if(!Lu)
{
System.out.println("Carte connectée");
System.out.println("ATR: " + arrayToHex(((ATR) card.getATR()).getBytes()));
}
ch = card.getBasicChannel();
/*Get UID*/
byte[] ApduArrayUID = {
(byte) 0xff,
(byte) 0xca,
(byte) 0x00,
(byte) 0x00,
(byte) 0x00
};
/*Iso Card*/
byte[] ApduArrayISO = {
(byte) 0xff,
(byte) 0xca,
(byte) 0x01,
(byte) 0x00,
(byte) 0x00
};
/* load Authentification */
byte[] ApduArrayLoadAuth= {
(byte) 0xff, //Class
(byte) 0x82, //INS
(byte) 0x00,//emplacement volatile du lecteur
(byte) 0x00, //emplacement sur le lecteur
(byte) 0x06, //LC
(byte) 0xff, // Valeur de la clé sur 6 bytes
(byte) 0xff,
(byte) 0xff,
(byte) 0xff,
(byte) 0xff,
(byte) 0xff
};
/*Authentication du Block 00h*/
byte[] ApduArrayAuth = {
(byte) 0xff,// Class
(byte) 0x86, //INS
(byte) 0x00,//P1
(byte) 0x00,//P2
(byte) 0x05,//LC
//Authentication Data bytes
(byte) 0x01, //Version
(byte) 0x00, // Byte 2
(byte) 0x00,//Block number
(byte) 0x60,// Clé de type A
(byte) 0x00 //Emplacement de la clé
};
/*Write Block 1*/
byte[] ApduArrayWrite = {
(byte) 0xff, //Class
(byte) 0xd6,//INS
(byte) 0x00,//P1
(byte) 0x00,//P2 = Block number
(byte) 0x02, // Lc = Number of bytes to update
//Data to be written
(byte)0x00,
(byte)0x01
};
/***** UID *****/
CommandAPDU GetDataUID = new CommandAPDU(ApduArrayUID);
ResponseAPDU CardApduResponseUID = ch.transmit(GetDataUID);
//nfc.AfficheUID(byteToString(CardApduResponseUID.getBytes()));
if(CardApduResponseUID.getSW() == 36864)
{
String Uid=byteToString(CardApduResponseUID.getBytes());
if(! Uid.equals(UidCourant))// Si une nouvelle carte les blocks mémoire ne sont pas authentifié
{
Auth=false;
Lu=false;
}
else
{
Auth=true; Lu=true;
}
UidCourant= byteToString(CardApduResponseUID.getBytes());
uid.setText(UidCourant);
if(!Lu)
System.out.println("UID : "+UidCourant);
}
/***** Charger authentification *****/
//System.out.println("UID response: " + byteToString(CardApduResponseUID.getBytes()));
if(!Charge)
{
System.out.println("Chargement de l'authentification dans le lecteur ");
CommandAPDU GetDataLoadAuth = new CommandAPDU(ApduArrayLoadAuth);
ResponseAPDU CardApduResponse = ch.transmit(GetDataLoadAuth);
if(CardApduResponse.getSW() == 36864) // 90 00h = success
{
Charge=true;
System.out.println("Chargement authentification réussie :" );
}
}
if(Charge)
{
if(!Auth)
{
/******* authentification du block 00h*********/
System.out.println("Authentification d'un block");
CommandAPDU GetDataAuth = new CommandAPDU(ApduArrayAuth);
ResponseAPDU CardApduResponseAuth = ch.transmit(GetDataAuth);
System.out.println("ResponseAPDU auth : "+ CardApduResponseAuth);
if(CardApduResponseAuth.getSW() == 36864)
{
Auth=true;
System.out.println("Authentification d'un block réussie ! ");
}
else
System.out.println("Impossible d'authentifier le block :'(");
}
if(Auth && !Lu) // si l'authentification est faite et qu'on a pas encore Lu, on lit
{
/*Ecriture du block 0x00*/
System.out.println("Ecriture d'un block");
CommandAPDU GetDataWrite = new CommandAPDU(ApduArrayWrite);
ResponseAPDU CardApduResponseWrite = ch.transmit(GetDataWrite);
System.out.println("ResponseAPDU Write : "+ CardApduResponseWrite);
if(CardApduResponseWrite.getSW() == 36864)
{
System.out.println("Ecriture réussite!");
System.out.println("Write response: " + byteToString(CardApduResponseWrite.getBytes()));
Lu=true;
}
else
System.out.println("Echec de l'écriture :/");
}
}
card.disconnect(true);
}
else
System.out.println("Carte non connectée");
}
You are currently authenticating to sector 0 with key A FF FF FF FF FF FF
. 您当前正在使用密钥A
FF FF FF FF FF FF
向扇区0进行身份验证。 Apps like GoToTags or NFC TagWriter will transform the MIFARE Classic card into an NDEF tag according to NXP's application note " NFC Type MIFARE Classic Tag Operation ". 诸如GoToTags或NFC TagWriter之类的应用程序将根据NXP的应用笔记“ NFC Type MIFARE Classic Tag Operation ”将MIFARE Classic卡转换为NDEF标签。 As a consequence, the access conditions for sector 0 (the MIFARE Application Directory sector) and the sectors used for storing NDEF data are modified.
结果,修改了扇区0(MIFARE应用程序目录扇区)和用于存储NDEF数据的扇区的访问条件。 Typically, this means that
通常,这意味着
A0 A1 A2 A3 A4 A5
("MAD key"), key B is set to FF FF FF FF FF FF
, and the access conditions are set in a way that key A can only be used for reading while key B can be used for reading and writing. A0 A1 A2 A3 A4 A5
(“ MAD密钥”),将密钥B设置为FF FF FF FF FF FF
,并且访问条件设置为只能使用密钥A键B可用于读取和写入。 D3 F7 D3 F7 D3 F7
, key B is set to FF FF FF FF FF FF
, and the access conditions are set in a way that key A can only be used for reading while key B can be used for reading and writing. D3 F7 D3 F7 D3 F7
,将密钥B设置为FF FF FF FF FF FF
,并设置访问条件,使得密钥A仅可用于读取,而密钥B仅可用于读取可用于阅读和写作。 Hence, once you used such an app, authenticating to sector 0 with key A FF FF FF FF FF FF
will no longer work, so you have to update the key in your byte[] ApduArrayLoadAuth
command definition accordingly (or change the key type in byte[] ApduArrayAuth
to key B). 因此,一旦使用了这样的应用程序,将不再使用密钥A
FF FF FF FF FF FF
对扇区0进行身份验证,因此您必须相应地更新byte[] ApduArrayLoadAuth
命令定义中的密钥(或更改密钥类型)。 byte[] ApduArrayAuth
to key B)。
Your write command in byte[] ApduArrayWrite
currently tries to write two bytes: 您在
byte[] ApduArrayWrite
写命令byte[] ApduArrayWrite
当前尝试写两个字节:
byte[] ApduArrayWrite = { (byte) 0xff, //Class
(byte) 0xd6, //INS
(byte) 0x00, //P1
(byte) 0x00, //P2 = Block number
(byte) 0x02, // Lc = Number of bytes to update
//Data to be written
(byte)0x00, (byte)0x01 };
MIFARE Classic blocks consist of 16 bytes, so writing only two bytes is not possible. MIFARE Classic块由16个字节组成,因此只能写入两个字节。 You always have to write a complete block:
您总是必须编写一个完整的块:
byte[] ApduArrayWrite = { (byte) 0xff, //Class
(byte) 0xd6, //INS
(byte) 0x00, //P1
(byte) 0x00, //P2 = Block number
(byte) 0x10, // Lc = Number of bytes to update
//Data to be written
(byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.