0
votes

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. I use the package javax.smartcardio. However, I can not read the data found on the tag or even the 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.

The code for the run method of my thread:

http://pastebin.com/u6m0jArd

Here are the results:

ResponseAPDU : ResponseAPDU: 2 bytes, SW=6300

ResponseAPDU getBytes: [B@5c12c55c

ResponseAPDU getData: [B@6c63e398

ResponseAPDU : ResponseAPDU: 2 bytes, SW=6300

ResponseAPDU getBytes: [B@5c12c55c

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

                        }
1
Please post the shortest code necessary to reproduce your problem in your question (and don't just link to it). Instead of printing the hash codes ([B@...) of the byte arrays, it would be helpful if you showed us the actual values.Michael Roland

1 Answers

0
votes

Reading data from the MIFARE Classic card is possible while it is empty, but does not work once another application (like GoToTags) wrote to the card

You are currently authenticating to sector 0 with key A FF FF FF FF FF FF. 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". As a consequence, the access conditions for sector 0 (the MIFARE Application Directory sector) and the sectors used for storing NDEF data are modified. Typically, this means that

  • for sector 0, key A is set to 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.
  • for all other sectors, key A is set to 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.

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).

Writing to the MIFARE Classic card does not work

Your write command in byte[] ApduArrayWrite currently tries to write two bytes:

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