I am currently trying to determine the best way to go about designing a system that integrates both barcodes and NFC passes.

The barcodes will be displayed on a phone screen. The barcode (2D, Aztec, as best for phones screens) will contain a 16 digit number which will effectively be a "pass ID", when querying the database you can see the holders name, balance etc. When this barcode is scanned, the merchant will be able to see an image of the account holder associated with the barcode to validate they are the owner. This data is obtained from a offline database (updated every 5 minutes) containing information about each pass. We could change the 16 digit number after each transaction, but as we want the NFC cards to reference the same balance, we haven't done this.

The NFC cards are new territory for me. I am familiar with common "hacks" used in Mifare classic cards, so at minimum we will use Mifare Plus cards. As far as I'm concerned, the NFC card simply needs to inform the NFC reader of its 16 digit number in the same way the barcode does so that the prepaid balance can be updated.

The worry I have with NFC cards is that the content can be cloned/edited which is far easier than it would be to do with the barcode (remember it's on a phone screen, not physical). To cheat with the barcode, you have to make an effort to obtain a visual image of someone else's pass, and even if that does happen we can simply blacklist the pass ID and refund the original owner on a new pass. With NFC I could just swipe my phone over someones pass, see their pass ID, update my pass ID and voila, I'm using their balance.

So in conclusion, I think what I am asking for is a professionals opinion as to whether I am thinking along the right lines. I appreciate I cannot just store a plain-text pass ID on the NFC card an expect no problems. I understand there has to be a form of encryption or way of preventing cloning/editing there. I would just like to know whether the concept I have provided sounds wise from a broad overview.

To be clear, the NFC cards would be optional for those that cannot display a barcode on their smartphone (e.g. the elderly, like a concessionary bus pass), as opposed to customers having both (which they could in theory, but would gain no advantage).

  • 2
    I would just like to know whether the concept I have provided sounds wise from a broad overview. What is the NFC part good for at all? And why do you think cloning NFCs is easier than cloning a visual barcode? It's not. Your swipable phone has a camera.
    – deviantfan
    Jul 26, 2016 at 0:16
  • @deviantfan For this project the elderly hold around 15-20% of the accounts used. Whilst we have a lot of students that are happy to show a barcode on their phone, it's important that we can optionally supply physical passes too, in order to ensure full up-take. With regards to it being easier to clone, I guess my point was that it's a bit more obvious with someone trying to take a picture of your barcode than it would be to sit close.
    – jskidd3
    Jul 26, 2016 at 0:24
  • 1
    Okay, I first thought you always wanted both. One or the other makes sense.
    – deviantfan
    Jul 26, 2016 at 0:25
  • 1
    @deviantfan I will update my question to make that clearer. :-)
    – jskidd3
    Jul 26, 2016 at 0:25
  • 1
    @domen Due to naivety, I'm not sure whether your comment is serious or not, but I'm going to reply to it anyway ;). Based on the fact there will be a cost reissuing cards who have had their barcodes ripped, this is why I have opted to use NFC. Different with virtual passes where a barcode can simply be updated with a download if it is blacklisted.
    – jskidd3
    Jul 26, 2016 at 16:31

4 Answers 4


