A self-sovereign contactless payment card

transparent NFC card

Introduction

Here we describe the steps for making your own, self-sovereign, self-custodial, contactless payment card to pay with Bitcoin over the Lightning Network.

The card uses open standards throughout and contains mitigation for replay attacks.

With this setup you can use your own server to authenticate a card tap, apply custom checks as required and make payment.

Contactless payment cards use Near Field Communication (NFC) with NFC Data Exchange Format (NDEF) messaging. Normally this would transmit a static message containing a link or other data but this would not be suitable for a payment card as the card could easily be copied onto another card. The interesting thing for us about the NTAG 424 DNA card (and others) by NXP is the Secure Unique NFC (SUN) message feature. SUN enables the card to be set up with secret keys to produce a message which changes each time it is read in a predictable way that can be verified on your server before it sends the payment.

Secure Unique NFC diagram

Secure Unique NFC (SUN)

Ok - let’s make one.

Resources

Steps

Check our setup

  • start the NFC TagXplorer software
  • Connect to the NFC card reader
  • place a card on the reader and click Connect Tag
  • verify the card description
tag connected

Read the card

  • select NDEF Operations and Read NDEF
  • if you get this error, click Format NDEF and try again
bytes to read should be greater than zero
  • verify that the read completes without erroring

Start to set up the URI

  • select NTAG Operations, Mirroring Features and NTAG 424 DNA
  • set Protocol to https://
  • set URI Data to
lnurlw://card.yourdomain.com
  • select Add PICCDATA and Enable SUN Message
  • adjust the URI Data to
lnurlw://card.yourdomain.com?p=00000000000000000000000000000000&c=0000000000000000
  • click after p= and note the p_position (38 in this case)
  • click after c= and note the c_position (73 in this case)
  • select Write To Tag
NDEF message written successfully
  • now go back to NDEF Operations and Read NDEF
  • verify that the NDEF Payload Info is as expected
read payload as text

Finish setting up the URI template

  • notice that the URI shows as https://lnurlw://card ... but we want lnurlw://card ...
  • go to NTAG Operations and NTAG 424 DNA
  • select Read/Write data
  • select File No as NDEF File - 02
  • click Read
read NDEF data
  • the NDEF file is 0057D1015355046C6E75726C ....
  • look for the bytes 5504 (6 bytes from the start)
  • 04 is the code for https:// URI prepending
  • change the 04 to 00 to indicate no prepending for the URI
write NDEF data
  • click Write
  • now go back to NDEF Operations and Read NDEF
  • verify that the NDEF Payload(HEX) Info is similar to that shown
read payload as hex
  • copy the hex data and convert to text, without the 0x00 prefix
  • verify you have your expected URI data value
    Online hex to text tool
hex to text online tool

Set up the SUN authentication message

  • go to NTAG Operations and NTAG 424 DNA
  • select Security Management and click Authentiate First
success dialog
  • select Get/Change File Settings
success dialog
  • set up the values in the order shown
file and SDM options with field entry order
  • select Change File Settings
success message
  • now go back to NDEF Operations and Read NDEF
  • convert the hex data to text again
  • verify that the p and c values are non zero
  • select Read NDEF again
  • convert the hex data to text again
  • verify that the p and c values are in the right place
  • verify that the p and c values change on each read

Change the application keys

  • go to NTAG Operations and NTAG 424 DNA
  • select Security Management
  • select Authenticate
  • leave the Card Key No set to 00
  • leave the Key value set to 00000000000000000000000000000000 if not changed yet
  • click Authenticate First
success message
  • select Change Key
  • select the Card Key No to change the key value for 00 to 04
  • leave the Old Key value set to 00000000000000000000000000000000 if not changed yet
  • enter a New Key value as required
  • enter a New Key Version value of 00 or as required to keep track of your keys
  • click Change Key
success message
  • repeat this to change all 5 application keys to your own values

Using the card

  • the point-of-sale (POS) system will read the NDEF message from your card
  • for example, NDEF message is
lnurlw://card.yourdomain.com?p=A2EF40F6D46F1BB36E6EBF0114D4A464&c=F509EEA788E37E32
  • the POS will call your server here
https://card.yourdomain.com?p=A2EF40F6D46F1BB36E6EBF0114D4A464&c=F509EEA788E37E32
  • your server should verify the payment request and issue an LNURLw response

LNURLw references

LUD-01: Base LNURL encoding and decoding
LUD-03: withdrawRequest base spec.
LUD-17: Protocol schemes and raw (non bech32-encoded) URLs.

Server side verification

  • select NDEF Operations and Read NDEF
  • convert the hex data to text
  • for the p value and the SDM Meta Read Access Key value, decrypt the UID and counter
  • for the c value and the SDM File Read Access Key value, check with AES-CMAC
decrypt and cmac steps

decrypt and authenticate calculations

  • the authenticated UID and counter values can be used on your server to verify the request
  • your server should only accept an increasing counter value
  • additional validation rules can be added at your server, for example
    • an enable flag
    • payment limits
    • a list of allowed merchants
    • a verification of your location from your phone
  • your server can then make payment from your lightning node

Conclusion

We have shown that you can create your own, self-sovereign, self-custodial, contactless payment card for using Bitcoin over the Lightning Network.