0

我正在尝试使用 Java 中的 smartcardio 库(JDK 8、NetBeans 7.4、Windows 10)。我尝试了许多其他库,但都没有成功。

读卡器 (ACS ACR122U) 附带一个 SDK CDROM,但必要的 .DLL 不在 CD 上,因此我无法使用 ACS 库。

由于我的 NFC 设备使用了 nfctools 库不支持的 EEPROM,因此我无法使用 nfctools。

我的代码如下:

package myPackage;

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

public class Blog {
 public static void main(String[] args) {
  try {
   // Display the list of terminals
   TerminalFactory factory = TerminalFactory.getDefault();
   List<CardTerminal> terminals = factory.terminals().list();
   System.out.println("Terminals: " + terminals);

   // Use the first terminal
   CardTerminal terminal = terminals.get(0);

   // Connect with the card
   Card card = terminal.connect("*");
   System.out.println("card: " + card);
   CardChannel channel = card.getBasicChannel();

   // Send Red and Green LED ON command
   byte[] cmd1 = {(byte)0xFF, // Pseudo-APDU class
                        0x00, // INS
                        0x00, // P1
                        0x00, // P2
                        9,    // Lc - number of bytes in Payload
                        (byte)0xFF, // First byte of payload - LED/Buzzer cntrl
                        0x00, // INS
                        0x40, // P1
                        0x0F, // P2 - LED state control
                        0x04, // Lc
                        0x00, // 4 byte blink duration control
                        0x00, 
                        0x00, 
                        0x00 };
   CommandAPDU apdu1 = new CommandAPDU( cmd1,   // Byte array to use
                                           0,   // index to start of msg
                                           14 );// msg length
   System.out.println( "apdu1: " + apdu1.toString() );

   ResponseAPDU answer1 = channel.transmit( apdu1 );
   System.out.println("answer1: " + answer1.toString());

   // Get Firmware Version of the reader
   byte[] cmd2 = {(byte)0xFF, 0x00, 0x00, 0x00, 5, (byte)0xFF, 0x00, 0x48, 0x00, 0x00 };
   CommandAPDU apdu2 = new CommandAPDU( cmd2, 0, 10 );
   System.out.println( "apdu2: " + apdu2.toString() );
   ResponseAPDU answer2 = channel.transmit( apdu2 );
   System.out.println("answer2: " + answer2.toString());
   System.out.println();

   // Disconnect the card
   card.disconnect(false);
  } catch(CardException e) 
  {
   System.out.println("Problem: " + e.toString());
  }
 }
}

它失败并显示有关“apdu 必须至少有 2 个字节长”的错误。

run:
Terminals: [PC/SC terminal ACS ACR122 0]
card: PC/SC card in ACS ACR122 0, protocol T=1, state OK
apdu1: CommmandAPDU: 14 bytes, nc=9, ne=0
Exception in thread "main" java.lang.IllegalArgumentException: apdu must be at least 2 bytes long
    at javax.smartcardio.ResponseAPDU.check(ResponseAPDU.java:73)
    at javax.smartcardio.ResponseAPDU.<init>(ResponseAPDU.java:67)
    at sun.security.smartcardio.ChannelImpl.transmit(ChannelImpl.java:91)
    at myPackage.Blog.main(Blog.java:43)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

对象 apdu1 长 14 个字节,所以我不确定错误消息的含义。

第 43 行是ResponseAPDU answer1 = channel.transmit( apdu1 );

4

1 回答 1

0

正如评论中的 APDU 命令的 0xff 类对卡无效,这用于让阅读器解释 APDU 而不是将其发送到卡。

不是同一个读者,但这张图很清楚

在此处输入图像描述

所以不要尝试通过复制 INS、P1、P2 和 Lc 字段来将 APDU 包装在另一个 APDU 中

// Send Red and Green LED ON command
   byte[] cmd1 = {(byte)0xFF, // First byte of payload - LED/Buzzer cntrl
                        0x00, // INS
                        0x40, // P1
                        0x0F, // P2 - LED state control
                        0x04, // Lc
                        0x00, // 4 byte blink duration control
                        0x00, 
                        0x00, 
                        0x00 };
   CommandAPDU apdu1 = new CommandAPDU( cmd1,   // Byte array to use
                                           0,   // index to start of msg
                                           9 );// msg length

于 2020-04-23T21:38:15.697 回答