Lightning payments with NFC cards - development notes
In these days of lockdown in Italy, I'm working to realize the idea I had last year of using a contactless card to pay a lightning invoice.
The process is simple: payment terminal (POS) generates the invoice and transfers it to the card to be signed, then sends the signed package to the payer node that, recognizing the signature, pays the invoice.
A lot of open-source development has been done this year, so I have plenty of exciting stuff to use as a good starting point.
First, I need a payment terminal.
Payment terminal: boost up "The Quickening".
At the Lightning conference in Berlin last year, I followed a workshop from Ben, showing us how to create a lightning payment terminal with $8 components value. It utilizes just an ESP32 microcontroller, a matrix keyboard and a TFT display. I want to keep the screen while adding an NFC chip, to allow people paying both with QR code and with the card, so let's fork it.
I summarize here the changes I've done to the project:
- I moved the check payment function, which is time-consuming, to the second core of ESP32.
- PN532 NFC module support added as a second SPI peripheral with relative library from Adafruit.
- I added support for a LED light and a buzzer to give feedbacks of the operations.
Here's the result, quite messy on the breadboard, but luckily the guys of Cryptocloaks are coming to the rescue with a 3D printed model case. It will be an NFC version of their design for the original Quickening by @cryptonobo.
Now I need to write the NFC communication part of the code between POS and card, so let's spend some words on what this card is.
NFC Java Card: not a regular office badge.
For this purpose, a card needs to be able to generate signing keys and use the private key to sign invoices.
I'm currently working with a J3H145 java card from NXP, which supports elliptic curve cryptography up to 521. I'm using 256-bit keys (sekp256k1).
These cards are programmed with an applet written in Java, a free software for the job is JCIDE.
There are some open-source signing applets, but I need a custom one to fit my use case.
The following is what, in my mind, will be the perspective of a user with his lightning card.
Setup phase, link the card to the wallet.
- Using a smartphone, a smart card reader or a future "Raspiblitz-like" NFC home node, the user initializes his white card executing an applet with these functions:
- Generate ECDSA keys and export public key to the node.
- Receive from the node his IP address and user wallet id (for multi-accounts nodes).
Once done, the card is linked to the wallet and ready to be used. Now it's time to pay an invoice and, when the user places his card on the reader, other functions come into play.
- The card receives the invoice from the POS and signs it on board.
- Signed invoice, along with node IP address and user wallet id, is sent back to the POS.
That's all for the card at the moment; an additional security feature could be a PIN to provide if the invoice is more than a certain threshold.
Which wallet to use?
The payment terminal can already operate with every wallet, I use the LNBits version for testing but also Opennode, Zap and others are available.
The card instead is a new element; therefore, we need to write the protocol to enable payments of the invoices.
I like the LndHub approach, that is open-source and manages multiple accounts on the same node.
In my vision, there won't be a lightning node each person, but reasonably one each family. It will run in ready-made boxes plugged to the wall, every home with his bank and one account each family member. I want to add payment cards to this concept.
LndHub already uses an internal database (Redis) to store data about users, so it's not a problem to store public signing key too.
Now, when payment requests come to the server, the wallet can verify if the invoice has been signed by the wallet owner's card, before paying it.
The security of the process is delegated to the strength of ECDSA signatures, and I think it will be simple for other wallets developers to add this feature.
Next steps: feedbacks and working demo
It's now time to escape virtually the lockdown and ask some feedbacks from the community.
I'm developing this project for The Lightning Foundation, whose aim is to provide access for everyone to the future global economy of Bitcoin, and I'm fascinated by the mesh nets technologies like Locha Mesh. What if not only the payer but also the recipient is offline? Can they still make a lightning transaction happen? I want to explore this idea.