nunchuk-io / tap-protocol

Coinkite Tap Protocol
MIT License
15 stars 4 forks source link

CKTapCard::Wait causes android.nfc.TagLostException: "Tag was lost" #8

Closed PeteClubSeven closed 9 months ago

PeteClubSeven commented 10 months ago

Hi, in my Flutter plugin where I use your library to communicate with Satscards and Tapsigners I'm encountering a strange problem. I've tested a bunch of functions which seem OK but the CKTapCard::Wait() function always triggers a strange exception when sending the bytes through IsoDep.transceive(). When searching online the error message I'm receiving typically means the message wasn't formatted correctly or there was some error receiving data from the NFC device. I wanted to make sure I wasn't experiencing data corruption and the data checks out.

Here is what the debugger is showing me inside TransportImpl::Send() once I call Wait() on a newly constructed CKTapCard:

request = {std::__ndk1::vector<unsigned char, std::__ndk1::allocator<unsigned char>>} size=15
 [0] = {unsigned char} 0 '\0'
 [1] = {unsigned char} 203 '\xcb'
 [2] = {unsigned char} 0 '\0'
 [3] = {unsigned char} 0 '\0'
 [4] = {unsigned char} 10 '\n'
 [5] = {unsigned char} 161 '\xa1'
 [6] = {unsigned char} 99 'c'
 [7] = {unsigned char} 99 'c'
 [8] = {unsigned char} 109 'm'
 [9] = {unsigned char} 100 'd'
 [10] = {unsigned char} 100 'd'
 [11] = {unsigned char} 119 'w'
 [12] = {unsigned char} 97 'a'
 [13] = {unsigned char} 105 'i'
 [14] = {unsigned char} 116 't'
tap_protocol::APP_ID = {const unsigned char [15]} "\xf0CoinkiteCARDv1"
tap_protocol::SW_OKAY_1 = {const unsigned char} 144 '\x90'
tap_protocol::SW_OKAY_2 = {const unsigned char} 0 '\0'

And here is what the Java debugger shows is getting passed to IsoDep.transceive():

"data" -> {byte[15]@20966} [0, -53, 0, 0, 10, -95, 99, 99, 109, 100, 100, 119, 97, 105, 116]
 key = "data"
 value = {byte[15]@20966} [0, -53, 0, 0, 10, -95, 99, 99, 109, 100, 100, 119, 97, 105, 116]
  0 = 0
  1 = -53
  2 = 0
  3 = 0
  4 = 10
  5 = -95
  6 = 99
  7 = 99
  8 = 109
  9 = 100
  10 = 100
  11 = 119
  12 = 97
  13 = 105
  14 = 116

The Java version is a signed byte array but it is a binary match. Interestingly when I send the command the auth delay does actually decrease by one (as shown by subsequent Status commands), however we never actually receive a valid response from the CKTapCard. I've tested the following functions and none of them cause an Android exception to be thrown:

I will continue investigating, potentially checking different SDK versions but I really can't see why this is an issue. Currently I'm testing with a Fairphone 4 running Android 12 and my app is using SDK version 31 with NDK version 21.4.7075529.

PeteClubSeven commented 9 months ago

Hey just an update here. I couldn't find anything wrong but then I noticed that on my Android device when tapping a Satscard apparently the IsoDep.Timeout property on my device shows a timeout of 618 milliseconds which isn't long enough to perform the 1-second wait command. That would mean it's not really something you can influence because that's decided by the card protocol itself.