我是学生,作为实习的一部分,我希望制作一个applet,让我从ACR122阅读器上读取一个nfc标签。 我使用包javax.smartcardio。 但是,我无法读取标签甚至uid上的数据。 传输方法返回了许多我不太了解的数据......而且完全是随机的。 我认为不要在我的CommandAPDU对象中花费十六进制值。
我的线程的run方法的代码:
结果如下:
ResponseAPDU:ResponseAPDU:2个字节,SW = 6300
ResponseAPDU getBytes:[B @ 5c12c55c
ResponseAPDU getData:[B @ 6c63e398
ResponseAPDU:ResponseAPDU:2个字节,SW = 6300
ResponseAPDU getBytes:[B @ 5c12c55c
ResponseAPDU getData:[B @ 6c63e39
更新
现在我可以读卡上的数据,但只有当它们是空的时,当我用另一个应用程序(如GoToTag)写它时,我无法验证一个块。 而且我也不能写它。
以下是我的代码:
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");
}
这是我的代码:
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");
}
答案 0 :(得分:0)
您目前正在使用密钥A FF FF FF FF FF FF
对扇区0进行身份验证。 GoToTags或NFC TagWriter等应用程序将根据恩智浦应用笔记“NFC Type MIFARE Classic Tag Operation”将MIFARE Classic卡转换为NDEF标签。结果,修改了扇区0(MIFARE应用目录扇区)和用于存储NDEF数据的扇区的访问条件。通常,这意味着
A0 A1 A2 A3 A4 A5
(“MAD密钥”),密钥B设置为FF FF FF FF FF FF
,访问条件设置为密钥A只能是用于阅读,而键B可用于阅读和写作。D3 F7 D3 F7 D3 F7
,密钥B设置为FF FF FF FF FF FF
,访问条件的设置方式是密钥A只能用于密钥读取B可用于阅读和写作。因此,一旦您使用了这样的应用程序,使用密钥A FF FF FF FF FF FF
对扇区0进行身份验证将不再有效,因此您必须相应地更新byte[] ApduArrayLoadAuth
命令定义中的密钥(或更改密钥类型在byte[] ApduArrayAuth
到密钥B)。
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块由16个字节组成,因此不能只写入两个字节。你总是要写一个完整的块:
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 };