diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index f938eec..1fabb30 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/de/androidcrypto/talktoyourcreditcard/MainActivity.java b/app/src/main/java/de/androidcrypto/talktoyourcreditcard/MainActivity.java
index 99e02e8..58b8f7a 100644
--- a/app/src/main/java/de/androidcrypto/talktoyourcreditcard/MainActivity.java
+++ b/app/src/main/java/de/androidcrypto/talktoyourcreditcard/MainActivity.java
@@ -15,6 +15,7 @@
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -54,7 +55,7 @@
public class MainActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback {
private final String TAG = "MainAct";
- private com.google.android.material.textfield.TextInputEditText etLog;
+ private com.google.android.material.textfield.TextInputEditText etData, etLog;
private View loadingLayout;
private NfcAdapter mNfcAdapter;
@@ -71,6 +72,7 @@ protected void onCreate(Bundle savedInstanceState) {
Toolbar myToolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(myToolbar);
+ etData = findViewById(R.id.etData);
etLog = findViewById(R.id.etLog);
loadingLayout = findViewById(R.id.loading_layout);
@@ -91,7 +93,7 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onTagDiscovered(Tag tag) {
- clearData(etLog);
+ clearData();
Log.d(TAG, "NFC tag discovered");
writeToUiAppend("NFC tag discovered");
playPing();
@@ -117,6 +119,7 @@ public void onTagDiscovered(Tag tag) {
// here we are going to start our journey through the card
printStepHeader(0, "our journey begins");
+ writeToUiAppend(etData, "00 reading of the card started");
writeToUiAppend("increase IsoDep timeout for long reading");
writeToUiAppend("timeout old: " + nfc.getTimeout() + " ms");
@@ -134,6 +137,7 @@ public void onTagDiscovered(Tag tag) {
byte[] selectPpseResponse = nfc.transceive(selectPpseCommand);
writeToUiAppend("01 select PPSE command length " + selectPpseCommand.length + " data: " + bytesToHexNpe(selectPpseCommand));
writeToUiAppend("01 select PPSE response length " + selectPpseResponse.length + " data: " + bytesToHexNpe(selectPpseResponse));
+ writeToUiAppend(etData, "01 select PPSE completed");
writeToUiAppend(prettyPrintDataToString(selectPpseResponse));
byte[] selectPpseResponseOk = checkResponse(selectPpseResponse);
@@ -144,6 +148,7 @@ public void onTagDiscovered(Tag tag) {
* step 1 code end
*/
+ /*
// get the tags from respond
BerTlvParser parserA = new BerTlvParser();
BerTlvs tlvs = parserA.parse(selectPpseResponseOk, 0, selectPpseResponseOk.length);
@@ -159,6 +164,8 @@ public void onTagDiscovered(Tag tag) {
}
+ */
+
/*
// devnied
writeToUiAppend("");
@@ -186,7 +193,7 @@ public void onTagDiscovered(Tag tag) {
* step 2 code start
*/
- writeToUiAppend("");
+ //writeToUiAppend("");
printStepHeader(2, "search applications on card");
writeToUiAppend("02 analyze select PPSE response and search for tag 0x4F (applications on card)");
@@ -206,6 +213,7 @@ public void onTagDiscovered(Tag tag) {
aidList.add(tlv4fBytes);
writeToUiAppend("application Id (AID): " + bytesToHexNpe(tlv4fBytes));
}
+ writeToUiAppend(etData, "02 analyze select PPSE response completed");
/**
* step 2 code end
@@ -227,14 +235,14 @@ public void onTagDiscovered(Tag tag) {
writeToUiAppend("03 select AID command length " + selectAidCommand.length + " data: " + bytesToHexNpe(selectAidCommand));
writeToUiAppend("03 select AID response length " + selectAidResponse.length + " data: " + bytesToHexNpe(selectAidResponse));
writeToUiAppend(prettyPrintDataToString(selectAidResponse));
-
+ writeToUiAppend(etData, "03 select AID completed");
//}
/**
* step 3 code end
*/
// intermediate step - get single data from card, will be printed later
- writeToUiAppend("");
+ //writeToUiAppend("");
writeToUiAppend("get single data elements");
byte[] applicationTransactionCounter = getApplicationTransactionCounter(nfc);
byte[] pinTryCounter = getPinTryCounter(nfc);
@@ -242,12 +250,14 @@ public void onTagDiscovered(Tag tag) {
byte[] logFormat = getLogFormat(nfc);
// print single data
writeToUiAppend(dumpSingleData(applicationTransactionCounter, pinTryCounter, lastOnlineATCRegister, logFormat));
- writeToUiAppend("");
- // todo remove code
+ /*
+ // does not work on my cards
byte[] challenge8Byte = getChallenge(nfc);
writeToUiAppend("challenge length: " + challenge8Byte.length + " data: " + bytesToHexNpe(challenge8Byte));
+ */
+
/**
* step 4 code start
@@ -255,7 +265,7 @@ public void onTagDiscovered(Tag tag) {
byte[] selectAidResponseOk = checkResponse(selectAidResponse);
if (selectAidResponseOk != null) {
- writeToUiAppend("");
+ //writeToUiAppend("");
printStepHeader(4, "search for tag 0x9F38");
writeToUiAppend("04 search for tag 0x9F38 in the selectAid response");
/**
@@ -265,13 +275,14 @@ public void onTagDiscovered(Tag tag) {
*/
BerTlvs tlvsAid = parser.parse(selectAidResponseOk);
BerTlv tag9f38 = tlvsAid.find(new BerTag(0x9F, 0x38));
+ writeToUiAppend(etData, "04 search for tag 0x9F38 in the selectAid response completed");
byte[] gpoRequestCommand;
if (tag9f38 != null) {
/**
* the following code is for VisaCards and (German) GiroCards as we found a PDOL
*/
writeToUiAppend("");
- writeToUiAppend("### processing the VisaCard and GiroCard path ###");
+ writeToUiAppend("### processing the America Express, VisaCard and GiroCard path ###");
writeToUiAppend("");
byte[] pdolValue = tag9f38.getBytesValue();
/*
@@ -293,8 +304,6 @@ public void onTagDiscovered(Tag tag) {
"] length " + String.valueOf(pdolEntry.getLength()));
}
- // todo show contents from pdol request returned with tags (just a dump)
- // take pdol + command, extract data
gpoRequestCommand = getGpoFromPdol(pdolValue);
//gpoRequestCommand = getGetProcessingOptionsFromPdol(pdolValue); // not working for DKB Visa
@@ -322,7 +331,7 @@ public void onTagDiscovered(Tag tag) {
writeToUiAppend(pdolRequestString);
}
- writeToUiAppend("");
+ //writeToUiAppend("");
printStepHeader(5, "get the processing options");
writeToUiAppend("05 get the processing options command length: " + gpoRequestCommand.length + " data: " + bytesToHexNpe(gpoRequestCommand));
@@ -340,6 +349,7 @@ public void onTagDiscovered(Tag tag) {
byte[] gpoRequestResponse = nfc.transceive(gpoRequestCommand);
byte[] gpoRequestResponseOk;
+ writeToUiAppend(etData, "05 get the processing options completed");
if (gpoRequestResponse != null) {
writeToUiAppend("05 get the processing options response length: " + gpoRequestResponse.length + " data: " + bytesToHexNpe(gpoRequestResponse));
gpoRequestResponseOk = checkResponse(gpoRequestResponse);
@@ -382,8 +392,13 @@ public void onTagDiscovered(Tag tag) {
BerTlv tag57 = tlvsGpo.find(new BerTag(0x57));
if (tag57 != null) {
- writeToUiAppend("");
+ //writeToUiAppend("");
writeToUiAppend("workflow a)");
+ writeToUiAppend("");
+ printStepHeader(6, "read files & search PAN");
+ writeToUiAppend("06 read the files from card skipped");
+ writeToUiAppend(etData, "06 read the files from card skipped");
+
writeToUiAppend("the response contains a Track 2 Equivalent Data tag [tag 0x57]");
byte[] gpoResponseTag57 = tag57.getBytesValue();
writeToUiAppend("found tag 0x57 in the gpoResponse length: " + gpoResponseTag57.length + " data: " + bytesToHexNpe(gpoResponseTag57));
@@ -393,9 +408,14 @@ public void onTagDiscovered(Tag tag) {
writeToUiAppend("");
printStepHeader(7, "print PAN & expire date");
writeToUiAppend("07 get PAN and Expiration date from tag 0x57 (Track 2 Equivalent Data)");
- writeToUiAppend("data for AID " + aidSelected);
+ writeToUiAppend(etData, "07 get PAN and Expiration date from tag 0x57 (Track 2 Equivalent Data) completed");
+ writeToUiAppend("data for AID " + bytesToHexNpe(aidSelected));
writeToUiAppend("PAN: " + pan);
- writeToUiAppend("Expiration date (YYMM): " + expDate);
+ String expirationDateString = "Expiration date (" + (expDate.length() == 4 ? "YYMM): " : "YYMMDD): ") + expDate;
+ writeToUiAppend(expirationDateString);
+ writeToUiAppend(etData, "data for AID " + bytesToHexNpe(aidSelected));
+ writeToUiAppend(etData,"PAN: " + pan);
+ writeToUiAppend(etData, expirationDateString);
writeToUiAppend("");
}
@@ -409,7 +429,7 @@ public void onTagDiscovered(Tag tag) {
BerTlv tag80 = tlvsGpo.find(new BerTag(0x80));
if (tag80 != null) {
- writeToUiAppend("");
+ //writeToUiAppend("");
writeToUiAppend("workflow b)");
writeToUiAppend("the response is of type 'Response Message Template Format 1' [tag 0x80]");
byte[] gpoResponseTag80 = tag80.getBytesValue();
@@ -427,7 +447,7 @@ public void onTagDiscovered(Tag tag) {
BerTlv tag77 = tlvsGpo.find(new BerTag(0x77));
if (tag77 != null) {
- writeToUiAppend("");
+ //writeToUiAppend("");
writeToUiAppend("workflow c)");
writeToUiAppend("the response is of type 'Response Message Template Format 2' [tag 0x77]");
writeToUiAppend("found tag 0x77 in the gpoResponse");
@@ -442,6 +462,10 @@ public void onTagDiscovered(Tag tag) {
writeToUiAppend("");
writeToUiAppend("found this AFL data in the gpoResponse to read from: " + bytesToHexNpe(aflBytes));
+ writeToUiAppend("");
+ printStepHeader(6, "read files & search PAN");
+ writeToUiAppend("06 read the files from card and search for PAN & Expiration date");
+ writeToUiAppend(etData, "06 read the files from card and search for PAN & Expiration date");
List tag94BytesList = divideArray(aflBytes, 4);
int tag94BytesListLength = tag94BytesList.size();
@@ -513,10 +537,14 @@ public void onTagDiscovered(Tag tag) {
writeToUiAppend("");
printStepHeader(7, "print PAN & expire date");
writeToUiAppend("07 get PAN and Expiration date from tags 0x5a and 0x5f24");
+ writeToUiAppend(etData, "07 get PAN and Expiration date from tags 0x5a and 0x5f24 completed");
writeToUiAppend("data for AID " + bytesToHexNpe(aidSelected));
writeToUiAppend("PAN: " + readRecordPanString);
- // todo yymmdd or yymm depending on length
- writeToUiAppend("Expiration date (YYMM): " + readRecordExpirationDateString);
+ String expirationDateString = "Expiration date (" + (readRecordExpirationDateString.length() == 4 ? "YYMM): " : "YYMMDD): ") + readRecordExpirationDateString;
+ writeToUiAppend(expirationDateString);
+ writeToUiAppend(etData, "data for AID " + bytesToHexNpe(aidSelected));
+ writeToUiAppend(etData,"PAN: " + readRecordPanString);
+ writeToUiAppend(etData, expirationDateString);
writeToUiAppend("");
}
} catch (RuntimeException e) {
@@ -563,7 +591,7 @@ public void onTagDiscovered(Tag tag) {
* step 4 code end
*/
-
+ writeToUiAppend(etData, lineSeparatorString);
} // for (int aidNumber = 0; aidNumber < tag4fList.size(); aidNumber++) {
/**
@@ -578,6 +606,7 @@ public void onTagDiscovered(Tag tag) {
}
printStepHeader(99, "our journey ends");
+ writeToUiAppend(etData, "99 reading of the card completed");
vibrate();
@@ -1342,19 +1371,37 @@ public static String trimLeadingLineFeeds(String input) {
return output.length > 1 ? output[1] : output[0];
}
- private void clearData(final TextView textView) {
+ private void clearData() {
runOnUiThread(() -> {
outputString = "";
exportString = "";
- textView.setText("");
+ etData.setText("");
+ etLog.setText("");
});
}
private void writeToUiAppend(String message) {
- System.out.println(message);
+ //System.out.println(message);
outputString = outputString + message + "\n";
}
+ private void writeToUiAppend(final TextView textView, String message) {
+ runOnUiThread(() -> {
+ if (TextUtils.isEmpty(textView.getText().toString())) {
+ if (textView == (TextView) etLog) {
+ } else {
+ textView.setText(message);
+ }
+ } else {
+ String newString = textView.getText().toString() + "\n" + message;
+ if (textView == (TextView) etLog) {
+ } else {
+ textView.setText(newString);
+ }
+ }
+ });
+ }
+
private void writeToUiFinal(final TextView textView) {
if (textView == (TextView) etLog) {
runOnUiThread(new Runnable() {
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index e692bef..eeb0c90 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -66,6 +66,33 @@
+
+
+
+
+