适用于nfc的ACR122和javax.smartcardio

时间:2015-03-09 16:24:28

标签: java nfc apdu mifare acr122

我是学生,作为实习的一部分,我希望制作一个applet,让我从ACR122阅读器上读取一个nfc标签。 我使用包javax.smartcardio。 但是,我无法读取标签甚至uid上的数据。 传输方法返回了许多我不太了解的数据......而且完全是随机的。 我认为不要在我的CommandAPDU对象中花费十六进制值。

我的线程的run方法的代码:

http://pastebin.com/u6m0jArd

结果如下:

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");

                        }

1 个答案:

答案 0 :(得分:0)

从MIFARE Classic卡中读取数据是空的,但是一旦其他应用程序(如GoToTags)写入卡中就无法工作

您目前正在使用密钥A FF FF FF FF FF FF对扇区0进行身份验证。 GoToTags或NFC TagWriter等应用程序将根据恩智浦应用笔记“NFC Type MIFARE Classic Tag Operation”将MIFARE Classic卡转换为NDEF标签。结果,修改了扇区0(MIFARE应用目录扇区)和用于存储NDEF数据的扇区的访问条件。通常,这意味着

  • 对于扇区0,密钥A设置为A0 A1 A2 A3 A4 A5(“MAD密钥”),密钥B设置为FF FF FF FF FF FF,访问条件设置为密钥A只能是用于阅读,而键B可用于阅读和写作。
  • 对于所有其他扇区,密钥A设置为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)。

写入MIFARE Classic卡不起作用

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 };