I'm trying to connect Android(Java) with Linux(Qt C++) using socket. After that I want to transfer length of message in bytes. For converting int in unsigned char array on the C++ side I use:
QByteArray IntToArray(qint32 source)
{
QByteArray tmp;
QDataStream data(&temp, QIODevice::ReadWrite);
data << source;
return tmp;
}
But I don't know how I can do the same converting on the Java side, because Java hasn't unsigned types. I tried to use some examples but always got different results. So, I need Java method which returns this for source = 17:
0x00, 0x00, 0x00, 0x11
I understand that it's a very simple question, but I'm new in Java so it's not clear to me.
UPD:
Java:
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.print(ByteBuffer.allocate(4).putInt(17).array());
Qt C++:
QByteArray* buffer = new QByteArray();
buffer->append(socket->readAll());
Output:
buffer = 0x5b, 0x42, 0x40, 0x61, 0x39, 0x65, 0x31,
0x62, 0x66, 0x35.
UPD2:
Java:
out.print(toBytes(17));
...
byte[] toBytes(int i)
{
byte[] result = new byte[4];
result[0] = (byte) (i >> 24);
result[1] = (byte) (i >> 16);
result[2] = (byte) (i >> 8);
result[3] = (byte) (i /*>> 0*/);
return result;
}
Qt C++: same
Output:
buffer = 0x5b, 0x42, 0x40, 0x63, 0x38, 0x61, 0x39,
0x33, 0x38, 0x33.
UPD3:
Qt C++:
QByteArray buffer = socket->readAll();
for(int i = 0; i < buffer.length(); ++i){
std::cout << buffer[i];
}
std::cout<<std::endl;
Output:
[B#938a15c
First of all, don't use PrintWriter.
Here's something to remember about Java I/O:
Streams are for bytes, Readers/Writers are for characters.
In Java, a character is not a byte. Characters have an encoding associated with them, like UTF-8. Bytes don't.
When you wrap a Stream in a Reader or a Writer, you are taking a byte stream and imposing a character encoding on that byte stream. You don't want that here.
Just try this:
OutputStream out = socket.getOutputStream();
out.write(toBytes(17));
Related
I have a requirement to use AES encryption with specific parameters but the only example provided is in Java. I need to move everything to PHP and I'm not sure how to do it exactly.
In Java the encryption class takes the iv/salt parameters as an array of bytes directly. Something in the likes of:
byte[] iv = {(byte) 0xCB, (byte) 0x35, (byte) 0xF3, (byte) 0x52, (byte) 0x1A, (byte) 0xF7, (byte) 0x38, (byte) 0x0B, (byte) 0x75, (byte) 0x03, (byte) 0x8E, (byte) 0xE0, (byte) 0xEF, (byte) 0x39, (byte) 0x98, (byte) 0xC7};
AlgorithmParameterSpec params = new IvParameterSpec(iv);
but PHP expects a string for input, so I tried to do something like:
private $salt = ['a7', '70', '1f', 'f6', '5e', 'd3', '29', '8f'];
private $iv = ['cb', '35', 'f1', '52', '1b', 'f7', '33', '0b', '75', '03', '8e', 'e0', 'cf', '39', '98', 'c7'];
public function __construct()
{
$iv = implode(array_map("hex2bin", $this->iv));
$this->iv = $iv;
$salt = implode(array_map("hex2bin", $this->salt));
$this->salt = $salt;
}
public function encrypt($unencryptedString)
{
$key = hash_pbkdf2('sha1', $this->passPhrase, $this->salt, $this->iterationCount, $this->keyLen, true);
var_dump($key);
$hash = openssl_encrypt($unencryptedString, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $this->iv);
$encoded = base64_encode($hash);
return $encoded;
}
I imagine I'm not using the iv/salt parameters the same way its used on Java, thats why it doesn't produce the same thing. Suggestions?
Basics (You did good!)
You should always Use a standard library for PHP encryption.
I know we shouldn't be making recommendations but encryption is in my opinion somewhat of an exception and you should utilise tried and tested libraries.
Use either the openssl extensions or libsodium
Answers on using both are linked here.
How to encrypt plaintext with AES-256 CBC in PHP using openssl()?
How to encrypt / decrypt AES with Libsodium-PHP
Problems?
In terms of your implemtation I think the $iv and $key aren't well formed inputs for hex2bin()
$iv = ['0xA7', '0x71', '0x1F', '0xF5', '0x5D', '0xD2', '0x28', '0x8F'];
array_map("hex2bin", $iv);
// outputs Warning: hex2bin(): Input string must be hexadecimal string
Following #Luke's suggestion:
Removing 0x and using lower case in all iv/salt values seems to do it.
private $salt = ['a7', '71', '1f', 'f5', '5d', 'd2', '28', '8f'];
I am unit testing a netty pipeline using the frame based decoder. It looks like the framing is incorrect if I use buffer size that is smaller that the largest frame. I am testing with a file that contains two messages. The length field is the second work and includes the length of the entire message including the length field and the work before it.
new LengthFieldBasedFrameDecoder(65536, 4, 4, -8, 0)
I am reading a file with various block sizes. The size of the first message is 348 bytes, the second is 456 bytes. If block size of 512, 3456, or larger, is used both messages are read and correctly framed to the next handler which for diagnostic purposes will print out as a hexadecimal string the contents of the buffer it received. If a smaller block size is used framing errors occur. The code used to read and write the file is shown below.
public class NCCTBinAToCSV {
private static String inputFileName = "/tmp/combined.bin";
private static final int BLOCKSIZE = 456;
public static void main(String[] args) throws Exception {
byte[] bytes = new byte[BLOCKSIZE];
EmbeddedChannel channel = new EmbeddedChannel(
new LengthFieldBasedFrameDecoder(65536, 4, 4, -8, 0),
new NCCTMessageDecoder(),
new StringOutputHandler());
FileInputStream fis = new FileInputStream(new File(inputFileName));
int bytesRead = 0;
while ((bytesRead = fis.read(bytes)) != -1) {
ByteBuf buf = Unpooled.wrappedBuffer(bytes, 0, bytesRead);
channel.writeInbound(buf);
}
channel.flush();
}
}
Output from a successful run with block size of 356 bytes is show below (with the body of the messages truncated for brevity
LOG:DEBUG 2017-04-24 04:19:24,675[main](netty.NCCTMessageDecoder) - com.ticomgeo.mtr.ncct.netty.NCCTMessageDecoder.decode(NCCTMessageDecoder.java:21) ]received 348 bytes
Frame Start========================================
(byte) 0xbb, (byte) 0x55, (byte) 0x05, (byte) 0x16,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x5c,
(byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x02,
(byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x50, (byte) 0x3a, (byte) 0xc9, (byte) 0x17,
....
Frame End========================================
Frame Start========================================
(byte) 0xbb, (byte) 0x55, (byte) 0x05, (byte) 0x1c,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xc8,
(byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x02,
(byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x04, (byte) 0x02, (byte) 0x00, (byte) 0x01,
If I change the block size to 256, the wrong bytes seem to be read as the length field.
Exception in thread "main" io.netty.handler.codec.TooLongFrameException: Adjusted frame length exceeds 65536: 4294967040 - discarded
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:499)
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.failIfNecessary(LengthFieldBasedFrameDecoder.java:477)
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:403)
TL;DR; Your problem is caused because netty reuses the passed in bytebuf, and then you are overwriting the contents.
LengthFieldBasedFrameDecoder is designed through inheritance to reuse the passed in ByteBuf, because it is useless to let the object decay through garbage collection when you can reuse it because its reference count is 1. The problem however comes from the fact that you are changing the internals of the passed in bytebuf, and therefore changing the frame on the fly. Instead of making a wrappedBuffer, that uses your passed in variable as storage, you should use copiedBuffer, because that one properly makes a copy of it, so the internals of LengthFieldBasedFrameDecoder can do freely things with it.
I'm working on a card reader now. I want to take data from the card. I took uid. I want to take encrypted data. So I want to enter the secure mode and start session. I did something. I send a command apdu to start session but every time return unknown exception 0x1f here is the code.
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
terminal = terminals.get(0);
card = terminal.connect("T=1");
CardChannel channel = card.getBasicChannel();
byte[] c1 = { (byte) 0x80, (byte) 0x72, (byte) 0x80, (byte) 0x00, (byte) 0x18, (byte) 0x5c, (byte) 0xc5,
(byte) 0x0a, (byte) 0xa2, (byte) 0x5b, (byte) 0x38, (byte) 0x7f, (byte) 0x81, (byte) 0x3a, (byte) 0x3d,
(byte) 0x1a, (byte) 0x88, (byte) 0x7d, (byte) 0x26, (byte) 0xfc, (byte) 0x2b, (byte) 0xa8, (byte) 0xa7,
(byte) 0xdd, (byte) 0xdc, (byte) 0x71, (byte) 0xe0, (byte) 0xf3, (byte) 0xc6 };
ResponseAPDU response = channel.transmit(new CommandAPDU(0xFF, 0x00,0x00,0x00,c1,5,24));
This code returns me 6a81( it means function not supported),
if I send directly start session command(84 72 00 00) this time returns unknown exception.
Please help me. You don't have to find the error in code. Tell me How Can I Start Session in a Smart Card. I use HID OMNÄ°KEY 5021 CL.
Exception in thread "main" javax.smartcardio.CardException: sun.security.smartcardio.PCSCException: Unknown error 0x1f
at sun.security.smartcardio.ChannelImpl.doTransmit(ChannelImpl.java:219)
at sun.security.smartcardio.ChannelImpl.transmit(ChannelImpl.java:90)
at CardReader.GetUID.getUID(GetUID.java:48)
at CardReader.GetUID.main(GetUID.java:86)
APDU you're sending is wrong, because you use CommandAPDU in an incorrect way.
new CommandAPDU(0xFF, 0x00,0x00,0x00,c1,5,24)
creates an APDU starting FF000000185CC50AA2... which is not what you (probably) want.
Try new CommandAPDU(0x84, 0x72,0x00,0x00,c1,5,24) instead.
See CommandAPDU javadoc and APDU format description.
I found the problem. The problem is byte types .net and java. C# byte type between 0 and 255 but java byte type -127 and +128. So if I send a higher than 127 value to java, card interpret like minus value.
I'm currently trying to write a couple of bytes to a specific block. My read commands work fine and I am able to read any block of my tag using the code below:
command = new byte[]{
(byte) 0x02, // Flags
(byte) 0x23, // Command: Read multiple blocks
(byte) 0x09, // First block (offset)
(byte) 0x03 // Number of blocks // MAX READ SIZE: 32 blocks:1F
};
byte[] data = nfcvTag.transceive(command);
When I try to write with the code below, my app crashes.
Write = new byte[]{
(byte) 0x02, // Flags
(byte) 0x21, // Command: Write 1 blocks
(byte) 0x5A, // First block (offset)
(byte) 0x41 // Data
};
nfcvTag.transceive(Write);
I'm doing this in an AsyncTask and getting the java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() exception.
Any tips? The tag is a STMicroelectronics M24LR04E-R
Figured it out. I was only writing 8 bits of data while the tag has 32 bits per block. Added 3 0x00's and the write was successful.
Write = new byte[]{
(byte) 0x02, // Flags
(byte) 0x21, // Command: Write 1 blocks
(byte) 0x5A, // First block (offset)
(byte) 0x41,
(byte) 0x00,
(byte) 0x00,
(byte) 0x00
};
nfcvTag.transceive(Write);
I am writing some code to handle a stream of binary data. It is received in chunks represented by byte arrays. Combined, the byte arrays represent sequential stream of messages, each of which ends with the same constant terminator value (0xff in my case). However, the terminator value can appear at any point in any given chunk of data. A single chunk can contain part of a message, multiple messages and anything in between.
Here is a small sampling of what data handled by this might look like:
[0x00, 0x0a, 0xff, 0x01]
[0x01, 0x01]
[0xff, 0x01, 0xff]
This data should be converted into these messages:
[0x00, 0x0a, 0xff]
[0x01, 0x01, 0x01, 0xff]
[0x01, 0xff]
I have written a small class to handle this. It has a method to add some data in byte array format, which is then placed in a buffer array. When the terminator character is encountered, the byte array is cleared and the complete message is placed in a message queue, which can be accessed using hasNext() and next() methods (similar to an iterator).
This solution works fine, but as I finished it, I realized that there might already be some stable, performant and tested code in an established library that I could be using instead.
So my question is - do you know of a utility library that would have such a class, or maybe there is something in the standard Java 6 library that can do this already?
I don't think you need a framework as a custom parser is simple enough.
InputStream in = new ByteArrayInputStream(new byte[]{
0x00, 0x0a, (byte) 0xff,
0x01, 0x01, 0x01, (byte) 0xff,
0x01, (byte) 0xff});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int b; (b = in.read()) >= 0; ) {
baos.write(b);
if (b == 0xff) {
byte[] bytes = baos.toByteArray();
System.out.println(Arrays.toString(bytes));
baos = new ByteArrayOutputStream();
}
}
prints as (byte) 0xFF == -1
[0, 10, -1]
[1, 1, 1, -1]
[1, -1]