Java 卡的PSE不是它应该是什么

Java 卡的PSE不是它应该是什么,java,smartcard,contactless-smartcard,emv,Java,Smartcard,Contactless Smartcard,Emv,所以,我有一张非接触式万事达卡和一部Visa paywave手机。 我使用非接触式HID万能钥匙5427 CK 这是我的代码:` static boolean cardReading = true; public static void main(String[] args) throws CardException, UnsupportedEncodingException { while (cardReading == true) { try { Termina

所以,我有一张非接触式万事达卡和一部Visa paywave手机。 我使用非接触式HID万能钥匙5427 CK

这是我的代码:`

static boolean cardReading = true;

public static void main(String[] args) throws CardException, UnsupportedEncodingException {

    while (cardReading == true) {

    try {
    TerminalFactory factory = TerminalFactory.getDefault();
    List<CardTerminal> terminals = factory.terminals().list();
    CardTerminal terminal = terminals.get(0);

    if (!terminal.isCardPresent()) {

        continue;

    }

    System.out.println("Terminals: " + terminals);
    System.out.println("Used terminal: " + terminal);

    Card card = terminal.connect("T=0");
    System.out.println("\n\nInserted card: " + card);
    CardChannel channel = card.getBasicChannel();

    String pse = "00A404000E325041592E5359532E444446303100";
    CommandAPDU apdu = new CommandAPDU(pse.getBytes());
    ResponseAPDU r = channel.transmit(apdu);

    System.out.println("Response: " + toHex(r.getData().toString()) + " " + r);
    System.out.println("ADPU: " + toHex(apdu.getBytes().toString()) + " " + r.getSW() + " " + r.getSW1() + " " + r.getSW2() + " " + r.getNr());

    apdu = new CommandAPDU((byte)0x00, (byte)0xB2, (byte)0x01, (byte)0x0C, (byte)0x00);
    r = channel.transmit(apdu);

    cardReading = false;
    Toolkit.getDefaultToolkit().beep();

    System.out.println("Terminals: " + terminals);
    System.out.println("Used terminal: " + terminal);
    System.out.println("\n\nInserted card: " + card);
    System.out.println("Response: " + toHex(r.getData().toString()) + " " + r);
    System.out.println("ADPU: " + toHex(apdu.getBytes().toString()) + " " + r.getSW() + " " + r.getSW1() + " " + r.getSW2() + " " + r.getNr());



    System.exit(1);

    } catch(Exception e) {

        continue;

    }

    }

}

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

public static String toHex(String arg) {
    return String.format("%040x", new BigInteger(1, arg.getBytes()));
}
我不明白为什么回复0000000000000000005b42403565616235383039。。。 请帮忙

你好,弗拉德。

正如迈克尔·罗兰所说——你对十六进制字符串的处理是错误的

元错误1:使用“byte[].toString()”

r.getData().toString()
String pse = "00A404000E325041592E5359532E444446303100";
CommandAPDU apdu = new CommandAPDU(pse.getBytes());
byte[].toString
使用默认的
Object.toString()
实现,该实现返回类名后跟
@
Object.hashCode()
的值(例如
)[B@312b1dae“
)--这不是您要进一步处理的内容

您可以使用
Arrays.toString()
方法(不进行十六进制转储),或

元错误2:使用“String.getBytes()”

