Merge pull request #1005 from iWarpBTC/ext-boltcards_keys

Boltcard ext upgrade
This commit is contained in:
Arc 2022-12-17 09:57:35 +00:00 committed by GitHub
commit 2b7c2a0c28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 147 additions and 62 deletions

View file

@ -6,26 +6,24 @@ This extension allows you to link your Bolt Card (or other compatible NXP NTAG d
**Disclaimer:** ***Use this only if you either know what you are doing or are a reckless lightning pioneer. Only you are responsible for all your sats, cards and other devices. Always backup all your card keys!***
***In order to use this extension you need to be able to setup your own card.*** That means writing a URL template pointing to your LNbits instance, configuring some SUN (SDM) settings and optionally changing the card's keys. There's a [guide](https://www.whitewolftech.com/articles/payment-card/) to set it up with a card reader connected to your computer. It can be done (without setting the keys) with [TagWriter app by NXP](https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter) Android app. Last but not least, an OSS android app by name [bolt-nfc-android-app](https://github.com/boltcard/bolt-nfc-android-app) is being developed for these purposes. It's available from Google Play [here](https://play.google.com/store/apps/details?id=com.lightningnfcapp).
***In order to use this extension you need to be able to setup your own card.*** That means writing a URL template pointing to your LNbits instance, configuring some SUN (SDM) settings and optionally changing the card's keys. There's a [guide](https://www.whitewolftech.com/articles/payment-card/) to set it up with a card reader connected to your computer. It can be done (without setting the keys) with [TagWriter app by NXP](https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter) Android app. Last but not least, an OSS android app by name [Boltcard NFC Card Creator](https://github.com/boltcard/bolt-nfc-android-app) is being developed for these purposes. It's available from Google Play [here](https://play.google.com/store/apps/details?id=com.lightningnfcapp).
## About the keys
Up to five 16-byte keys can be stored on the card, numbered from 00 to 04. In the empty state they all should be set to zeros (00000000000000000000000000000000). For this extension only two keys need to be set:
Up to five 16-byte keys can be stored on the card, numbered from 00 to 04. In the empty state they all should be set to zeros (00000000000000000000000000000000). For this extension only two keys need to be set, but for the security reasons all five keys should be changed from default (empty) state. The keys directly needed by this extension are:
One for encrypting the card UID and the counter (p parameter), let's called it meta key, key #01 or K1.
- One for encrypting the card UID and the counter (p parameter), let's called it meta key, key #01 or K1.
One for calculating CMAC (c parameter), let's called it file key, key #02 or K2.
- One for calculating CMAC (c parameter), let's called it file key, key #02 or K2.
The key #00, K0 (also know as auth key) is skipped to be use as authentification key. Is not needed by this extension, but can be filled in order to write the keys in cooperation with bolt-nfc-android-app.
The key #00, K0 (also know as auth key) is used as authentification key. It is not directly needed by this extension, but should be filled in order to write the keys in cooperation with Boltcard NFC Card Creator. In this case also K3 is set to same value as K1 and K4 as K2, so all keys are changed from default values. Keep that in your mind in case you ever need to reset the keys manually.
***Always backup all keys that you're trying to write on the card. Without them you may not be able to change them in the future!***
## Setting the card - bolt-nfc-android-app (easy way)
So far, regarding the keys, the app can only write a new key set on an empty card (with zero keys). **When you write non zero (and 'non debug') keys, they can't be rewrite with this app.** You have to do it on your computer.
- Read the card with the app. Note UID so you can fill it in the extension later.
- Write the link on the card. It shoud be like `YOUR_LNBITS_DOMAIN/boltcards/api/v1/scan/{external_id}`
- `{external_id}` should be replaced with the External ID found in the LNbits dialog.
## Setting the card - Boltcard NFC Card Creator (easy way)
Updated for v0.1.3
- Add new card in the extension.
- Set a max sats per transaction. Any transaction greater than this amount will be rejected.
@ -33,14 +31,29 @@ So far, regarding the keys, the app can only write a new key set on an empty car
- Set a card name. This is just for your reference inside LNbits.
- Set the card UID. This is the unique identifier on your NFC card and is 7 bytes.
- If on an Android device with a newish version of Chrome, you can click the icon next to the input and tap your card to autofill this field.
- Otherwise read it with the Android app (Advanced -> Read NFC) and paste it to the field.
- Advanced Options
- Card Keys (k0, k1, k2) will be automatically generated if not explicitly set.
- Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in debug mode.
- GENERATE KEY button fill the keys randomly. If there is "debug" in the card name, a debug set of keys is filled instead.
- Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in default (empty) state (this is unsecure).
- GENERATE KEY button fill the keys randomly.
- Click CREATE CARD button
- Click the QR code button next to a card to view its details. You can scan the QR code with the Android app to import the keys.
- Click the "KEYS / AUTH LINK" button to copy the auth URL to the clipboard. You can then paste this into the Android app to import the keys.
- Tap the NFC card to write the keys to the card.
- Click the QR code button next to a card to view its details. Backup the keys now! They'll be comfortable in your password manager.
- Now you can scan the QR code with the Android app (Create Bolt Card -> SCAN QR CODE).
- Or you can Click the "KEYS / AUTH LINK" button to copy the auth URL to the clipboard. Then paste it into the Android app (Create Bolt Card -> PASTE AUTH URL).
- Click WRITE CARD NOW and approach the NFC card to set it up. DO NOT REMOVE THE CARD PREMATURELY!
## Erasing the card - Boltcard NFC Card Creator
Updated for v0.1.3
Since v0.1.2 of Boltcard NFC Card Creator it is possible not only reset the keys but also disable the SUN function and do the complete erase so the card can be use again as a static tag (or set as a new Bolt Card, ofc).
- Click the QR code button next to a card to view its details and select WIPE
- OR click the red cross icon on the right side to reach the same
- In the android app (Advanced -> Reset Keys)
- Click SCAN QR CODE to scan the QR
- Or click WIPE DATA in LNbits to copy and paste in to the app (PASTE KEY JSON)
- Click RESET CARD NOW and approach the NFC card to erase it. DO NOT REMOVE THE CARD PREMATURELY!
- Now if there is all success the card can be safely delete from LNbits (but keep the keys backuped anyway; batter safe than brick).
## Setting the card - computer (hard way)
@ -48,7 +61,7 @@ Follow the guide.
The URI should be `lnurlw://YOUR-DOMAIN.COM/boltcards/api/v1/scan/{YOUR_card_external_id}?p=00000000000000000000000000000000&c=0000000000000000`
Then fill up the card parameters in the extension. Card Auth key (K0) can be omitted. Initical counter can be 0.
Then fill up the card parameters in the extension. Card Auth key (K0) can be filled in the extension just for the record. Initical counter can be 0.
## Setting the card - android NXP app (hard way)
- If you don't know the card ID, use NXP TagInfo app to find it out.
@ -70,4 +83,4 @@ Then fill up the card parameters in the extension. Card Auth key (K0) can be omi
- Save & Write
- Scan with compatible Wallet
This app afaik cannot change the keys. If you cannot change them any other way, leave them empty in the extension dialog and remember you're not secure. Card Auth key (K0) can be omitted anyway. Initical counter can be 0.
This app afaik cannot change the keys. If you cannot change them any other way, leave them empty in the extension dialog and remember you're not secured. Card Auth key (K0) can be omitted anyway. Initical counter can be 0.

View file

@ -1,21 +1,13 @@
import base64
import hashlib
import hmac
import json
import secrets
from http import HTTPStatus
from io import BytesIO
from typing import Optional
from urllib.parse import urlparse
from embit import bech32, compact
from fastapi import Request
from fastapi.param_functions import Query
from fastapi.params import Depends, Query
from lnurl import Lnurl, LnurlWithdrawResponse
from lnurl import encode as lnurl_encode # type: ignore
from lnurl.types import LnurlPayMetadata # type: ignore
from loguru import logger
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.responses import HTMLResponse
@ -33,7 +25,6 @@ from .crud import (
get_hit,
get_hits_today,
spend_hit,
update_card,
update_card_counter,
update_card_otp,
)
@ -126,8 +117,8 @@ async def lnurl_callback(
extra={"tag": "boltcard", "tag": hit.id},
)
return {"status": "OK"}
except:
return {"status": "ERROR", "reason": f"Payment failed"}
except Exception as exc:
return {"status": "ERROR", "reason": f"Payment failed - {exc}"}
# /boltcards/api/v1/auth?a=00000000000000000000000000000000

View file

@ -149,6 +149,7 @@ new Vue({
},
qrCodeDialog: {
show: false,
wipe: false,
data: null
}
}
@ -259,9 +260,10 @@ new Vue({
})
})
},
openQrCodeDialog(cardId) {
openQrCodeDialog(cardId, wipe) {
var card = _.findWhere(this.cards, {id: cardId})
this.qrCodeDialog.data = {
id: card.id,
link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp,
name: card.card_name,
uid: card.uid,
@ -272,6 +274,17 @@ new Vue({
k3: card.k1,
k4: card.k2
}
this.qrCodeDialog.data_wipe = JSON.stringify({
action: 'wipe',
k0: card.k0,
k1: card.k1,
k2: card.k2,
k3: card.k1,
k4: card.k2,
uid: card.uid,
version: 1
})
this.qrCodeDialog.wipe = wipe
this.qrCodeDialog.show = true
},
addCardOpen: function () {
@ -397,8 +410,16 @@ new Vue({
let self = this
let cards = _.findWhere(this.cards, {id: cardId})
Quasar.utils.exportFile(
cards.card_name + '.json',
this.qrCodeDialog.data_wipe,
'application/json'
)
LNbits.utils
.confirmDialog('Are you sure you want to delete this card')
.confirmDialog(
"Are you sure you want to delete this card? Without access to the card keys you won't be able to reset them in the future!"
)
.onOk(function () {
LNbits.api
.request(

View file

@ -48,6 +48,7 @@
</q-th>
<q-th auto-width></q-th>
<q-th auto-width></q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
@ -58,7 +59,7 @@
dense
icon="qr_code"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="openQrCodeDialog(props.row.id)"
@click="openQrCodeDialog(props.row.id, false)"
>
<q-tooltip>Card key credentials</q-tooltip>
</q-btn>
@ -99,7 +100,7 @@
flat
dense
size="xs"
@click="deleteCard(props.row.id)"
@click="openQrCodeDialog(props.row.id, true)"
icon="cancel"
color="pink"
>
@ -215,6 +216,7 @@
emit-value
v-model="cardDialog.data.wallet"
:options="g.user.walletOptions"
:disable="cardDialog.data.id != null"
label="Wallet *"
>
</q-select>
@ -283,7 +285,7 @@
v-model="toggleAdvanced"
label="Show advanced options"
></q-toggle>
<div v-show="toggleAdvanced">
<div v-show="toggleAdvanced" class="q-gutter-y-md">
<q-input
filled
dense
@ -358,44 +360,105 @@
<q-dialog v-model="qrCodeDialog.show" position="top">
<q-card v-if="qrCodeDialog.data" class="q-pa-lg lnbits__dialog-card">
{% raw %}
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
<qrcode
:value="qrCodeDialog.data.link"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive>
<p style="word-break: break-all" class="text-center">
(Keys for
<a
href="https://play.google.com/store/apps/details?id=com.lightningnfcapp"
target="_blank"
>bolt-nfc-android-app</a
>)
</p>
<div class="col q-mt-lg text-center">
<q-responsive
:ratio="1"
class="q-mx-xl q-mb-md"
v-show="!qrCodeDialog.wipe"
>
<qrcode
:value="qrCodeDialog.data.link"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive>
<p class="text-center" v-show="!qrCodeDialog.wipe">
(QR for <strong>create</strong> the card in
<a
href="https://play.google.com/store/apps/details?id=com.lightningnfcapp"
target="_blank"
style="color: inherit"
>Boltcard NFC Card Creator</a
>)
</p>
<q-responsive
:ratio="1"
class="q-mx-xl q-mb-md"
v-show="qrCodeDialog.wipe"
>
<qrcode
:value="qrCodeDialog.data_wipe"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive>
<p class="text-center" v-show="qrCodeDialog.wipe">
(QR for <strong>wipe</strong> the card in
<a
href="https://play.google.com/store/apps/details?id=com.lightningnfcapp"
target="_blank"
style="color: inherit"
>Boltcard NFC Card Creator</a
>)
</p>
</div>
<div class="col q-mt-md q-mb-md text-center">
<q-btn-toggle
v-model="qrCodeDialog.wipe"
rounded
unelevated
toggle-color="primary"
color="white"
text-color="primary"
:options="[
{label: 'Create', value: false},
{label: 'Wipe', value: true}
]"
/>
</div>
<p style="word-break: break-all">
<strong>Name:</strong> {{ qrCodeDialog.data.name }}<br />
<strong>UID:</strong> {{ qrCodeDialog.data.uid }}<br />
<strong>External ID:</strong> {{ qrCodeDialog.data.external_id }}<br />
<strong>Lock key:</strong> {{ qrCodeDialog.data.k0 }}<br />
<strong>Meta key:</strong> {{ qrCodeDialog.data.k1 }}<br />
<strong>File key:</strong> {{ qrCodeDialog.data.k2 }}<br />
<br />
Always backup all keys that you're trying to write on the card. Without
them you may not be able to change them in the future!<br />
<strong>Lock key (K0):</strong> {{ qrCodeDialog.data.k0 }}<br />
<strong>Meta key (K1 & K3):</strong> {{ qrCodeDialog.data.k1 }}<br />
<strong>File key (K2 & K4):</strong> {{ qrCodeDialog.data.k2 }}<br />
</p>
<p>
Always backup all keys that you're trying to write on the card. Without
them you may not be able to change them in the future!
</p>
<br />
<q-btn
unelevated
outline
color="grey"
@click="copyText(qrCodeDialog.data.link)"
label="Keys/Auth link"
label="Create link"
v-show="!qrCodeDialog.wipe"
>
<q-tooltip>Click to copy, then paste to NFC Card Creator</q-tooltip>
</q-btn>
<q-btn
unelevated
outline
color="grey"
@click="copyText(qrCodeDialog.data_wipe)"
label="Wipe data"
v-show="qrCodeDialog.wipe"
>
<q-tooltip>Click to copy, then paste to NFC Card Creator</q-tooltip>
</q-btn>
<q-btn
unelevated
outline
color="red"
@click="deleteCard(qrCodeDialog.data.id)"
label="Delete card"
v-show="qrCodeDialog.wipe"
v-close-popup
>
<q-tooltip>Backup the keys, or wipe the card first!</q-tooltip>
</q-btn>
<q-tooltip>Click to copy, then add to NFC card</q-tooltip>
{% endraw %}
<div class="row q-mt-lg q-gutter-sm">
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>

View file

@ -12,7 +12,6 @@ from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key
from . import boltcards_ext
from .crud import (
create_card,
create_hit,
delete_card,
enable_disable_card,
get_card,
@ -22,11 +21,9 @@ from .crud import (
get_hits,
get_refunds,
update_card,
update_card_counter,
update_card_otp,
)
from .models import CreateCardData
from .nxp424 import decryptSUN, getSunMAC
@boltcards_ext.get("/api/v1/cards")