NFC cards can authenticate the reader. Mifare Plus (and Classic as well, but they're broken) can implement ACLs on sectors so that a key must be presented in order to read/write a sector. You can have two different keys per sector, called key A and key B, and a bitfield controls which key can do what and whether unauthenticated access is allowed.

I believe Mifare DESFire can even do crypto on the card itself, so not only is the transport layer encrypted and the reader authenticated, the card merely proves it has the user's secret key without ever disclosing it, where as Plus and Classic are only doing authentication but then behave like dumb storage devices. Don't quote me on that though, check the datasheets for yourself.

So, if you use Mifare Plus I would recommend setting a key for the sectors holding the sensitive data, and then put there an user ID, a nonce and a MAC. The MAC should be updated each time the card is used so that even if someone manages to copy a card, they won't be able to use it if the legitimate card has been used in the meantime because the nonce would be already used, and they can't make another one because the MAC would no longer be valid.

For QR codes, never use a static code with just the user's ID. Require your mobile app to have a connection to the server, and then when used the app should request a new token from the server and only display that token. It will be one-time use only and have a limited lifetime. This is similar to the card approach above, except since the phone and POS machine don't communicate, there is no way to update the nonce and MAC, so it's better to have the phone just request a new one each time. The only time it would be acceptable to use a static ID is if you require some other method of authentication to actually use the funds from the card.

You can maintain two types of tokens, one for the NFC card and one for the phone. The NFC one would be static (user's ID) but protected by a nonce and MAC, while the phone's one is dynamic. Usage of either type shouldn't affect the other one. Also, the card doesn't even need to be aware of its balance since this is kept on the server anyway. Storing balance on the card would be an unnecessary risk no matter how good the crypto is (remember when people thought Mifare Classic was safe? Imagine the disaster if you had the balance on the card and someone figured out a way to add some hundreds to his balance...)

If you decide to go with the DESFire route and it can actually do on-card crypto, just store the user's ID and a private key on the card. On the server you keep the public key, and each time the card is used the reader should ask the card to sign a random challenge with its key, and the server can then check whether the signature is valid. Since the key is never transmitted and it's pretty much impossible to get it out, this approach is safe. That's similar to how credit cards work by the way. You can even couple this approach with having the card authenticate the reader before talking to it, just like you'd do on the Plus by setting the appropriate sector keys and ACL bits.

Finally you can periodically rotate the sector keys, on each transaction the reader tries every key used in the last X months (the lifetime of the card), and once successfully logged in it updates the card's key to the latest one. That would prevent a rogue employee having extracted the key from the POS software from copying the cards, even though the nonce + MAC would most likely defeat him anyway, but another layer of security is always good. Key rotation should be done regularly but the total number of usable keys has to remain reasonable - this should be calculated based on the maximum lifetime of a card and the acceptable transaction delay. For example, if the lifetime is a year, and you'd rotate the keys every month, the worst case scenario would be that the reader has to try the last 12 keys, which would take about a second. Adjust the values according to your requirements.

  • Thank you for your answer André. I must admit it's a little scary looking as I'm new to NFC but I will try my best to learn and understand the techniques you speak of! I would say that I disagree with not supplying static barcodes. If you take a look at Apple Wallet, the Starbucks loyalty card does exactly this. I think it's important to remember that on a phone you only access the barcode when you require, whereas a card is constantly naked. Whilst your barcode theory is more secure, it would invalidate most virtual passes that exist is in Apple Wallet/Android Pay!
    – jskidd3
    Jul 26, 2016 at 9:47
  • André, or anyone else reading the question, do you know of any resources where I can learn the basics of smartcards? E.g. sectors, keys, storage etc.
    – jskidd3
    Jul 26, 2016 at 9:50
  • 1
    @jskidd3 passes in Apple Wallet can update automatically as well. And the passes you're talking about can't be used to redeem funds, so there is no incentive to copy them, thus no security needed. If you try to redeem funds I expect them to ask for more authentication. Jul 26, 2016 at 10:51
  • @jskidd3 to start off with, smartcards are like small computers, so each one of them behaves differently. You need to refer to their respective datasheets. Jul 26, 2016 at 10:52
  • Yes that is exactly my point, our barcode passes function in the same way. The balance associated with each pass is held on a server and then passed down to wallet passes via a push notification (balance changes - send push notification). Therefore the only incentive for me to try and steal your barcode would be to get one or two free drinks before the owner reports it and the pass is blacklisted. The moment that pass is blacklisted we update the barcode, send a push notification and it's sorted. This is why I cannot see any advantage to adding extra security on the fixed barcodes.
    – jskidd3
    Jul 26, 2016 at 15:53

I'm afraid I'm not familiar with NFC, but I have some suggestion regarding the Barcode shown on the phone screen.

You can use a simple cryptographic operation to secure the Barcode before it is presented. It may be possible for the same data exchange to be presented in NFC format as well.

The main problem I see with your original suggestion is that the barcode is static. It is like a password that is never changed. The best thing would be for you add some protection against Replay Attacks, so that every time it is used legitimately, a new barcode will be needed before another transaction can be processed.

  1. The app should be pre-loaded with not only the 16 character member ID, but also a secret Salt. The Salt has to be unique per device, so when the app is installed, the device will have to be registered one-time online on your server equipment before a Salt is returned.

  2. The presented barcode generated offline contains:

    • The Device ID.
    • A counter, which is incremented for each new barcode.
    • An SHA-256 Hash value of Device ID + Counter + Secret Salt.
      • You can truncate the hash value significantly without taking a significant security hit.

When the Barcode is read at the terminal, it will

  • find the Device ID
  • compare the Counter value, and make sure it is higher than the value of the last used transaction
  • generate the Hash value to verify the authenticity of the Barcode
  • proceed with the transaction using the corresponding Member ID

If Counter is not an option for you (requires two-way sync of the terminals), you could use a date/time value instead.

In fact you can even use a combination.

There is one shortcoming which is that if a Terminal is stolen, then the Salt for all devices is stolen as well. If you wanted better security, you could use a Public/Private keypair for each device, and then hash the Encrypted Member ID using the Private Key. The Terminal would only need to store the Public Key.

  • Hi George, thanks very much for your answer. Please see my latest comment response to André's answer
    – jskidd3
    Jul 26, 2016 at 15:57
  • @jskidd3, I've read your comment in response to André suggestion that a new barcode is obtained from the server each time. However, the solution I've posted here works even offline. A connection to the internet is only required when the mobile device is initially registered. In fact, even the Terminal can be offline for a period of time as well, it just would not be able to share the latest Counter update with other Terminals in that case. Jul 26, 2016 at 16:04
  • Understood, well if that's the case I'd be naive not to use a more secure solution that doesn't hinder experience. Thanks very much! :)
    – jskidd3
    Jul 26, 2016 at 16:27
  • With your solution, do you think it would be viable to also achieve this with a physical card? As in, perhaps this solution is secure enough to ditch NFC and just use physical cards with barcodes? Actually... no I guess it won't as it requires regeneration functionality
    – jskidd3
    Jul 26, 2016 at 16:39
  • Do you think it's at all possible to ditch NFC and use barcodes on cards, or is my judgement right in that there is no way to make that secure enough?
    – jskidd3
    Jul 26, 2016 at 16:54

(Too long for a comment)

As the barcodes are displayed by phones, you might as well display unique ones for each transaction by adding sequence numbers.

This way a cloned barcode can at most be used once if the transaction is checked online; and for the offline systems, until the next data download (which includes the highest sequence for each "card").

To prevent an attacker from generating fake barcodes with new sequence numbers, you'll have to encrypt/digitally sign the barcode content, preferably using a per-user key.

A similar technique is used in the EMV contactless protocol. You might find a lot of inspirations in technical documentations of existing payment systems like this.


The best here would be using the protection on the Plus card in Security Level 1. This also means your reader don't need to support Mifare Plus, everything can be done in Classic mode.

You can then do a mutual authentication so you know the card is genuine. Note that even if a fraudster can read all the data on the card, they cannot use it.

This means using a shared key on the card to do a authentication to the reader and to the card. As the key cannot be extracted from card, the card cannot be cloned.

The same "sort" of protection could be used on the barcodes, by embedding secret data in the barcode that will be updated each transaction, and from time to time.

If you use the app to do some authentication to a API endpoint to get the updated BarcodeSecret, and also implementing the above Plus security, you won't need a picture of the holder, it will be very difficult to copy the card/barcode.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .