0

I just want to get AID from scanned debit/credit card, many apps are available on Google play store that easily gets the info on scan but i am unable to get the same. The purpose of getting the AID instead of actual Card Information (Card Number , Expiry etc) is that the client has received a legal notice to use AID instead of the card info.

Here is what i've tried so far:

  • Added Service reference in Manifest file
  • Created apduservice.xml and added reference in Menifest file as available on internet.

AndroidMenifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.NFC" />

    <uses-feature
        android:name="android.hardware.nfc.hce"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.NFC"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED"/>
<!--                <action android:name="android.nfc.action.NDEF_DISCOVERED"/>-->
                <!-- Default category is required for the intent filter to work -->
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
                <!-- Default category is required for the intent filter to work -->
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
            <!-- Also register for the URL if it appears outside of NFC tags -->
        </activity>



        <service
            android:name=".NdefHostApduService"
            android:exported="true"
            android:permission="android.permission.BIND_NFC_SERVICE">
            <intent-filter>
                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />

<!--                <category android:name="android.intent.category.DEFAULT" />-->
            </intent-filter>

            <meta-data
                android:name="android.nfc.cardemulation.host_apdu_service"
                android:resource="@xml/apduservice" />
        </service>
    </application>

</manifest>

apduservice.xml

<?xml version="1.0" encoding="utf-8"?>

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/servicedesc"
    android:requireDeviceUnlock="false">
    <aid-group android:description="@string/aiddescription"
        android:category="other">
        <aid-filter android:name="A0000002471001"/>
        <aid-filter android:name="F00000000A0101"/>
<!--        <aid-filter android:name="F0010203040506"/>-->
        <aid-filter android:name="F0394148148100"/>
        <aid-filter android:name="D2760000850101"/>
        <aid-filter android:name="A0000000041010"/>
        <aid-filter android:name="A0000000031010"/> <!-- Visa -->
        <aid-filter android:name="A0000000041010"/> <!-- Mastercard -->
        <aid-filter android:name="A00000002501"/>   <!-- American Express -->
        <aid-filter android:name="A0000000042203"/> <!-- Discover -->
        <aid-filter android:name="A0000000651010"/> <!-- JCB -->
        <aid-filter android:name="A0000003330101"/> <!-- UnionPay -->


    </aid-group>
</host-apdu-service>

NdefHostApduService.java // processCommandApdu Never triggers

package com.example.nfc;

import android.content.Context;
import android.content.Intent;
import android.nfc.NdefRecord;
import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;

import java.math.BigInteger;
import java.nio.charset.Charset;

public class NdefHostApduService extends HostApduService {

    public NdefHostApduService(){

    }
    private static final String TAG = "NdefHostApduService";
    String STATUS_SUCCESS = "9000";
    String STATUS_FAILED = "6F00";
    String CLA_NOT_SUPPORTED = "6E00";
    String INS_NOT_SUPPORTED = "6D00";
    String AID = "A0000002471001";
    String SELECT_INS = "A4";
    String DEFAULT_CLA = "00";
    int MIN_APDU_LENGTH = 12;
    private static final byte[] NDEF_ID = {
            (byte)0xE1,
            (byte)0x04
    };

    private NdefRecord NDEF_URI = new NdefRecord(
            NdefRecord.TNF_WELL_KNOWN,
            NdefRecord.RTD_TEXT,
            NDEF_ID,
            "Hello world!".getBytes(Charset.forName("UTF-8"))
    );
    private byte[] NDEF_URI_BYTES = NDEF_URI.toByteArray();
    private byte[] NDEF_URI_LEN = BigInteger.valueOf(NDEF_URI_BYTES.length).toByteArray();
    @Override
    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
        // Convert the command APDU to a hexadecimal string for easier manipulation
        String commandApduHex = toHexString(commandApdu);

        // Check if the command APDU is a SELECT APDU
        if (commandApduHex.startsWith("00A404")) {
            // Extract the AID from the SELECT APDU
            String aid = commandApduHex.substring(6);
            Log.d(TAG, "Selected AID: " + aid);

            // You can further process or use the AID as needed
        }

        // Handle other APDU commands as needed

        // Return a response APDU if necessary
        return new byte[0];
    }

    @Override
    public void onDeactivated(int reason)
    {
        Log.d(TAG, "Deactivated: " + reason);
    }

    private static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
}

8
  • 1
    I don't understand what you are trying to archive with your code. The "HostApduService" class is used when you are trying to emulate a tag by Host-based Card Emulating (HCE) technology, but, as per your description, your task is to read data (AID) from an existing NFC/Credit Card. I even do not understand why your client was asked to use a generic AID instead of personalized data. If you read the AID you "only" know who issued the card (like Mastercard, Visa..). And you already know that there can be multiple AIDs on one card (e.g. one for ATM and another for buying goods) ? Commented Mar 21 at 7:50
  • I literally have no knowledge of NFC, what i've just tried is a suggestion/search from google or ChatGPT. I also have no idea why he wants to get the AID instead of personalized data. Commented Mar 21 at 7:52
  • @MichaelFehr I just want to read the AID let's say i have Visa Debit card and if someone scans the card i want to get the AID Commented Mar 21 at 7:52
  • 2
    I wrote an article series about reading of an EMV/Credit Card and you can stop with part part 1 (reading the AIDs stored on tag): medium.com/@androidcrypto/… Commented Mar 21 at 7:58
  • 1
    Thank, it's not worth to post a one liner answer :-) Commented Mar 21 at 9:52

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.