Reading PACS (raw Wiegand) data with Omnikey 5022

1.9k Views Asked by At

I'm developing a Java application that connects to HID Omnikey 5022 card reader. What I need is reading PACS bits (raw Wiegand data).

I have exactly the same problem with this question, I also can see the data with PACS Probe application:

How to read Smart Card data

Unfortunately the provided answer to that is not working for me.

This is what I get from PACS Probe:

  • Card Reader: HID Global OMNIKEY 5022 Smart Card Reader 0
  • Card type: PicoPass 32KS (8x2 + 16)
  • Card serial number (CSN, UID): 32966202F8FF12E0 (hex)
  • PACS bits (raw Wiegand) data: 000000310BC53938 (hex)

I have already tried the command I found in Omnikey 5023 guide, surprisingly it returns some data but it's not what I need.

That command is:

commandAPDU = new CommandAPDU(new byte[] { (byte) 0xFF, (byte) 0x70, (byte) 0x07, (byte) 0x6B, (byte) 0x07,
                (byte) 0xA0, (byte) 0x05, (byte) 0xBE, (byte) 0x03, (byte) 0x80, (byte) 0x01, (byte) 0x04, (byte) 0x00 }); // Read PACS 5023

It returns this:

9E020003
// I need 000000310BC53938

Any help is appreciated since I am new to smart card development. Thanks in advance.

2

There are 2 best solutions below

0
On BEST ANSWER

I was able to use javax.smartcardio, and get the Wiegand data using code like below. At the end you can see the facility code and card number are printed.

TerminalFactory terminalFactory = TerminalFactory.getDefault();

CardTerminals cardTerminals = terminalFactory.terminals();

List<CardTerminal> terminalList = cardTerminals.list();

CardTerminal cardTerminal = terminalList.get(0);
cardTerminal.waitForCardPresent(10 * 1000); // wait 10 seconds
Card card = cardTerminal.connect("*");
System.out.println("Card: " + card);
CardChannel channel = card.getBasicChannel();

byte[] aid = { (byte) 0xA0, (byte) 0x05, (byte) 0xA1, (byte) 0x03, (byte) 0x80, (byte) 0x01, (byte) 0x04 };
CommandAPDU apdu = new CommandAPDU(0xFF, (byte) 112, (byte) 7, (byte) 107, aid, 256);
ResponseAPDU r = channel.transmit(apdu);
byte[] bytesOut = r.getBytes();

int num1 = (int) bytesOut[3];
if (bytesOut.length - 6 != num1)
System.out.println("problem");

int numberOfBitsShifted = (int) bytesOut[4];
int num2 = num1 - 1;

byte[] newBytesArr = Arrays.copyOfRange(bytesOut, 5, 5 + num2);
if (newBytesArr.length != num2)
    System.out.println("problem");

ByteBuffer wrapped = ByteBuffer.wrap(newBytesArr);
int num = wrapped.getInt();
int first26 = num >> 6;
int withoutParity = first26 >> 1;

int cardNumber = withoutParity & 0xffff;
int facilityCode = (withoutParity >> 16) & 0xff;

System.out.println(facilityCode);
System.out.println(cardNumber);

1
On

The response APDU you are getting from the reader is an error code for unsupported proprietary command.

You will need a secure session to access PACS bit data using OMNIKEY 5022 or OMNIKEY 5023 readers.

Unless you have the appropriate documentation for this reader, I would probably stick to the card serial number (UID, CSN) and use a Java wrapper for PC/SC (or pcsclite) to connect to reader and card.

Then issue (via SCardTransmit(FFCA0000 APDU) to get the UID (32966202F8FF12E0) shown in your the sample output from https://PACSprobe.com

As for Java: use smartcardio lib. That's a good wrapper for native PC/SC

It's a lot of work porting the secure channel protocols to Java. Calling a third-party library may be easier.