Get AID from Debit/Credit Card using NFC

36 Views Asked by At

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();
    }
}

0

There are 0 best solutions below