我试图通过HID OMNIKEY 5427 CK通过APDUs命令来操作MIFARE卡即。 Ultralight C卡,在使用WinSCard.dll的Windows 10 x64 OS环境中。 (我在NXP NDA下并且可以完全访问他们的文件)
我试图在网上查找信息好几天了。除了2页小册子外,似乎没有该模型的公开文件。
GetUID(FFCA000000)之类的简单命令没问题,我可以取回实际的UID卡。
但是对于“使用卡进行身份验证”,来自HID 5421模型的参考文档说我应该从OpenGenericSession(FFA0000703010001)开始,我试过了,读者总是用6D00h回复(错误)
我尝试直接发送验证命令'1Ah + 00h'(FFA00005080100F30000641A0000),读者也总是回复错误代码。
我对HID 5421型号的使用经验非常直接,不知道为什么这款5427不像它的兄弟。
是的,我联系了HID支持。没运气。我没有从他们那里获得有用的信息。
如果有任何想法或有5427软件开发指南请帮忙。我现在已经把头发拉了近一个星期。
答案 0 :(得分:2)
以下是使用Omnikey 5321/6321通过通用会话与Ultralight-C进行通信的概念验证Java代码:
private static final byte AF = (byte)0xAF;
protected static final byte[] PREFIX = new byte[] { 0x01, 0x00, (byte) 0xF3, 0x00, 0x00, 0x64 };
protected final CardChannel channel;
protected void openGenericSession() throws CardException {
System.out.println("OPEN GENERIC SESSION");
transmitAssert9000(new CommandAPDU(0xFF, 0xA0, 0x00, 0x07, new byte[] { 0x01, 0x00, 0x01}));
}
protected byte[] transmitRaw(byte[] data) throws CardException {
System.out.println(" => " + toHex(data));
byte[] ret = transmitAssert9000(new CommandAPDU(0xFF, 0xA0, 0x00, 0x05, ArrayUtils.addAll(PREFIX, data), 256));
if(ret.length<2) {
throw new RuntimeException();
}
if((ret[0]==0x00)&&(ret[1]==0x00)) {
// Success
ret = Arrays.copyOfRange(ret, 2, ret.length);
System.out.println(" <= " + toHex(ret));
return ret;
}
if((ret[0]==0x08)&&(ret[1]==0x04)&&(ret.length==3)) {
// ACK/NAK
switch(ret[2]) {
case 0x0A:
System.out.println(" <= ACK");
return ArrayUtils.EMPTY_BYTE_ARRAY;
default:
// Buyer beware: very simplified
System.out.println(" <= NAK");
throw new RuntimeException("NAK");
}
}
ret = Arrays.copyOfRange(ret, 2, ret.length);
System.out.println(" <= " + toHex(ret));
return ret;
}
protected static byte[] assert9000(ResponseAPDU transmit) {
if(transmit.getSW()!=0x9000) {
throw new RuntimeException("Unexpected response code");
}
return transmit.getData();
}
protected byte[] transmitAssert9000(CommandAPDU commandAPDU) throws CardException {
return assert9000(transmit(commandAPDU));
}
protected ResponseAPDU transmit(CommandAPDU commandAPDU) throws CardException {
System.out.println(" -> " + toHex(commandAPDU.getBytes()));
ResponseAPDU responseAPDU = channel.transmit(commandAPDU);
System.out.println(" <- " + toHex(responseAPDU.getBytes()));
return responseAPDU;
}
public byte[] read(int offset) throws CardException {
System.out.println("READ");
return transmitRaw(new byte[] {0x30, (byte)offset});
}
注1:此代码使用javax.smartcardio和Apache Commons Lang。
注2:我写这段代码已经有一段时间了,请验证我的想法......
注3:对于Ultralight-C身份验证代码,请参阅此companion answer。
通用会话示例跟踪(Omnikey 6321 with Ultralight-C):
OPEN GENERIC SESSION
-> FFA0000703010001
<- 9000
AUTHENTICATE
=> 1A00
-> FFA00005080100F30000641A0000
<- 0000AF4BDA4E34B5D04A019000
<= AF4BDA4E34B5D04A01
=> AF6F18402E0F0E5357D854833B149FBB56
-> FFA00005170100F3000064AF6F18402E0F0E5357D854833B149FBB5600
<- 000000F0F667CCF0E140419000
<= 00F0F667CCF0E14041
READ
=> 3003
-> FFA00005080100F3000064300300
<- 0000000000000000000000000000000000009000
<= 00000000000000000000000000000000
CLOSE GENERIC SESSION
-> FFA0000703010002
<- 9000
一些补充说明:
(AFAIK)此方法适用于Windows(使用Omnikey驱动程序)。它在linux下不起作用(即使使用Omnikey驱动程序)。
请注意,PC/SC version 2.02 Part 3定义MANAGE SESSION
,TRANSAPARENT EXCHANGE
和SWITCH PROTOCOL
命令,这些命令以标准化方式提供相同的内容(您的读者可能会支持它而非专有通用会话机制 - HID甚至参与了本文件。)