Bluetooth LE Java byte array size on characteristic setValue - java

I am trying to send a value using Bluetooth LE on my Android phone with the following line of code.
I am getting an error that it exceeds the size of the array, which is 127 because of the 0xEA byte. I converted the byte to around 234. Is there a way to send this byte using the following line of code?
private void writeCharacteristic(BluetoothGatt gatt)
{BluetoothGattCharacteristic characteristic;
Log.d(TAG, "Writing Data");
characteristic = gatt.getService(SERVICE).getCharacteristic(DATA_IN);
characteristic.setValue(new byte[]{0x08, 0x01, 0x03, 0x04, 0x52, 0x00, 0x02, 0x62, 0xEA});
gatt.writeCharacteristic(characteristic);
}

To be able to use byte values above 127 in java, use (byte)0xEA.

Related

Reading PACS (raw Wiegand) data with Omnikey 5022

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.
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.
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);

How to avoid individual casting to byte during initialization of byte array in Java

I am using a byte array to store a text file outside of the filesystem.
It looks like this:
private static final byte[] CDRIVES = new byte[] {
(byte)0xe0, 0x4f, (byte)0xd0, 0x20, (byte)0xea, 0x3a, 0x69, 0x10,
(byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b, 0x30, 0x30, (byte)0x9d,
(byte)0xba, (byte)0x8a, 0x0d, 0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11,
(byte)0x98, (byte)0xa8, 0x08, 0x00, 0x36, 0x1b, 0x11, 0x03,
(byte)0x80, 0x53, 0x1c, (byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10,
(byte)0xa2, (byte)0xea, 0x08, 0x00, 0x2b, 0x30, 0x30, (byte)0x9d
...
...
...
};
Is there a way to avoid casting to (byte) for better visual interpretation?
I don't mind using other data type, but I need to be able build an InputStream out of it and do it the fastest way if possible. (for example storing a text file into a String variable is not the best way...)
Well one simple approach would be to use base64 - but perform the conversion on class initialization, so you only take the performance hit once:
private static final byte[] CDRIVES = Base64.decode("YOURBASE64HERE");
Or if it's genuinely text, perform that encoding once in a similar way:
private static final byte[] CDRIVES =
"Your constant text here".getBytes(StandardCharsets.UTF_8);
Again, the performance hit occurs exactly once, and then you can use the bytes multiple times. I would be very surprised if the cost of encoding text into bytes at class initialization time is genuinely a bottleneck for you.

possibly lossy conversion from int to byte

I am trying to write hexadecimal data into my serial port using java, but now I cant convert the hexadecimal data into the byte array.
Here is the code which shows the error message:
static byte[] bytearray = {0x02, 0x08, 0x16, 0x0, 0x00, 0x33, 0xC6, 0x1B};
This is the code writing into the serial port:
try {
outputStream = serialPort.getOutputStream();
// Write the stream of data conforming to PC to reader protocol
outputStream.write(bytearray);
outputStream.flush();
System.out.println("The following bytes are being written");
for(int i=0; i<bytearray.length; i++){
System.out.println(bytearray[i]);
System.out.println("Tag will be read when its in the field of the reader");
}
} catch (IOException e) {}
Can I know how can I solve this problem. Currently I am using the javax.comm plugin. Thank you.
If you look at the error message:
Main.java:10: error: incompatible types: possible lossy conversion from int to byte
static byte[] bytearray = {0x02, 0x08, 0x16, 0x0, 0x00, 0x33, 0xC6, 0x1B};
^
There is a small caret pointing to the value 0xC6. The reason for the issue is that java's byte is signed, meaning that its range is from -0x80 to 0x7F. You can fix this by casting:
static byte[] bytearray = {0x02, 0x08, 0x16, 0x0, 0x00, 0x33, (byte) 0xC6, 0x1B};
Or, you can use the negative, in-range value of -0x3A (which is equivalent to 0x36 in two's-complement notation).
Try to cast 0xC6 like this as byte range is from -0x80 to 0x7F:
static byte[] bytearray = {0x02, 0x08, 0x16, 0x0, 0x00, 0x33, (byte) 0xC6, 0x1B};

can not select file on ISO-7816-4 smartcard

I am trying to read data from ISO-7816-4 eVCR (electronic vehicle registration card) using
javax.smartcardio. Whenever I try to select file from card I get SW code 6A86 which
translates to 'Incorrect P1 or P2 parameter'. I tried many combinations of values for
P1 and P2 and got same result.
Card itself works fine with other programs and sample code works fine with other cards.
Card I have problem with is same card as in this question.
This is code I use:
Card card = terminal.connect("*");
System.out.println("ATR: " + Utils.bytes2HexString(card.getATR().getBytes()));
byte aid[] = {(byte)0xA0, 0x00, 0x00, 0x00, 0x77, 0x01, 0x08, 0x00, 0x07,
0x00, 0x00, (byte) 0xFE, 0x00, 0x00, (byte) 0xAD, (byte) 0xF2};
ResponseAPDU response = null;
CardChannel channel = card.getBasicChannel();
response = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04, 0x0C, aid));
System.out.println("AID: " + response);
response = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x02, 0x00, new byte[]{(byte)0xD0, 0x01}));
System.out.println("SELECT: " + response);
And output is:
ATR: 3B:DB:96:00:80:B1:FE:45:1F:83:00:31:C0:64:1A:18:01:00:0F:90:00:52
AID: ResponseAPDU: 2 bytes, SW=9000
SELECT: ResponseAPDU: 2 bytes, SW=6a86
I can't see what am I doing wrong. Do some cards require extra initialization steps or some extra parameters for select?
You could use 0x0C as P2 (instead of 0x00)? Maybe the file ID is correct, but it cannot give back any file information (0x0C means: don't give back file information).
It depends on the card operating system and/or application if this would influence the returned status word.

Converting bytearray to Objective-C data structure [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Byte array in objective-c
Am converting some Java code to Objective-C and have run into an issue that I can't get my head around:
public static final byte[] DATA_GENERIC = new byte[] { (byte)0xA0, 0x00, 0x00, 0x00, 0x03,
0x10, 0x10 };
Does anyone know to convert the above into Objective-C
Here is an example of getting your data into a NSData object.
const unsigned char bytes[] = { 0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10 };
NSData *data = [NSData dataWithBytes:bytes length:7];
NSLog(#"%#", data);
Output:
<a0000000 031010>
One major difference from java is you will need to keep track of the number of bytes yourself when working with a raw char array. Once you create the NSData you can access the length.

Categories