Social Icons

Read and Write to NFC tag


Hello again,
I’ve experienced getting universal identification from the NFC card by previous post. So now I’m going to show you how to write and read data to the NFC tag.

Write data to the NFC tag

You can see, on the main window there is a textbox to enter your data. When click on “Write data to the card” button we are writing data on the 5th block of the NFC tag.
Make sure your code contains previous posts’ mainwindow codes.


Read written data from the NFC tag

Now we are going to retrieve what we wrote on 5th block of the NFC tag.


Thank you very much!
Please comment below if you have any questions or errors or anything :)
Enjoy!!
Irantha Jayasekara



98 comments:

  1. Sir, when i try to read the UID from card using your code, it gives me error

    ReplyDelete
    Replies
    1. What is the error? and what is your card type? Can you give me more details?

      Delete
    2. Error is : 6
      I changed the settings in configuration manager to x86 also
      M using
      ACR 122U nfc reader
      Win 8 64 bit
      VS 2010 (i also have VS 2012)
      I dont know about the card
      may b its Mifare 4K

      Delete
    3. Error 6 refer to "the card has been reset and specific communication protocols have been established". can you try with different card?
      I tried with Mifare 1K cards but APDU command should works with 4K also.

      Delete
    4. Yes
      I have tried with 5 different cards
      It gives me the same result

      Delete
    5. Hi Malvinder,
      I tried just now with 4K cards and its works fine. please make sure your card type is Mifare 1K, 4K or Ultralight.

      Delete
  2. Yes, sir
    I am sure its Mifare 4k
    Apart from the Cars.cs file
    here's the code for winform

    public List ListReaders()
    {
    int ReaderCount = 0;
    List AvailableReaderList = new List();

    //Make sure a context has been established before
    //retrieving the list of smartcard readers.
    retCode = Card.SCardListReaders(hContext, null, null, ref ReaderCount);
    if (retCode != Card.SCARD_S_SUCCESS)
    {
    MessageBox.Show(Card.GetScardErrMsg(retCode));
    //connActive = false;
    }

    byte[] ReadersList = new byte[ReaderCount];

    //Get the list of reader present again but this time add sReaderGroup, retData as 2rd & 3rd parameter respectively.
    retCode = Card.SCardListReaders(hContext, null, ReadersList, ref ReaderCount);
    if (retCode != Card.SCARD_S_SUCCESS)
    {
    MessageBox.Show(Card.GetScardErrMsg(retCode));
    }

    string rName = "";
    int indx = 0;
    if (ReaderCount > 0)
    {
    // Convert reader buffer to string
    while (ReadersList[indx] != 0)
    {

    while (ReadersList[indx] != 0)
    {
    rName = rName + (char)ReadersList[indx];
    indx = indx + 1;
    }

    //Add reader name to list
    AvailableReaderList.Add(rName);
    rName = "";
    indx = indx + 1;

    }
    }
    return AvailableReaderList;

    }

    private string getcardUID()//only for mifare 1k cards
    {
    string cardUID = "";
    byte[] receivedUID = new byte[256];
    Card.SCARD_IO_REQUEST request = new Card.SCARD_IO_REQUEST();
    request.dwProtocol = Card.SCARD_PROTOCOL_RAW;
    request.cbPciLength = System.Runtime.InteropServices.Marshal.SizeOf(typeof(Card.SCARD_IO_REQUEST));
    byte[] sendBytes = new byte[] { 0xFF, 0xCA, 0x00, 0x00, 0x00 }; //get UID command for Mifare cards
    int outBytes = receivedUID.Length;
    int status = Card.SCardTransmit(hCard, ref request, ref sendBytes[0], sendBytes.Length, ref request, ref receivedUID[0], ref outBytes);

    if (status != Card.SCARD_S_SUCCESS)
    {
    MessageBox.Show(status.ToString());
    }
    else
    {
    cardUID = BitConverter.ToString(receivedUID.Take(4).ToArray()).Replace("-", string.Empty).ToLower();
    }

    return cardUID;
    }


    private void button1_Click(object sender, EventArgs e)
    {
    try
    {
    /*for (int i = 0; i <= 10; i++)
    {*/
    string cardUId = getcardUID();
    listBox2.Items.Add(cardUId);
    /* Thread.Sleep(2000);
    }*/
    }
    catch (Exception ex)
    {

    }
    }

    ReplyDelete
    Replies
    1. Looks like you didn't establish the context before you connect the reader.
      check your code again. check whether you call establishContext() method.

      Delete
  3. Hello, Thanks for your nice article, I did everything you said but i have some problem with your codes:
    when I try to get UID of Mifare 1k it textbox show me "17900000" for all of mifare 1k cards.
    and when I try to read or write block textbox show me "FailAuthentication"
    can you help me??? thanks a lot

    ReplyDelete
    Replies
    1. Hi Morid,
      You are welcome!
      Can you check your cards information with any other way like Android application?
      Did you try with block number 5 ? Can you try with brand new card?

      Delete
  4. hi i am getting different uid number in nfc mobile and through this code.both are different and when i read or write its gives a msg that failed authentication

    ReplyDelete
    Replies
    1. Hi Nikitha,
      Sorry for the delay.
      What is your card type? Mifare 1K ?
      The reason why you can't read or write is you have encrypted the card before. You will need that encrypted code to write and read data.

      Delete
  5. Hai jeyasekar i using Ask smart card reader i am getting UID but i am trying to read data from card i return -2146434967 this number how to i fix it

    ReplyDelete
    Replies
    1. Error code means that the smart card has been removed on the reader,
      Check this link:
      http://stackoverflow.com/a/19110907/1134291

      Delete
    2. thanks for your reply, Now I am getting error code 69 84 on read or write data in smart card how to solve this issue

      Delete
  6. Hi IJ,

    I hope you always in the great life...
    I want to ask something. How to detect card continuously then the read card data executed without clicking a login button?
    Thank you..

    ReplyDelete
    Replies
    1. Hi Duni,

      yes you can, its quite a handy work.
      will give u a hint, you have to write a event catcher for catch the change of the reader status.
      SCardGetStatusChange() method and SCARD_READERSTATE struct
      Good luck!

      Delete
    2. Hi Duni,

      this works for me enjoy

      internal enum SmartcardState
      {
      None = 0,
      Inserted = 1,
      Ejected = 2
      }


      private BackgroundWorker _worker;
      private Card.SCARD_READERSTATE[] states;

      public void SelectDevice()
      {
      List availableReaders = this.ListReaders();
      if (availableReaders.Count == 0) { return; }

      this.RdrState = new Card.SCARD_READERSTATE();
      readername = availableReaders[0].ToString();//selecting first device
      this.RdrState.RdrName = readername;

      ///
      states = new Card.SCARD_READERSTATE[1];
      states[0] = new Card.SCARD_READERSTATE();
      states[0].RdrName = readername;
      states[0].UserData = IntPtr.Zero;
      states[0].RdrCurrState = Card.SCARD_STATE_EMPTY;
      states[0].RdrEventState = 0;
      states[0].ATRLength = 0;
      states[0].ATRValue = null;


      if (availableReaders.Count > 0)
      {
      this._worker = new BackgroundWorker();
      this._worker.WorkerSupportsCancellation = true;
      this._worker.DoWork += WaitChangeStatus;
      this._worker.RunWorkerAsync();
      }

      }

      private void WaitChangeStatus(object sender, DoWorkEventArgs e)
      {
      while (!e.Cancel)
      {
      int nErrCode = Card.SCardGetStatusChange(hContext, 1000, ref states[0], 1);

      //Check if the state changed from the last time.
      if ((this.states[0].RdrEventState & 2) == 2)
      {
      //Check what changed.
      SmartcardState state = SmartcardState.None;
      if ((this.states[0].RdrEventState & 32) == 32 && (this.states[0].RdrCurrState & 32) != 32)
      {
      //The card was inserted.
      state = SmartcardState.Inserted;
      }
      else if ((this.states[0].RdrEventState & 16) == 16 && (this.states[0].RdrCurrState & 16) != 16)
      {
      //The card was ejected.
      state = SmartcardState.Ejected;
      }
      if (state != SmartcardState.None && this.states[0].RdrCurrState != 0)
      {
      switch (state)
      {
      case SmartcardState.Inserted:
      {
      MessageBox.Show("Card inserted");
      break;
      }
      case SmartcardState.Ejected:
      {
      MessageBox.Show("Card ejected");
      break;
      }
      default:
      {
      MessageBox.Show("Some other state...");
      break;
      }
      }
      }
      //Update the current state for the next time they are checked.
      this.states[0].RdrCurrState = this.states[0].RdrEventState;
      }
      }
      }

      Delete
    3. Awesome!
      Ill try this.
      Thank you Petr

      Delete
    4. You are welcome let me know if any issue

      Delete
    5. Petr Toth, thank you, I will try it...

      Delete
    6. Great code. Thanks for sharing.

      Delete
    7. Dear sir,
      64 bit system background worker is not working properly sir ...any idea ?

      Delete
  7. SendAPDUandDisplay, ClearBuffers, and AuthenticateBlock is not in current context...How should I fix that? Thank you!

    ReplyDelete
    Replies
    1. Hello Maron,
      Did you copy all the codes displayed here? I have coded SendAPDUandDisplay(), ClearBuffers() and authenticateBlock(String block) methods. Please come through the previous post and try again.
      Thanks

      Delete
  8. Hi, this article is what I'm looking for. Thanks a lot :) Btw, I'd like to automatically connect the reader and display the card UID to the textbox without pressing a button. The card UID is displayed automatically every time a new card is tapped... How can I do this?

    ReplyDelete
    Replies
    1. Hi, your question same as mine and Petr Toth already answer in this page (you can check above noted)...
      I am still trying and get error for this "The calling thread cannot access this object because a different thread owns it."...

      case SmartcardState.Inserted:
      {
      string text = verifyCard("5"); // 5 - is the block we are reading
      textBlock1.Text = text.ToString(); // error on this line

      MessageBox.Show("Card inserted");
      break;
      }

      I am still working on this and if I have the answer I let you know...

      Delete
    2. Hi all you have to create new thread

      using System.Threading;

      then

      case SmartcardState.Inserted:
      {
      //MessageBox.Show("Card inserted");
      Dispatcher.BeginInvoke(new ThreadStart(() =>
      {
      your text field or label or.Text = "Card inserted";

      }));
      break;
      }

      Delete
    3. Also i did read/write for mifare ultralight cards if this interest you let me know in this blog

      Delete
    4. Hi Petr,

      Thank you for your help... Is every card have different code (problems) to display data and read them, like mifare (I though all mifare has same code)...

      Delete
    5. This comment has been removed by the author.

      Delete
    6. Read is same for mifare standard and ultralight, only write is little bit different for ultralight.

      Delete
    7. I see... You help a lot Petr...

      It's maybe sound a silly questions for the expert, but I want to know...
      How to determine which one mifare classic with other card when the card tapped in to the reader?

      Delete
    8. Card type is include ATR string so for example:
      case SmartcardState.Inserted:
      {
      string CardType = BitConverter.ToString(states[0].ATRValue.Take(15).ToArray()).Replace("-", string.Empty);
      CardType = CardType.Substring(26, 4);
      }

      give you :
      0001 = standard
      0003 = ultralight

      Delete
    9. For another card brands you have to find out this number.

      Delete
    10. Thanks, I'll try with the Ultralight asap...

      Delete
  9. Hi, I have a solution to this one....
    You have to create a function that will set the textbox text property to show the card's UID every time a card is tapped/changed state...

    private void showTheFuckingUID()
    {
    //This function is necessary to avoid the stated error when setting the text in the TextBox property.
    //ERROR: Cross-thread operation not valid: Control 'textBlock1' accessed from a thread other than the thread it was created on.
    if (this.txtstud_No.InvokeRequired == true)
    {
    txtstud_No.Invoke(new MethodInvoker(delegate
    {
    txtstud_No.Text = getUID();
    performOperation();
    }));
    }// if (this.textBlock1.InvokeRequired == true)

    }//private void showTheFuckingUID()

    ReplyDelete
  10. You just have to call your function in the WaitChangeStatus(.......) in the SmartcardState.Inserted case :) I hope that helps.....


    private void WaitChangeStatus(object sender, DoWorkEventArgs e)
    {
    while (!e.Cancel)
    {
    int nErrCode = Card.SCardGetStatusChange(hContext, 1000, ref states[0], 1);

    //Check if the state changed from the last time.
    if ((this.states[0].RdrEventState & 2) == 2)
    {
    //Check what changed.
    SmartcardState state = SmartcardState.None;

    if ((this.states[0].RdrEventState & 32) == 32 && (this.states[0].RdrCurrState & 32) != 32)
    {
    //The card was inserted.
    state = SmartcardState.Inserted;
    }// if ((this.states[0].RdrEventState & 32) == 32 && (this.states[0].RdrCurrState & 32) != 32)

    else if ((this.states[0].RdrEventState & 16) == 16 && (this.states[0].RdrCurrState & 16) != 16)
    {
    //The card was ejected.
    state = SmartcardState.Ejected;
    }// else if ((this.states[0].RdrEventState & 16) == 16 && (this.states[0].RdrCurrState & 16) != 16)

    string stats = "";

    if (state != SmartcardState.None && this.states[0].RdrCurrState != 0)
    {
    switch (state)
    {
    case SmartcardState.Inserted:
    {
    stats = "Card State: Card INSERTED";
    showTheFuckingCardStatus(stats);//Displays the card's changed state

    showTheFuckingUID();//Displays the Card UID/Serial & the Student Details
    timeInOut();//Card Read&Write Functions
    break;
    }//case SmartcardState.Inserted:
    case SmartcardState.Ejected:
    {
    stats = "Card State: Card EJECTED";
    showTheFuckingCardStatus(stats);
    break;
    }//case SmartcardState.Ejected:
    default:
    {
    stats = "Card State: UNKNOWN STATE";
    showTheFuckingCardStatus(stats);
    break;
    }// default:
    }//switch (state)
    }//if (state != SmartcardState.None && this.states[0].RdrCurrState != 0)

    //Update the current state for the next time they are checked.
    this.states[0].RdrCurrState = this.states[0].RdrEventState;

    }// if ((this.states[0].RdrEventState & 2) == 2)

    }//while (!e.Cancel)

    }//private void WaitChangeStatus(object sender, DoWorkEventArgs e)


    private string getUID()
    {
    if (connectCard())
    {
    string cardUID = getcardUID();
    return cardUID;
    }//if (connectCard())

    else
    {
    return null;
    }//else

    }//private void getUID

    ReplyDelete
    Replies
    1. hi thank you for the code! can i have your project please. the whole vb solution. please

      Delete
  11. hi Irantha Jayasekara
    thanks for his article, it is useful for me
    i try it i am getting card uid using this code
    but when I try to read or write block textbox show me "FailAuthentication"

    i am using "acr122u" reader and card type is "Mifare Classic 1k" card

    and what is block
    submitText(TextBox1.Text, "5");

    thanks in advance.

    ReplyDelete
    Replies
    1. Hi Ketan,
      Thank you for compliment.
      Block is the where you write data in to the card. you have plenty of location in a card that you can write data. Also there are some restricted blocks you should not write in to.
      check this link for more information;
      https://learn.adafruit.com/adafruit-pn532-rfid-nfc/mifare
      Fail authentication mean you have set up key to that block earlier. Try to write in to the block 9.

      Delete
    2. thanks irantha
      i solved my problem for Mifare Classic card using mifare classic tool android app factory format.
      but now i have one another card, type is "Mifare ultralight" and i am getting same error and this android app is only for mifare classic card.
      so i can't format
      and i am use block 9 but not solve.

      max block is?
      and any idea for Mifare ultralight card?

      Delete
    3. Im sorry I didn't check with another card types.

      Delete
  12. thanks i got it my card problem if any one getting this problem than using
    mifare classic tool android app and card factory formate than you can read write your card.

    ReplyDelete
  13. Dear Irantha Jayasekara,
    First of all, Thanks for the nice article. I tried your source on another NFC reader but when I read the NFC card (MiFare 1K) it keeps display ? What should I do ?

    ReplyDelete
    Replies
    1. Im sorry, I'm not sure whether it works with another type of readers. What do you mean by it keeps display?

      Delete
  14. Can I read data via P2P insted of card blocks. I need to transfer data from a Cordova mobile application to a ACR122U and cannot use host-based card emulation. Thanks

    ReplyDelete
  15. Hi Sir,
    I can not find "winscard.dll". Please help me!

    ReplyDelete
    Replies
    1. What is your windows operating system? can you manually register winscard.dll ?
      Read more from here;
      http://www.solvusoft.com/en/files/missing-not-found-error/dll/windows/microsoft/msdn-windows-codename-whistler-personal-beta-1/winscard-dll/

      Delete
    2. Irantha, you have not been coming online like before. Pls we still need your assistant on the mifare Ultralight coding I keep getting FailAuthentiation when i try to read or write to the card.

      Delete
    3. When you have to read/write to ultralight cards you don't need to do any authentication, you can find this info here":https://learn.adafruit.com/adafruit-pn532-rfid-nfc/mifare

      Delete
  16. Hi sir,
    im getting this error code, 69 88 which is SM_INCORRECT or secure messaging data objects are incorrect can you help me solve this? thanks

    ReplyDelete
  17. Hi Irantha Jayasekara,
    I'm using ACS122u-A9. It's quite similar, reading uid works perfectly.
    Unfortunately i can't either read or write data on card, it gives me an error, it returns 0 on SCardTransmit all the time so SendAPDUandDisplay method returns -202 what is "Return bytes are not acceptable."
    error is the same if i m sending the data from textbox or no data is sent from textbox.

    Please suggest needful.

    ReplyDelete
    Replies
    1. I have the same problem. I can read the uid however whenever I try to read/write gives failauthentication error

      Delete
  18. Hi Irantha Jayasekara,

    Now i am able to READ/WRITE on the particular block of card .But the still problem is that i have to WRITE DATA on all the blocks at once and same for READ DATA at once as well.

    So if i m doing it by looping method then "FailAuthentication" error is occurring in both the cases.

    Please suggest needful in order to WRITE AND READ DATA in all blocks at once.

    ReplyDelete
    Replies
    1. Tell me how did you manage to read/write data from/on a certain block. Because I can see you had problem with authentication few days ago.

      Delete
    2. i had used above code for read and write into NFC card.

      Delete
    3. thanks for reply,
      But how did you manage to fix authentication after having the same error?

      Delete
  19. Hi, I used this code to write to blocks 1-15 and after some reading and writing the blocks fail authentication, what could have happened and how do I fix this card?

    ReplyDelete
    Replies
    1. Full code and project files https://app.box.com/s/g8jwjuiicxu8vvtyhnb7drbqh4b7jrnv

      Delete
    2. I think I know what I did. I have acidentally overwritten the keys for each block. FYI anyone else do not use blocks 0,3,7,11,15

      Delete
    3. Hi Matthew Wood,
      You mean to say we can't write data in blocks 0,3,7,11,15 because after writing data on these blocks "FailAuthentiation" error is occurring. right...?

      And if you have resolved(reset cards as default) the problem in overwritten cards then please suggest me also how to reset those as default !

      Delete
  20. Thanks very much for this post. Please i have followed your code but get FailAuthentiation each time i try to read or write to my Mifare Ultralight card. What is the problem pls. Also you can contact me for paid support on this project. Thanks

    ReplyDelete
  21. Read Function:
    what can i do read NDEF code? Thanks

    ReplyDelete
  22. thank you for your useful post. It's very helpful.
    I would like to something to ask you that How can i recover the sector after I write data into block 3 in this sector.

    ReplyDelete
    Replies
    1. You should not write data in to these blocks 0,3,7,11,15.
      I am not sure how to recover them.

      Delete
  23. How to prevent rewrite on same block that previously written data

    ReplyDelete
    Replies
    1. U can handle it by ur code, check if the block is empty, if not, write to it

      Delete
    2. sir I need Write Protected ...

      Delete
  24. Sir, I am able to write and read data in mifare 1kb card but i am unable make the card data secure.

    ReplyDelete
  25. Hi Sir,

    How to do read/write ndef block?
    thanks for you help

    ReplyDelete
  26. Great article,, Sir, i want ask, when leng character i change to be more than 16, it's can't write,,,
    how if i want to write more than 16 character??

    ReplyDelete
    Replies
    1. If you want to write more than 16 characters, you need to write to to blocks, so you have to make and custom mechanism that will divide your string into 16characters strings and write them on different blocks....

      Delete
  27. Hi guys, how do I write to an ultrahigh card?
    Any help greatly appreciated.
    Thanks

    ReplyDelete
  28. Great post, and great code. Thank you very much.

    ReplyDelete
  29. Hello how to automatically read data when i tap the card? I create a function that will send the data to textbox. My problem is where i will put the function

    ReplyDelete
  30. Thank you very much it helps me a lot
    Now i am able to READ/WRITE on the particular block of card .

    ReplyDelete
  31. Hello Sir
    when leng of character i change to be more than 16, it's can't write,,,
    how if i want to write more than 16 character??
    please ans me i a waiting for answer.....

    ReplyDelete
    Replies
    1. If you want to write more than 16 characters, you need to write to two blocks, so you have to make and custom mechanism that will divide your string into 16 characters strings and write them on different blocks. but make sure you do not write data in to these blocks 0,3,7,11,15.

      Delete
  32. This comment has been removed by the author.

    ReplyDelete
  33. Sir I am unable to Build the project. 1 Failed

    ReplyDelete
  34. Hey, I still get the FailAuthentication problem. Could somebody tell how to fix it?

    ReplyDelete
  35. Hi sir @Irantha Jayasekara. Good day, can i have your project uploaded here please. Im a first timer in this technology. Please and thank you in advance :)

    ReplyDelete
  36. Hello, Whenever I attempt to read more than two blocks in a row I get the error "The thread 0x84 has exited with code 0 (0x0)." Does anyone know how to fix this and what will allow me to read multiple blocks at what time?

    ReplyDelete
  37. This comment has been removed by the author.

    ReplyDelete
  38. Hi,
    Thank you for this awesome code.How can I change the default Authentication Key?
    Thank you

    ReplyDelete
  39. How I can get the CardUID without click button 1 ?

    ReplyDelete
  40. hi, i tried this code and got output successful... but i have one major problem... u gave this code..

    submitText(textBox1.Text, "5"); // 5 - is the block we are writing data on the card

    here it save and also read from the block"5"...

    so i tried the same method with different block's... to save multiple textbox datas...like this ..

    write operation..

    submitText(regnumber, "5");
    submitText(firstname, "6");
    submitText(lastname, "7");
    submitText(finnumber, "8");
    submitText(dt, "9");
    read operation...

    string a = verifyCard("5");
    txtShow4.Text = a.ToString();
    string b = verifyCard("6");
    txtShow3.Text = b.ToString();
    string c = verifyCard("7");
    txtShow2.Text = c.ToString();
    string d = verifyCard("8");
    txtShow1.Text = d.ToString();

    at first time it execute without any error...

    but when i tried to rewrite the datas...i mean update the data on that block's again and again..it returns "fail authentication" error.. so i tried with some other blocks...like 20,21,22,23,24,,,etc.. in all i got same error..

    pls help to overcome that problem...

    ReplyDelete
    Replies
    1. You should not write data in to these blocks 0,3,7,11,15.
      I am not sure how to recover them now.

      Delete
  41. Hi,
    Thanks for the code above . Its very helpfull to me for creating an windows form application, But now iam facing a problem.
    The code is working fine in windows form, but i used this in web application iam facing retcode=Card.SCardTransmit() getting a value of "6". why iam getting this error in web application, friends please help me to solve this issue, i already wasted a lot of time for this, now its very urgent, please help me frinds,

    Thanks

    ReplyDelete
  42. Hi Irantha Jayasekara,
    Thanks for this article. I tried and successfully read and write data to the card. But I want to trigger the data reading method at the time of tap the card on NFC reader. Now i need to click the read button for getting the data stored in the card. Please help me.

    Thanks

    ReplyDelete
  43. Hi Sir,
    Thank you for this helpful article. I already successfully display card UID without clicking a button. Right now, i'm working on multiple forms and i want to reset the device everytime i open another form. Please help me.

    Thanks

    ReplyDelete
    Replies
    1. It is really grateful if you could tell me,that how can I detect the UID of the card without clicking the button...

      Delete
  44. Hello Sir

    WIll this code work with ACS ACR1251U?

    ReplyDelete
  45. how to read and write on each and every block of nfc card in c#

    ReplyDelete
  46. What a great write up, and I can read the UID from a NTAG213 with a ACR122 Reader on Windows 10. But I can't read or write custom data to the tag all I get is "Fail Authentication" any ideas as this is so close.

    ReplyDelete
  47. Hey where can I get the full source code?

    ReplyDelete