gpt4 book ai didi

java - 卡的 PSE 不是它应该的样子

转载 作者:行者123 更新时间:2023-12-02 03:21:36 26 4
gpt4 key购买 nike

所以,我有一张非接触式万事达卡和一部 Visa 付费电话。我使用非接触式 HID Omnikey 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()));
}

`

所以输出是:

Terminals: [PC/SC terminal HID OMNIKEY 5427 CK 0]
Used terminal: PC/SC terminal HID OMNIKEY 5427 CK 0


Inserted card: PC/SC card in HID OMNIKEY 5427 CK 0, protocol T=0, state OK
Response: 0000000000000000005b42403163343630306630 ResponseAPDU: 65 bytes, SW=9000
ADPU: 000000000000000000005b424035623665663230 36864 144 0 63
Terminals: [PC/SC terminal HID OMNIKEY 5427 CK 0]
Used terminal: PC/SC terminal HID OMNIKEY 5427 CK 0


Inserted card: PC/SC card in HID OMNIKEY 5427 CK 0, protocol T=0, state OK
Response: 0000000000000000005b42403565616235383039 ResponseAPDU: 14 bytes, SW=9000
ADPU: 0000000000000000005b42403433323065373664 36864 144 0 12

我不明白为什么响应是 0000000000000000005b42403565616235383039...请帮忙。

问候,弗拉德。

最佳答案

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

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

r.getData().toString()

byte[].toString 使用默认的 Object.toString() 实现,该实现返回类名,后跟 @ 和值Object.hashCode()(例如 "[B@312b1dae")——这不是您想要进一步处理的内容。

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

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

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

}

请注意一些有趣的部分:

  • 此代码使用Apache Commons Codec用于十六进制转换

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

  • 您的READ RECORD APDU 已修改为期望 256 字节的响应数据 -- this is how this particular constructor works (您的代码将生成 ISO case 1 Command-APDU,这可能不是您想要的)

附加说明:

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

祝你好运!

关于java - 卡的 PSE 不是它应该的样子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39543402/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com