When a card taps a phone without a corresponding app installed, the NFC feature should open a web page showing a helper app (i.e., a mobile wallet) to install for interacting with the card.
However, much more than that is possible. For example, we can show a deposit address and display the balance for a SATSCARD™, something we already do for OPENDIME® USB products.
Therefore, a dynamic NDEF response is desired.
https://
).Example: https://getsatscard.com/start#
+ DYNAMICPART
</br>
The dynamic part is: u=S&o=3&r=bcajrh2jdk&n=01020304050607&s=fefb...00
u
= State: S=sealed, U=unsealed, E=error/tampero
= Displayed slot’s slot numberr
= Address’s right-most 8 charactersn
= Card-selected nonce, in hex, 8 bytes (16 when hex-encoded)s
= Signature, 64 bytes (non-recoverable style), hex-encodedo
could be o=23
.s
field must be last, no other order is required.t
= 1
: TAPSIGNER mode is activeu
= State: S=sealed, U=unused (no key defined yet), E=error/tamperc
= 8 bytes, called card_ident
, in hex (16 chars when hex-encoded)n
= Card-selected nonce, in hex, 8 bytes (16 when hex-encoded)s
= Signature, 64 bytes (non-recoverable style), hex-encodeds
field must be last, no other order is required.card_ident
card_ident
is SHA256(card_pubkey)[0:8]
.The dynamic portion is the message being signed. It consists of everything up to and including the s=
.
u=S&o=3&r=bcajrh2jdk&n=01020304050607&s=
)u=E
if a slot or card is tampered with.On the server side (or caller’s Javascript, in-browser if possible), we will recover the public key by brute-forcing up to 4 possible values for the public key compared to the bech32 address fragment (or TAPSIGNER: pubkey hash) provided.
For SATSCARD, if the bech32 address is on testnet, additional comparisons may be required as the URL does not encode testnet status explicitly.
url
command which can be used to read the dynamic URL as if a tap had occurred.From ../cktap
, see file verify_link.py
which
implements full decode and verification, including address recovery or
card ident recovery.
>>> from cktap.verify_link import url_decoder
>>> sc='u=S&o=0&r=vekusqj5&n=8334bd83e0bb7b25&s=4d868754a6e22172977ded6b12fbf05c0b8fe16194159373125e247f4f27811d6e6fe17ef65a050799e138305239ddcb97ad124cf1ae47c45ed8dd7f875626fe'
>>> url_decoder(sc)
{'addr': 'bc1q7h0u5yn8y4pajn94ze4gnhz487c8ysvekusqj5',
'is_tapsigner': False,
'nonce': '8334bd83e0bb7b25',
'sealed': True,
'slot_num': 0,
'state': 'Sealed',
'tampered': False
}
>>> from cktap.utils import card_pubkey_to_ident
>>> card_pubkey_to_ident(b'\x02'*33)
'YTIZ2-MQZZZ-XPA2D-I5OGH'