首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PSE卡,而不是它应该是什么

PSE卡,而不是它应该是什么
EN

Stack Overflow用户
提问于 2016-09-17 06:06:15
回答 1查看 350关注 0票数 0

所以,我有一部非接触式万事达和一部Visa付费电话。我用的是非接触式HID Omnikey 5427 CK。

这是我的密码:

代码语言:javascript
复制
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()));
}

`

所以输出是:

代码语言:javascript
复制
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

我不明白为什么回复是000000000000005b42403565616235383039。请帮帮忙。

你好,弗拉德。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-19 09:39:38

正如Michael所说--你对十六进制字符串的处理是错误的。

Meta-错误1:使用'byte[].toString()'

代码语言:javascript
复制
r.getData().toString()

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

您可以使用Arrays.toString()方法(它不执行十六进制转储)或任何其他方法

Meta-错误2:使用'String.getBytes()'

代码语言:javascript
复制
String pse = "00A404000E325041592E5359532E444446303100";
CommandAPDU apdu = new CommandAPDU(pse.getBytes());

不创建所需的APDU对象,因为String.getBytes()不执行十六进制转换,而是在平台的默认字符集中进行字符集转换,例如:"1234".getBytes()提供{ 0x31, 0x32, 0x33, 0x34 } (而不是您可能预期的{ 0x12, 0x34 } )。

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

代码语言:javascript
复制
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协议更具通用性。
  • 您的READ RECORD APDU被修改为期望256个字节的响应数据-- 这就是这个特定的构造函数的工作方式。 (您的代码将产生一个ISO 1命令-APDU,这可能不是您想要的)

另有一项说明:

  • 不要在没有参数的情况下使用String.getBytes()方法(即使要将单个字符转换为字节)。请始终指定所需的字符集(例如:"US-ASCII“、"UTF-8")

祝好运!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39543402

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档