【问题标题】:ACR122 and javax.smartcardio for nfc用于 nfc 的 ACR122 和 javax.smartcardio
【发布时间】:2015-05-10 21:37:33
【问题描述】:

我是一名学生,作为实习的一部分,我希望制作一个小程序,让我可以从 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");

                        }

【问题讨论】:

  • 请在您的问题中发布重现您的问题所需的最短代码(不要只是链接到它)。如果您向我们展示实际值,而不是打印字节数组的哈希码 ([B@...),将会很有帮助。

标签: java nfc apdu mifare acr122


【解决方案1】:

可以在 MIFARE Classic 卡为空时读取数据,但在其他应用程序(如 GoToTags)写入卡后就无法工作

您当前正在使用密钥 A FF FF FF FF FF FF 对扇区 0 进行身份验证。根据恩智浦的应用说明“NFC Type MIFARE Classic Tag Operation”,GoToTags 或 NFC TagWriter 等应用程序会将 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 命令定义中的密钥(或更改 @ 中的密钥类型987654329@ 键 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 };

【讨论】:

    猜你喜欢
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多