r.getData().toString()
String pse = "00A404000E325041592E5359532E444446303100";
CommandAPDU apdu = new CommandAPDU(pse.getBytes());
不创建所需的APDU对象,因为方法
String.getBytes()
不执行十六进制转换,而是在平台的默认字符集中进行字符集转换,例如:
“1234”。getBytes()
给出
{0x31、0x32、0x33、0x34}
(而不是您可能期望的
{0x12、0x34}

下面是一个简单的代码示例,其执行(几乎)与您的代码相同:

package test.java.so;

import java.util.List;

import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;

import org.apache.commons.codec.binary.Hex;

@SuppressWarnings("restriction")
public class So39543402 {

    public static void main(String[] args) throws Exception {
                TerminalFactory factory = TerminalFactory.getDefault();
                List<CardTerminal> terminals = factory.terminals().list();
                CardTerminal terminal = terminals.get(0);

                Card card = terminal.connect("*");
                CardChannel channel = card.getBasicChannel();

                String pse = "00A404000E325041592E5359532E444446303100";
                CommandAPDU apdu = new CommandAPDU(Hex.decodeHex(pse.toCharArray()));
                exchangeApdu(channel, apdu);

                apdu = new CommandAPDU(0x00, 0xB2, 0x01, 0x0C, 256);
                exchangeApdu(channel, apdu);
    }

    private static ResponseAPDU exchangeApdu(CardChannel channel, CommandAPDU apdu) throws javax.smartcardio.CardException {
        System.out.println("APDU: " + Hex.encodeHexString(apdu.getBytes()));
        ResponseAPDU r = channel.transmit(apdu);
        System.out.println("Response: " + Hex.encodeHexString(r.getBytes()));
        return r;
    }

}
package test.java.so;
导入java.util.List;
导入javax.smartcardio.Card;
导入javax.smartcardio.CardChannel;
导入javax.smartcardio.CardTerminal;
导入javax.smartcardio.CommandAPDU;
导入javax.smartcardio.responseADU;
导入javax.smartcardio.TerminalFactory;
导入org.apache.commons.codec.binary.Hex;
@禁止警告(“限制”)
公共类So39543402{
公共静态void main(字符串[]args)引发异常{
TerminalFactory=TerminalFactory.getDefault();
列表端子=工厂.terminals().List();
CardTerminal=terminals.get(0);
卡=终端。连接(“*”);
CardChannel=card.getBasicChannel();
字符串pse=“00A404000E325041592E5359532E44446303100”;
CommandAPDU apdu=newcommandapdu(Hex.decodeHex(pse.toCharArray());
exchangeApdu(通道,apdu);
apdu=新命令apdu(0x00、0xB2、0x01、0x0C、256);
exchangeApdu(通道,apdu);
}
私有静态响应EAPDU exchangeApdu(CardChannel通道,CommandAPDU apdu)引发javax.smartcardio.CardException{
System.out.println(“APDU:+Hex.encodeHexString(APDU.getBytes()));
ResponseADU r=信道传输(apdu);
System.out.println(“响应:+Hex.encodeHexString(r.getBytes()));
返回r;
}
}
请注意一些有趣的部分:

  • 此代码用于十六进制转换

  • 参数
    “*”
    用于
    CardTerminal.connect()
    ,它比总是请求
    T=0
    协议更通用

  • 您的
    读取记录
    APDU被修改为需要256字节的响应数据--(您的代码将生成一个ISO case 1命令APDU,这可能不是您想要的)

另一项说明:

  • 不要使用不带参数的
    String.getBytes()
    方法(即使您确实希望将单个字符转换为字节)。始终指定所需的字符集(例如“US-ASCII”、“UTF-8”)
祝你好运!

正如迈克尔·罗兰所说——你对十六进制字符串的处理是错误的

元错误1:使用“byte[].toString()”

r.getData().toString()
String pse = "00A404000E325041592E5359532E444446303100";
CommandAPDU apdu = new CommandAPDU(pse.getBytes());
byte[].toString
使用默认的
Object.toString()
实现,该实现返回类名后跟
@
Object.hashCode()
的值(例如
)[B@312b1dae“
)--这不是您要进一步处理的内容

您可以使用
Arrays.toString()
方法(不进行十六进制转储),或

元错误2:使用“String.getBytes()”

r.getData().toString()
String pse = "00A404000E325041592E5359532E444446303100";
CommandAPDU apdu = new CommandAPDU(pse.getBytes());
不创建所需的APDU对象,因为方法
String.getBytes()
不执行十六进制转换,而是在平台的默认字符集中进行字符集转换,例如:
“1234”。getBytes()
给出
{0x31、0x32、0x33、0x34}
(而不是您可能期望的
{0x12、0x34}

下面是一个简单的代码示例,其执行(几乎)与您的代码相同:

package test.java.so;

import java.util.List;

import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;

import org.apache.commons.codec.binary.Hex;

@SuppressWarnings("restriction")
public class So39543402 {

    public static void main(String[] args) throws Exception {
                TerminalFactory factory = TerminalFactory.getDefault();
                List<CardTerminal> terminals = factory.terminals().list();
                CardTerminal terminal = terminals.get(0);

                Card card = terminal.connect("*");
                CardChannel channel = card.getBasicChannel();

                String pse = "00A404000E325041592E5359532E444446303100";
                CommandAPDU apdu = new CommandAPDU(Hex.decodeHex(pse.toCharArray()));
                exchangeApdu(channel, apdu);

                apdu = new CommandAPDU(0x00, 0xB2, 0x01, 0x0C, 256);
                exchangeApdu(channel, apdu);
    }

    private static ResponseAPDU exchangeApdu(CardChannel channel, CommandAPDU apdu) throws javax.smartcardio.CardException {
        System.out.println("APDU: " + Hex.encodeHexString(apdu.getBytes()));
        ResponseAPDU r = channel.transmit(apdu);
        System.out.println("Response: " + Hex.encodeHexString(r.getBytes()));
        return r;
    }

}
package test.java.so;
导入java.util.List;
导入javax.smartcardio.Card;
导入javax.smartcardio.CardChannel;
导入javax.smartcardio.CardTerminal;
导入javax.smartcardio.CommandAPDU;
导入javax.smartcardio.responseADU;
导入javax.smartcardio.TerminalFactory;
导入org.apache.commons.codec.binary.Hex;
@禁止警告(“限制”)
公共类So39543402{
公共静态void main(字符串[]args)引发异常{
TerminalFactory=TerminalFactory.getDefault();
列表端子=工厂.terminals().List();
CardTerminal=terminals.get(0);
卡=终端。连接(“*”);
CardChannel=card.getBasicChannel();
字符串pse=“00A404000E325041592E5359532E44446303100”;
CommandAPDU apdu=newcommandapdu(Hex.decodeHex(pse.toCharArray());
exchangeApdu(通道,apdu);
apdu=新命令apdu(0x00、0xB2、0x01、0x0C、256);
exchangeApdu(通道,apdu);
}
私有静态响应EAPDU exchangeApdu(CardChannel通道,CommandAPDU apdu)引发javax.smartcardio.CardException{
System.out.println(“APDU:+Hex.encodeHexString(APDU.getBytes()));
ResponseADU r=信道传输(apdu);
System.out.println(“响应:+Hex.encodeHexString(r.getBytes()));
返回r;
}
}