Read write data in SLE4442 smart card with java commandAPDU? - java

I want to read and write data in SLE4442 smart card
i have ACR38U-i1 smart card reader
For write I am use this commandAPDU
byte[] cmdApduPutCardUid = new byte[]{(byte)0xFF, (byte)0xD0, (byte)0x40,(byte)0x00, (byte)4,(byte)6,(byte)2,(byte)6,(byte)2};
And for read data
byte[] cmdApduGetCardUid = new byte[]{(byte)0xFF,(byte)0xB0,(byte)0x40,(byte)0x00,(byte)0xFF};
both are execute and send SW= 9000
but no one data receive in responseAPDU
Like I write 6262 data but it not receive
I am also use Select command to before write and read command
The select command is
byte[] cmdApduSlcCardUid = new byte[]{(byte)0xFF,(byte)0xA4,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x06};
Have anyone Proper java code to read and write in SLE4442 smart card ?

APDU Commands related to work with Memory Cards could be different for different readers and implemented support. Here is an example for OmniKey reader.
Take a look to your ACR reader specification and use specific Pseudo-APDU command to work with SLE 4442.
For your question:
4.6.1 SELECT_CARD_TYPE: "FF A4 00 00 01 06", where 0x06 in the data meant "Infineon SLE 4432 and SLE 4442".
4.6.2 READ_MEMORY_CARD: "FF B0 00 [Bytes Address] [MEM_L]", where
[Bytes Address]: is the memory address location of memory card
[MEM_L]: Length of data to be read from the memory card
4.6.5 WRITE_MEMORY_CARD: "FF D0 00 [Bytes Address] [MEM_L] [Data]"
[Data]: data to be written to the memory card
You used P1 = 0x40 and this could be an issue.

Related

Sending APDU commands to Write Data to a smartCard Reader using java smartcardio functions

