【问题标题】:Java smartcardio // transmitControlCommand response is always empty // ACR 39Java smartcardio // transmitControlCommand 响应始终为空 // ACR 39
【发布时间】:2022-12-17 23:03:35
【问题描述】:

在用户vlp 提供了非常有用的提示后,我终于能够通过 java 智能卡 API (original thread) 与我的 ACR39 card reader 连接到 AT24C16 I2C card

由于我要读取的免费存储卡不是智能卡,我需要使用伪 APDU 命令通过Card.transmitControlCommand 与卡通信。读卡器附带一个很棒的documentation,其中包含我需要的所有命令(基本上我只需要读取卡上的数据)。

虽然一切似乎都工作正常,但我没有从卡或读卡器(查询固件时)得到任何响应。

我有这个:

package com.Smaca;

import java.util.List;
import javax.smartcardio.*;

public class SReader {

    public static void readCard() {

        TerminalFactory factory = TerminalFactory.getDefault();

        // GET_READER_INFORMATION
        // I believe this is the correct command - the manual specifies 11h as the last byte
        // I tried both
        byte[] GET_R_INFO = new byte[] { (byte)0xFF,(byte)0x09,(byte)0x00,(byte)0x00,(byte)0xB};
        //byte[] GET_R_INFO = new byte[] { (byte)0xFF,(byte)0x09,(byte)0x00,(byte)0x00,(byte)0x11};


        //SELECT_CARD_TYPE
        byte[] SELECT_CARD_TYPE = new byte[] { (byte)0xFF, (byte)0xA4, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x01 };
        
        //SELECT_PAGE_SIZE
        byte[] SELECT_PAGE_SIZE = new byte[] { (byte)0xFF, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x04 };

        //READ_MEMORY_CARD
        byte[] READ = new byte[] { (byte)0xFF, (byte)0xB0, (byte)0xFF, (byte)0x00, (byte)0xFF };

        int SCARD_CTL_CODE = 3500;

        try {
            List terminals = factory.terminals().list();
            CardTerminal ter = (CardTerminal)terminals.get(0);

            ter.waitForCardPresent(3000000);

            if(ter.isCardPresent())
            {
                System.out.println("Card present");

                Card ca = ter.connect("direct");
                System.out.println(ca);

                byte[] response_info = ca.transmitControlCommand(SCARD_CTL_CODE(SCARD_CTL_CODE), GET_R_INFO);
                System.out.println("Reader info: "+ bytesToHex(response_info));

                byte[] response = ca.transmitControlCommand(SCARD_CTL_CODE(SCARD_CTL_CODE), SELECT_CARD_TYPE);
                System.out.println("Select card: "+bytesToHex(response));

                byte[] response_ps = ca.transmitControlCommand(SCARD_CTL_CODE(SCARD_CTL_CODE), SELECT_PAGE_SIZE);
                System.out.println("Select page size: "+ bytesToHex(response_ps));

                byte[] response_read = ca.transmitControlCommand(SCARD_CTL_CODE(SCARD_CTL_CODE), READ);
                System.out.println("Data read: "+ bytesToHex(response_read));


            }

            System.out.println( "is Card Present: " + ((CardTerminal)terminals.get(0)).isCardPresent());


        } catch (CardException e) {
            e.printStackTrace();
        }
    }

    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte hashByte : bytes) {
            int intVal = 0xff & hashByte;
            if (intVal < 0x10) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(intVal));
        }
        return sb.toString();
    }   


    public static final int SCARD_CTL_CODE(int command) 
    {
        boolean isWindows = System.getProperty("os.name").startsWith("Windows");
        if (isWindows) {
            return 0x00310000 | (command << 2);
        } else {
            return 0x42000000 | command;
        }
    }



    public static void main(String[] args) {
        readCard();
    }
}

这是输出:

Card present
PC/SC card in ACS ACR39U ICC Reader, protocol Unknown protocol 4, state OK
Reader info: 
Select card: 
Select page size: 
Data read: 
is Card Present: true

谁能看到我做错了什么?至少 GET_READER_INFORMATION 命令应该有效?!

更新:

我想我知道问题出在哪里。我只传输了命令的原始数据,但它们需要作为 PC_to_RDR_XfrBlock 命令 (Chapter 7.1.4.) 的有效载荷传输。

不过,我在格式化命令时仍然遇到问题。 如果有人知道该怎么做,请告诉我。一个具体的例子会很棒。

谢谢! 汤姆

【问题讨论】:

  • 试试transmit而不是transmitControlCommand...
  • Card ca = ter.connect("direct"); ca.beginExclusive(); CardChannel channel = ca.getBasicChannel(); CommandAPDU apdu = new CommandAPDU(SELECT_CARD_TYPE); channel.transmit(apdu);
  • javax.smartcardio.CardException: sun.security.smartcardio.PCSCException: SCARD_E_NOT_TRANSACTED 在 java.smartcardio/sun.security.smartcardio.ChannelImpl.doTransmit(ChannelImpl.java:226) 在 java.smartcardio/sun.security.smartcardio.ChannelImpl.transmit (ChannelImpl.java:89) 在 Smaca/com.Smaca.SReader.readCard(SReader.java:50) 在 Smaca/com.Smaca.SReader.main(SReader.java:109) 引起:sun.security.smartcardio。 PCSCException:SCARD_E_NOT_TRANSACTED 在 java.smartcardio/sun.security.smartcardio.PCSC.SCardTransmit(本机方法)在 java.smartcardio/sun.security.smartcardio.ChannelImp...

标签: i2c apdu eeprom acr smartcardio


【解决方案1】:

我有同样问题的读卡器 acr39 和卡 at24

【讨论】:

    猜你喜欢
    • 2016-11-17
    • 1970-01-01
    • 2020-07-23
    • 2016-09-29
    • 2016-03-27
    • 2018-12-18
    • 2014-08-13
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多