0

I try to emulate emv card on Android device. And it will be read on acr1252 over some software. It's work fine, software can read card but identifies like token, but in emv answer I set it like physical card.

AndroidManifest.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"
    package="com.ptks.cardEmulator">

    <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
    <uses-permission android:name="android.permission.NFC" />
    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
    <uses-feature android:name="android.hardware.nfc" android:required="false" />



    <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.Android_CardEmulator"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:directBootAware="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
            </intent-filter>
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/usb_device_filter" />

        </activity>



        <service
            android:name=".MyHostApduService"
            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>


        <service
            android:name=".UsbService"
            android:enabled="true">
        </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/service_description"
    android:requireDeviceUnlock="false">
    <aid-group
        android:description="@string/aid_group_description"
        android:category="payment">
        <aid-filter android:name="A0000000041010" />
        <aid-filter android:name="A0000000031010" />
    </aid-group>
</host-apdu-service>

Please, help, how to correct sent that I "use" physical card? Thanks!

P.S. HostApduService:

    package com.cardEmulator;

import static com.cardEmulator.MainActivity.changeNfcEnabled;

import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
import android.util.Log;

public class MyHostApduService extends HostApduService {

    private byte[] hexToBinary(String s) {


        byte[] data = new byte[s.length()/2];

        for( int i=0, j=0;
             i<s.length() && j<data.length;
             i+=2, j++)
        {


            if ((byte)Integer.parseInt(s.substring(i, i+2), 16) >=0 && (byte)Integer.parseInt(s.substring(i, i+2), 16)<16)
                data[j] = (byte) (0 + (byte)Integer.parseInt(s.substring(i, i+2), 16));
            else
                data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
        }

        return data;
    }


    @Override
    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {

        Log.d("chrome", "Get command from card: ");



        String getReq = "";

        for (int i = 0; i<=commandApdu.length-1; i++)
            getReq+=String.format("%02x", commandApdu [i]);


            Log.d("chrome", getReq);

if (getReq.toLowerCase().contains("00A4040007A00000000".toLowerCase())) {
  
    Log.d("chrome", "Send first answer");

    sendResponseApdu(hexToBinary("6F23840E325041592E5359532E4444463031A511BF0C0E610C4F07A00000000410108701019000"));
}


if (getReq.toLowerCase().contains("80a8000002830000".toLowerCase())) {
    sendResponseApdu(hexToBinary("771282021980940C0000000000000000000000009000"));
  
}
        Globals.curCard = "5167803202840547";

        if (getReq.toLowerCase().contains("00b2000400".toLowerCase()))
            sendResponseApdu(hexToBinary("7081A657135167803202840547D24112010000000001960F5A0851678032028405475F24032411305F25031911015F280208045F3401018C279F02069F03069F1A0295055F2A029A039C019F37049F35019F45029F4C089F34039F21039F7C148D0C910A8A0295059F37049F4C088E0E000000000000000042031E031F039F0702FFC09F080200029F0D05B4508400009F0E0500000000009F0F05B4708480009F420209809F4A01829000"));


        if (getReq.toLowerCase().contains("00b2011400".toLowerCase()))
            sendResponseApdu(hexToBinary("7081A657135167803202840547D24112010000000001960F5A0851678032028405475F24032411305F25031911015F280208045F3401018C279F02069F03069F1A0295055F2A029A039C019F37049F35019F45029F4C089F34039F21039F7C148D0C910A8A0295059F37049F4C088E0E000000000000000042031E031F039F0702FFC09F080200029F0D05B4508400009F0E0500000000009F0F05B4708480009F420209809F4A01829000"));
       

if (getReq.toLowerCase().equals("80ca9f7f00".toLowerCase()))

           sendResponseApdu(hexToBinary( "9F7F08425032729000" ));

        return null;
    }

    @Override
    public void onDeactivated(int reason) {

        Log.d("chrome", "Communication with the card reader is interrupted!!!");

    }
}
  • On what point you identify an answer as "token" and not "physical" ? What should be the correct response ? And, I'm sorry, the answer to your question seems to be in that part of code you are hidding. Maybe it is, as always, the error in code line "42" :-) – Michael Fehr Jul 31 '23 at 18:41
  • As I wrote - I test with acr1252 over some software (not my). This software is identifies like token. I don't know how – Николай Деменков Jul 31 '23 at 19:30
  • "I try to emulate emv card on Android device" means that the emulating part is done by YOUR software that produces a "token" instead of "physical", right ?Please show us your code so we are been able to reproduce the activity of your software. A lot of guys are willing to help but. everyone needs input. to work on and not only some send and response exchange data. – Michael Fehr Jul 31 '23 at 22:28
  • Thanks for answer, I update main post – Николай Деменков Aug 01 '23 at 20:46

0 Answers0