I am trying to write data to contactless card in HID Omnikey 5122 device using java smartcardIO functions.
The Data that I need to insert to the card is {00 01 02 03}.
APDU command I am trying to send through channel.transmit function is {FF D6 00 04 04 00 01 02 03}
where:
FF is CLS
D6 is INS
00 is P1
04 is P2
04 is Number of bytes to update
00 01 02 03 is the data that I need to insert.
I am not able to correctly build the APDU command through below function. Can some one help me with this. I am using functions available in java smartcardio library.
ResponseAPDU respApdu = channel.transmit(
new CommandAPDU(0xFF,0xD6,0x00,0x04,0x04,
new byte[] {(byte) 0x00,
(byte) 0x01,
(byte)0x02,
(byte)0x03}));
I am getting syntax error like constructor command is having invalid arguments.
It looks like you are trying to send an UPDATE BINARY APDU to update the transparent file at offset 4 (this is what you provide in P1-P2). You have to use a CLA byte of 00h (if that file operation doesn't require the use of Secure Messaging).
Since P1-P2 doesn't specify a short file identifier in your case, your currently selected file has
to be compatible with the READ/UPDATE BINARY commands
to have file size >=9 byres.

Authenticating Ultralight EV1 with PC/SC reader

I have a problem trying to authenticate an Ultralight EV1 card using a PC/SC reader (specifically an ACR1222L) in Java. I'm able to write and read on an unprotected tag using the corresponding APDUs for ISO 14443-3 tags. However, I can't find a way to run the PWD_AUTH command since it is not part of the 14443-3 standard (or any native command for that matter). Is it possible to run this command (or any native command for that matter)?
I have tried sending the following APDU {e0 00 00 24 07 1b ff ff ff ff 63 00} where 1b is the native command, ff ff ff ff is the password and 63 00 is the CRC_A of the command plus password. I have also tried without the CRC, switching the order of the parameters, etc., but so far I could not get it working.
I also tried wrapping the APDU (as described in https://stackoverflow.com/a/41729534/3613883). I got it working with a Desfire EV1 card but it doesn’t work with the ultralight EV1 (since it doesn’t support ISO7816-4 obviously).
So, is there a way to authenticate a Ultralight EV1 card using a PC/SC reader?
First of all, MIFARE Ultralight EV1 does not speak APDUs. Instead it uses commands based directly on the framing defined in ISO/IEC 14443-3. Since ISO/IEC 14443-3 only defines the framing and the anti-collision/enumeration commands, any protocol on top of that (e.g. the MIFARE Ultralight/NTAG command sets) is proprietary.
The correct command for password authentication using the password FF FF FF FF would be:
byte[] tagCommand = new byte[] { (byte)0x1B, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF };
Note that the CRC will typically be handled by the contactless frontend chip so you don't need to apped it manually.
With the ACR1222L, there are multiple different ways to exchange such proprietary commands:
You can use PC_to_RDR_Escape (note that that's only available if you installed the original ACR driver package for the reader). Assuming that you are using the Java Smartcard IO API, you would do that using the method Card.transmitControlCommand():
byte[] response = card.transmitControlCommand(SCARD_CTL_CODE(3500), command);
The definition of the method SCARD_CTL_CODE can be found in this post.
The command needs to be a byte array that contains an APDU header for the pseudo-APDU that passes raw commands to the contactless frontend chip and the actual command for the contactless frontend chip. Since the ACR1222L is based on an NXP PN532(?), the command for the contactless frontend chip would be the InDataExchange command (see the user manual):
byte[] interfaceCommandHeader = new byte[] { (byte)0xD4, (byte)0x40, (byte)0x01 };
byte[] interfaceCommand = Arrays.copyOf(interfaceCommandHeader, interfaceCommandHeader.length + tagCommand.length);
System.arraycopy(tagCommand, 0, interfaceCommand, interfaceCommandHeader.length, tagCommand.length);
Depending on how the reader actually activates the card, you might need to use the InCommunicateThru command instead of InDataExchange:
byte[] interfaceCommandHeader = new byte[] { (byte)0xD4, (byte)0x42 };
byte[] interfaceCommand = Arrays.copyOf(interfaceCommandHeader, interfaceCommandHeader.length + tagCommand.length);
System.arraycopy(tagCommand, 0, interfaceCommand, interfaceCommandHeader.length, tagCommand.length);
The pseudo APDU header can be added by:
byte[] commandHeader = new byte[] { (byte)0xE0, (byte)0x00, (byte)0x00, (byte)0x24, (byte)0x00 };
byte[] command = Arrays.copyOf(commandHeader, commandHeader.length + interfaceCommand.length);
System.arraycopy(interfaceCommand, 0, command, commandHeader.length, interfaceCommand.length);
command[4] = (byte)(interfaceCommand.length & 0x0FF); // update Lc field
Another option is to send commands directly using PC_to_RDR_XfrBlock. This maps to CardChannel.transmit() in the Java Smartcard IO API:
ResponseAPDU responseApdu = cardChannel.transmit(commandAPDU);
The manual of your reader is not quite clear if the same pseudo APDU header can be used over that interface. However, if you look into appendix H, you'll find a different header from wrapping into a pseudo APDU (the ACR122U legacy mode). So you could use the following:
CommandAPDU commandAPDU = new CommandAPDU(0xFF, 0x00, 0x00, 0x00, interfaceCommand);
Note that, again, you have to wrap the tag command into the InDataExchange command for the contactless frontend chip.

SMB JCIFS file writing issue

I want to write a password protected file at remote location in JAVA. So I am using SMB api(JCIFS).
However I am seeing an inconsistency in the data written at destination file.
E.g.
If my intension is to write the data as,
AB
CD
EF
GH
When I write the data in file,
The api misses some characters,
Some times it writes,
AB
CDE //EF not on next line & 'E' missed by api.
GH
some times it writes,
AB
CD
EFH
I am using SMBFileOutputStream to write a line by line in file.
smbOutputStream.write(myString.getByte);

Get hex values from socket and convert to decimal

I have data that I read from a socket and I know it has the following format:
[2bytes][8bytes][2bytes] = 12 bytes
That I want to read separately; and the values are in Hex. I actually captured that data a while ago in PHP and saved it to files and I can view it properly using od (unix):
$ od -h myFile
$ 0000000 02eb 02fe fe02 fefe 02fe 02fe 000a
$ 0000015
That, has a CR and LF at the end, resulting in 14 bytes. How can I obtain those values in Java reading from a socket? For instance how do I get that "02eb" (2 bytes) and convert it to a decimal value?
I am already reading from the socket, last thing I tried was:
mMessage = mBRin.readLine();
byte[] bytes = mMessage.trim().getBytes()
But that gives me 18 bytes in the array.
If it helps, in PHP to get that first part I did:
$input = socket_read($value,13,PHP_BINARY_READ);
$trim_input = trim($input);
$float_head = hexdec(bin2hex(substr($input,0,2)));
I think I am not understanding this, which may be the answer
I have data that I read from a socket and I know it has the following
format:
[2bytes][8bytes][2bytes] = 12 bytes
If you already have code to read bytes from a socket, you can use a ByteBuffer to convert the bytes to short, int, long etc. values.
Socket s = .....;
InputStream in = s.getInputStream();
byte [] buf = new byte[12];
// read 12 bytes from socket into bytes
in.read(buf);
ByteBuffer bb = ByteBuffer.allocate(buf.length);
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.put(buf);
bb.flip();
short short1 = bb.getShort();
long long1 = bb.getLong();
short short2 = bb.getShort();
Note the call to set the byte buffer to little endian.
When you did the od command you got output similar to the following (this output comes from a file I created on my system to mimic yours). The od -h command reads the bytes from the file, puts them together as 2-byte shorts in little endian mode then prints out the short values in hex.
$ od -h binary.dat
0000000 02eb 02fe fe02 fefe 02fe 02fe 000a
0000015
However if you use the -tx1 you see the bytes in the real order they appear in the file.
$ od -tx1 binary.dat
$ 0000000 eb 02 fe 02 02 fe fe fe fe 02 fe 02 0a
$ 0000015
If you run this on your file I think you will see that it is really 13 bytes not 14 bytes and is terminated by a single LF, not CRLF. The "extra" byte you saw was a "present" from od -h is does not actually exist in file.
Anyhow, The first byte is value 235 (EB in hex). The second byte is 2. The question is - what is the correct value for that first short want. If, according to your socket protocol, the data is serialized in little endian mode, the value of those two bytes concatenated into a short is 02EB hex or 747. If the socket protocol uses big endian, then the value is EB02 hex or 60162.
The ByteBuffer approach gives you flexibility and allows you to read/write in either big-endian or little endian. It also allows you to separate the reading of data off the socket (into byte arrays) then later converting the data into numbers. This may make it easier for unit testing since you can create byte arrays for various test cases and make sure your parsing code works as expected.
The DataInputStream approach in sharadendu's answer will also work - but only if the socket protocol is big-endian. DataInputStream is hard-coded to big-endian.
Socket socket = ......;
DataInputStream dis = new DataInputStream(socket.getInputStream());
short f1 = dis.readShort();
long f2 = dis.readLong();
sort f3 = dis.readShort();
To print the values in hex use String.format("%x",f1);
Hope it helps ...

What's the most efficient way to add data mid way through a stream of bytes?

I've been making an image rescaler that uses the ImageIO library in Java to convert them to a buffered image. Unfortunately it doesn't recognise every type of JPEG that I may pass to it and so I need to "convert" these other types. The way I'm converting them is to take an existing APP0 tag from a standard JFIF JPEG and what I want to do is on the 3rd byte into the file insert 18 bytes of data (the FFE0 marker and the 16 byte APP0 tag) and then I want to add the rest of the file to the end of that.
So to generalise, what's the most efficient way to add/insert bytes of data mid way through a stream/file?
Thanks in advanced,
Alexei Blue.
This question is linked to a previous question of mine and so I'd like to thank onemasse for the answer given there.
Java JPEG Converter for Odd Image Types
If you are reading your images from a stream, you could make a proxy which acts like an inputstream and takes an outputstream. Override the read method so it returns the extra missing bytes when they are missing.
A proxy can be made by extending FilterInputStream http://download.oracle.com/javase/6/docs/api/java/io/FilterInputStream.html
If it is a file, the recommended way to do this is to copy the existing file to a new one, inserting, changing or removing bytes at the appropriate points. Then rename the new file to the old one.
In theory you could try to use RandomAccessFile (or equivalent) perform an in-place update of an existing file. However, it is a bit tricky, not as efficient as you might imagine and ... most important ... it is unsafe. (If your application or the system dies at an inopportune moment, you are left with a broken file, and no way to recover it.)
A PushbackInputStream might be what you need.
Thanks for the suggestion guys, I used a FilterInputStream at first but then saw there was no need to, I used the following piece of code to enter my APP0 Hex tag in:
private static final String APP0Marker = "FF E0 00 10 4A 46 49 46 00 01 01 01 00 8B 00 8B 00 00";
And in the desired converter method:
if (isJPEG(path))
{
fis = new FileInputStream(path);
bytes = new byte[(int)(new File(path).length())];
APP0 = hexStringToByteArray(APP0Marker.replaceAll(" ", ""));
for (int index = 0; index < bytes.length; index++)
{
if (index >= 2 && index <= (2 + APP0.length - 1))
{
b = APP0[index-2];
}
else
{
b = (byte) fis.read();
}//if-else
bytes[index] = b;
}//for
//Write new image file
out = new FileOutputStream(path);
out.write(bytes);
out.flush();
}//if
Hope this helps anyone having the a similar problem :)

Categories