本机 DESFire APDU 成帧不起作用

问题描述 投票:0回答:2

我正在使用 Galaxy A5、Android 5.0.2、SDK 21 和 Android Studio 1.1.0

Android 作为 PCD,Mifare DESFire 作为 PICC。本机 DESFire APDU 帧不起作用,但 ISO 7816-4 起作用。

示例:

MIFARE DESFire SelectApplication,AID 等于

000000h
(PICC 级别)
命令:
90 5a 00 00 03 00 00 00 00

预期回复:
91 00
.
目前的回应是
68 00

文档参考:AN11004.pdf(第33页)

void SelectApp() {
    _isoDep.connect();
    byte[] reqSelectApp = new byte[]{(byte) 0x90, (byte) 0x5A, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
    byte[] resSelectApp = _isoDep.transceive(reqSelectApp);
    _responseTextView.append(String.format("reqSelectApp: %s length:%d\n", BytesToHexStr(reqSelectApp), reqSelectApp.length));
    _responseTextView.append(String.format("resSelectApp: %s length:%d\n", BytesToHexStr(resSelectApp), resSelectApp.length));
}

String BytesToHexStr(byte[] items) {
    StringBuilder builder = new StringBuilder();
    for (byte item : items) {
        builder.append(String.format("%02X", item));
    }
    return builder.toString();
}                        

TagInfo 扫描(版本 4.11.59 [β4011059])

信息

  • IC制造商:NXP半导体
  • IC类型:未知IC

NDEF

  • 无 NFC 数据集存储:

额外

科技

  • 支持技术:
  • 兼容 ISO/IEC 14443-4(A 型)
  • 兼容 ISO/IEC 14443-3(A 型)
  • 兼容 ISO/IEC 14443-2(A 型)

  • Android技术信息: 标签说明:

  • 标签:技术 [android.nfc.tech.IsoDep,android.nfc.tech.NfcA]
    • android.nfc.tech.IsoDep
  • 最大收发长度:261字节
  • 默认最大收发超时:309 ms
  • 不支持扩展长度 APDU
    • android.nfc.tech.NFCA
  • 最大收发长度:253字节
  • 默认最大收发超时:618 ms

Android 中不存在 MIFARE Classic 支持

详细协议信息:

  • ID:04:62:26:82:8A:29:80
  • ATQA:0x4403
  • SAK:0x20
  • ATS:0x1078B3C402654B5450304432654B545000
  • 最大。接受的帧大小:256 字节(FSCI:8)
  • 支持的接收速率:106、212、424 kbit/s(DR:1、2、4)
  • 支持的发送速率:106、212、424 kbit/s(DS:1、2、4)
  • 不支持不同的发送和接收速率
  • SFGT:4.833 毫秒(SFGI:4)
  • FWT:1.237 秒(FWI:12)
  • 不支持NAD
  • 支持来电显示
  • 历史字节:0x654B5450304432654B5450 |eKTP0D2eKTP|
android nfc mifare apdu contactless-smartcard
2个回答
0
投票

虽然 ATQA/SAK 看起来好像该卡是 DESFire(这就是为什么我的 NFC TagInfo 应用程序检测到它,但应该给您一个读取错误或指示 DESFire 主应用程序的可用性),其余参数(特别是历史字节)清楚地表明这不是 DESFire 卡。

因此,不要期望卡响应 DESFire 命令(本机或包装本机)。这也与卡的行为相匹配,因为它响应

68 00
(这表明不支持 CLA 字节的编码(在您的情况下为
0x90
)。


0
投票

我找到了解决办法。所以,如果有人遇到类似的问题 代码是这样的。顺便说一句,关键在于

setTransceive
方法!?!?!!!

MyApp.TapLinx.getCustomModules().setTransceive(new MyCardApduHandler(new MyCardReader(terminal)));
desFire = DESFireFactory.getInstance().getDESFireEV2(MyApp.TapLinx.getCustomModules());
desFire.getReader().connect();

// Read UID.
byte[] uid = desFire.getUID();
// To do anything further, and unlike Android , you have to set Command Set to ISO.
desFire.setCommandSet(IDESFireEV1.CommandSet.ISO);
// Select ID app...
desFire.selectApplication(0);
// ...and so on

MyCardApduHandler
是准系统:

public class MyCardApduHandler implements IApduHandler {
    IReader reader;

    public SCardApduHandler(IReader reader) {
        this.reader = reader;
    }

    @Override
    public byte[] apduExchange(byte[] bytes) {
        return reader.transceive(bytes);
    }

    @Override
    public IReader getReader() {
        return reader;
    }
}

MyCardReader
如下:

public class MyCardReader implements IReader {
    CardTerminal mTerminal;
    CardChannel mKanal;
    Card mJavaCard;
    ProtocolDetails mProtokol;
    boolean isConnected = false;

    public SCardReader(CardTerminal terminal) {
        mTerminal = terminal;
    }

    @Override
    public byte[] transceive(byte[] bytes) {
        ResponseAPDU res;
        try {
            res = mKanal.transmit(new CommandAPDU(bytes));
        } catch (CardException e) {
            throw new NxpNfcLibException(e, e.getMessage());
        }
        return res.getBytes();
    }

    @Override
    public void connect() {
        if (!isConnected) {
            try {
                mTerminal.waitForCardPresent(0);
                mJavaCard = mTerminal.connect("*");
                mKanal = mJavaCard.getBasicChannel();
                mProtokol = new ProtocolDetails();
                mProtokol.uid = Commands.uid(mKanal);
                // TODO: Other components of the protocol.
                isConnected = true;
            } catch (CardException e) {
                throw new NxpNfcLibException(e, e.getMessage());
            }
        }
    }

    @Override
    public void close() {
        if (isConnected) {
            try {
                if (mKanal.getChannelNumber() != 0) mKanal.close();
                mJavaCard.disconnect(false);
                isConnected = false;
            } catch (Exception e) {
                throw new NxpNfcLibException(e, e.getMessage());
            }
        }
    }

    @Override
    public boolean isConnected() {
        return isConnected;
    }

    @Override
    public void setTimeout(long l) {
        throw new NotSupportedException("SCardReader: metoda setTimeout nije podržana. ");
    }

    @Override
    public long getTimeout() {
        throw new NotSupportedException("SCardReader: metoda getTimeout nije podržana. ");
    }

    @Override
    public ProtocolDetails getProtocolDetails() {
        return mProtokol;
    }
}

而且,

Commands.uid(mKanal)
是通过原始APDU实现的:

public static byte[] uid(CardChannel kanal) throws CardException, RuntimeException {
    CommandAPDU cmd = new CommandAPDU(new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 });
    ResponseAPDU res = kanal.transmit(cmd);
    if (res.getSW1() != 0x90 && res.getSW2() != 0x00) throw new RuntimeException(String.format("uid: greška SW1 SW2 = %02X %02X", res.getSW1(), res.getSW2()));
    return res.getData();
}
© www.soinside.com 2019 - 2024. All rights reserved.