How can I write bits to byte array in java? - java

I try to create mpegts presentation timestamp. It is 5 bytes length. I found solution in source code of VLC player. It's looks like this (in C lang code):
bits_write( &bits, 4, i_pts_dts ); // '0010' or '0011'
bits_write( &bits, 3, i_pts >> 30 );
bits_write( &bits, 1, 0x01 ); // marker
bits_write( &bits, 15, i_pts >> 15 );
bits_write( &bits, 1, 0x01 ); // marker
bits_write( &bits, 15, i_pts );
bits_write( &bits, 1, 0x01 ); // marker
i_header_size -= 0x5;
That means I must to collect 5 bytes from 40 bits.
For example, I need to 5 bytes from 2350 decimal number. Binary view:
1001 0010 1110
After VLC manipulation I must have this binary view:
0010 000 1 000000000000000 1 000100100101110 1
Hex view:
21 00 01 12 5D
How can I do it in Java?
Also I found Java-solution on GitHub: https://github.com/taktod/myLib/blob/master/myLib.MIT/myLib.container.mpegts/src/main/java/com/ttProject/container/mpegts/field/PtsField.java
But this realization is too difficult. For a one-time operation it is necessary to create too many helper classes like Bit1, Bit2, Bit3, etc...

This is simple bit-manipulation:
int dts = 2; // must be 2 or 3
long pts = 2350; // must be less than 8,589,934,592
byte[] output = new byte[] {
(byte) (dts << 4 | pts >> 30 | 1),
(byte) (pts >> 22),
(byte) (pts >> 15 | 1),
(byte) (pts >> 7),
(byte) (pts << 1 | 1)
};
for (byte b : output)
System.out.printf("%02x ", b); // prints: 21 00 01 12 5d

Related

Trying to find the height and width of a .bmp file gets inconsistent results in processing

I'm trying to manually draw pixels I read of a .bmp file.
This information is stored in the BMP Header. image width (4 bytes - 0x12 to 0x15), image height (4 bytes - 0x16 - 0x19) and the offset for the raw pixel data (4 bytes - 0xa to 0xd).
To find width and height, I use this:
byte[] bytes = loadBytes("ImageFile.bmp");
imageWidth = ((bytes[0x12]) | (bytes[0x13])<<8 | (bytes[0x14])<<16 | (bytes[0x15])<<24) ;
imageHeight = ((bytes[0x16]) | (bytes[0x17])<<8 | (bytes[0x18])<<16 | (bytes[0x19])<<24) ;
offset = (bytes[0xa]) | (bytes[0xb])<<8 | (bytes[0xc])<<16 | (bytes[0xd])<<24;
size(imageWidth,imageHeight);
after that, I get accurate results: imageWidth is 600, imageHeight is 780.
but for a smaller bmp image, 250x250, after the same calculation I get the answer in 2's complement: imageWidth is -6 and imageHeight is -6.
this conversion is wierd to me,because when I view the hex data with notepad++, I get:
fa 00 00 00 fa 00 00 00
these are from bytes from 0x12 - 0x19.
they are not stored as signed values. So why do I read them as such?
And is there a single way to get the actual unsigned values regardless of the actual size?
Thank you!
See my comments above about doing it the hard way. This is tons easier:
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
bb.position(0x12);
int width = bb.getInt();
int height = bb.getInt();
Hard way:
long imageWidth = bytes[0x12] & 0xFF | (bytes[0x13] & 0xFF) << 8 | (bytes[0x14] << 16) & 0xFF | (bytes[0x15] << 24) & 0xFF;
long imageHeight = bytes[0x16] & 0xFF | (bytes[0x17] & 0xFF) << 8 | (bytes[0x18] & 0xFF) << 16 | (bytes[0x19] & 0xFF) << 24;

CryptoJS encrypt HMACSha256 different than Java

I'm trying to convert this code of CryptoJS to Kotlin:
const hash = CryptoJS.HmacSHA256(message, key);
const signature = CryptoJS.enc.Hex.stringify(hash);
That's the kotlin code equivalent to above snippet:
private fun generateSignature(key: String, payload: String): String {
val algorithm = "HmacSHA256"
return Mac.getInstance(algorithm)
.apply { init(SecretKeySpec(key.toByteArray(), algorithm)) }
.run { doFinal(payload.toByteArray()) }
.let { HexUtils.toHexString(it) }
}
But it is not working at all. They generate different results. CryptoJS generates an array of bytes that has 8 positions, the Java code generates an array of bytes that has 32 positions.
I don't know what Im doing wrong. I need to make my Kotlin code work exactly as the javascript one.
Update: I can't change the Javascript way. I have to do the exactly same thing in Kotlin
Update2: Here is a test where the JS code and the Kotlin code generates different results.
Input:
key = 's21fk4vb-5415-46c7-aade-303dcf432bb4'
message = 'POST,/wallets/3323461f96-bdf3-4e03-bc93-7da1fb27aee7/withdraw/,1573148023809,{"amount":"1.0","bank":{"bank":"789","agency":"456","account":"12378","accountDigit":"6","name":"joao","taxId":"33206913098","holderType":"personal"}}'
Results with JS code:
Result of encrypt in bytes:
{sigBytes: 32, words: [8]}
sigBytes: 32
words: [8]
0: 2102759135
1: -196086391
2: -2099697915
3: -1620551271
4: 2463524
5: 1757965357
6: -1039993965
7: -1798822705
Bytes to Hex:
7d558edff44ff58982d927059f6859990025972468c86c2dc202f39394c824cf
Results with Kotlin code:
Result of encrypt in bytes:
{byte[32]#1126}
0 = 82
1 = -110
2 = -100
3 = -128
4 = -63
5 = 22
6 = -103
7 = -31
8 = 83
9 = -125
10 = -72
11 = 109
12 = -91
13 = -69
14 = 54
15 = -41
16 = 27
17 = -107
18 = -60
19 = -110
20 = -57
21 = -29
22 = -20
23 = -32
24 = -66
25 = 88
26 = 87
27 = -50
28 = -47
29 = -18
30 = -96
31 = 25
Bytes to Hex:
52929c80c11699e15383b86da5bb36d71b95c492c7e3ece0be5857ced1eea019
No SHA-256 hash can have only 8 byte positions. The output, as the name suggests, should be 256 bits or 32 bytes. What I suspect to happen is that the input of stringify is already presumed to be bytes, while CryptoJS functions return a WordArray of 32 bit words. As 8 * 32 = 256 this seems reasonable.
So I presume you can simply fix this by using a function on the WordArray instead, for instance hash.toString('hex').

How to decode ResponseAPDU to XML from an Austrian e-card?

I try to read information from an Austrian e-card to get the first name and last name.
What works for now is: Access the card, send APDU commands and get the information as byte array.
How can I convert the received byte array to XML to extract the needed data?
Here is the code:
import java.util.List;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;
public class Main2 {
public static void main(String[] args) {
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals;
try {
terminals = factory.terminals().list();
CardTerminal terminal = terminals.get(0);
Card card = terminal.connect("*");
CardChannel channel = card.getBasicChannel();
// Select the MF
byte[] aid = { (byte) 0xD0, 0x40, 0x00, 0x00, 0x17, 0x01, 0x01, 0x01 };
ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04, 0x00, aid));
System.out.println("Response: " + resp.toString());
// Select the Personaladata-file
byte[] aid2 = { (byte) 0xEF, 0x01 };
resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x02, 0x04, aid2));
System.out.println("Response: " + resp.toString());
// Get the data from the file
resp = channel.transmit(new CommandAPDU(0x00, 0xB0, 0x00, 0x00, 0xFF));
System.out.println("Response: " + resp.toString());
System.out.println("Response String: " + new String(resp.getData()));
card.disconnect(false);
} catch (CardException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I'm not sure how to transform that data into an XML structure (and according to what schema). However, the byte array that I received from my SV card looks like an ASN.1 DER encoded TLV structure:
30 xxxx
SEQUENCE
30 18
SEQUENCE
06 08
OBJECT IDENTIFIER
2A28000A01040101
=> OID 1.2.40.0.10.1.4.1.1 (SV number)
31 0C
SET
12 0A
NumericString
nnnnnnnnddddmmmmyyyy
=> SV number: NNNN DDMMYY
30 0F
SEQUENCE
06 08
OBJECT IDENTIFIER
2A28000A01040103
=> OID 1.2.40.0.10.1.4.1.3 (Card sequence number)
31 03
SET
02 01
INTEGER
xx
=> Card sequence number: xx
30 xx
SEQUENCE
[...]
30 xx
SEQUENCE
06 03
OBJECT IDENTIFIER
55042A
=> OID 2.5.4.42 ({joint-iso-itu-t(2) ds(5) attributeType(4) givenName(42)})
31 xx
SET
0C xx
UTF8String
4D69636861656C
=> Given name: "Michael"
30 xx
SEQUENCE
06 03
OBJECT IDENTIFIER
550404
=> OID 2.5.4.4 ({joint-iso-itu-t(2) ds(5) attributeType(4) surname(4)})
31 xx
SET
0C xx
UTF8String
526F6C616E64
=> Surname: "Roland"
30 xx
SEQUENCE
[...]
30 1D
SEQUENCE
06 08
OBJECT IDENTIFIER
2B06010505070901
=> OID 1.3.6.1.5.5.7.9.1 ({iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) pda(9) dateOfBirth(1)})
31 11
SET
18 0F
GeneralizedTime
yyyyyyyymmmmdddd3132303030305A
=> Date of birth: YYYY-MM-DD 12:00:00Z
30 0F
SEQUENCE
06 08
OBJECT IDENTIFIER
2B06010505070903
=> OID 1.3.6.1.5.5.7.9.3 ({iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) pda(9) gender(3)})
31 03
SET
13 01
PrintableString
4D
=> Gender: M (male)
So this seems to follow something like the following ASN.1 notation:
SVPersonGrunddaten ::= SEQUENCE OF Attribute
Attribute ::= SEQUENCE {
attributeName OBJECT IDENTIFIER,
attributeValue SET OF AttributeType }
AttributeType ::= CHOICE {
numericString NumericString,
integer INTEGER,
utf8String UTF8String,
time GeneralizedTime,
printableString PrintableString }
Where the attributes for the given name and the surname are
givenName Attribute ::= {
attributeName 2.5.4.42,
attributeValue { utf8String "Given Name" }
}
surname Attribute ::= {
attributeName 2.5.4.4,
attributeValue { utf8String "Surname" }
}
So in order to get the given name and the surname, you would parse the TLV structure, search for the OIDs of those two elements, and decode the associated values as a UTF8 string.
Note that simply assuming that the fields are there at the exact positions does not seem to be a good idea. For instance, there is a field 30 xx ... (a field of type Attribute) before the given name field that seems to be only present if there is an academic/professional title (e.g. "Dr." in my case) printed on the card. Similarly, there is another optional field for academic suffixes (such as "M.Sc.") that is only present if such a suffix is printed on the card. Though all other fields were always in the same order on my cards, I'm not sure if that's even required.
Thanks for the hint, here are code to decode the DER byte array to String
ASN1InputStream input = new ASN1InputStream(resp.getData());
ASN1Primitive p;
try {
while ((p = input.readObject()) != null) {
// System.out.println("DEBUG: " + ASN1Dump.dumpAsString(p));
// Sozialversicherungsnummer
ASN1Sequence asn1 = ASN1Sequence.getInstance(p);
ASN1Sequence seq = DLSequence.getInstance(asn1.getObjectAt(0));
ASN1Set svn = DLSet.getInstance(seq.getObjectAt(1));
DERNumericString svnObject = DERNumericString.getInstance(svn.getObjectAt(0));
System.out.println("SVN: " + svnObject.getString());
// Vorname
seq = DLSequence.getInstance(asn1.getObjectAt(2));
svn = DLSet.getInstance(seq.getObjectAt(1));
DERUTF8String stringObject = DERUTF8String.getInstance(svn.getObjectAt(0));
System.out.println("Vorname: " + stringObject.getString());
// Nachname
seq = DLSequence.getInstance(asn1.getObjectAt(3));
svn = DLSet.getInstance(seq.getObjectAt(1));
stringObject = DERUTF8String.getInstance(svn.getObjectAt(0));
System.out.println("Vorname: " + stringObject.getString());
// Geschlecht
seq = DLSequence.getInstance(asn1.getObjectAt(5));
svn = DLSet.getInstance(seq.getObjectAt(1));
DERPrintableString charObject = DERPrintableString.getInstance(svn.getObjectAt(0));
System.out.println("Geschlecht: " + charObject.getString());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

PNG True color with Alpha decoding

I am writing a PNG decoder and I am encountering some weirdness. Going through the PNG file format, I have managed to decode PNGs with Color Index + tRNS (alpha) and True Color + tRNS (alpha) correctly. I am currently not sure why I cannot decode a PNG with True Color with Alpha type PNG. I have verified that my inflate of IDAT chunk is correct. Here's what the chunks looks like:
Width: 256
Height: 256
Bit Depth: 8
Color Type: 6
Compression: 0
Filter: 0
Interlace: 0
Length: 25
Type: tEXt
Data: 53 6f 66 74 77 61 72 65 00 41 64 6f 62 65 20 49 6d 61 67 65 52 65 61 64 79
CRC: 71c9653c
Length: 20690
Type: IDAT
Data: 78 da ec 7d 09 9c 1c 57 99 df f7 7a a6 e7 3e 5a a3 fb ...
CRC: 21550259
The actual data is too long to be printed here. Here's my logic of decoding this, please correct me if I'm wrong:
Inflate all the bytes given in the IDAT chunk
Un-filter the inflated chunks. In this case, all filters are of type 0 and therefore, we simply discard the filter byte.
Since this is color type 6, a pixel is represented by RGBA channels with 1 byte each. This means we need to interpret 4 bytes at a time. The following code is used:
ByteBuffer image = BufferUtil.getDirectByteBuffer(data.length, ByteOrder.BIG_ENDIAN);
int i = 0;
while(i < data.length){
int color = ( (data[i] & 0xff) << 24) | ( (data[i+1] & 0xff) << 16) | ( (data[i+2] & 0xff) << 8) | (data[i+3] & 0xff);
image.putInt(color);
i += 4;
What's strange is that I get mostly RRGGBBAA = 0x00000000 data resulting in a clear image with little color.
The problem is you are neglecting to observe the filtering for each scanline.
From the image provided the decompressed data looks like
1 ffffffff 0 0 0 ...
2 0 0 0 0 0 0 ...
..
the first value in each line conforms to the filter method used [http://www.w3.org/TR/PNG/#9Filters]
the scanlines post processing will look like
ffffffff ffffffff ffffffff ...
ffffffff ffffffff ffffffff ...
...
here is some example code that handles methods 0, 1 and 2.
private static void processScanLine(byte filterValue, byte[] scanLine, byte[] previousScanLine) {
switch(filterValue){
case 0:break;
case 1:
for (int i =4;i<scanLine.length;i++){
scanLine[i] = (byte)(scanLine[i]+scanLine[i-4]);
}
break;
case 2:
for (int i =0;i<scanLine.length;i++){
scanLine[i] = (byte)(scanLine[i]+previousScanLine[i]);
}
break;
}
}

How to replicate struct.pack in java at a low level

I have been working with a client/server where the client is written in Java (Android) and the server is written in C++. I basically need to be able to pass it a dataset and have it interpret that data correctly.
I wrote a prototype in Python, as I know what its supposed to look like there. With struct.pack, it will pack the data and you can specify that it do it in network byte order (Big Endian). This is the prototype that I wrote (and this works with the server).
5 def _BuildPDUToTx(pduObj):
6 txData = struct.pack('!i i', pduObj.Src.Type, pduObj.Src.Len) #pduObj.Src.Type: 1
#pduObj.Src.Len: 16
7 txData += pduObj.Src.Value #pduObj.Src.Value: sourceid
8 txData += struct.pack('!i i', pduObj.Dst.Type, pduObj.Dst.Len) #pduObj.Dst.Type: 2
#pduObj.Dst.Len: 14
9 txData += pduObj.Dst.Value #pduObj.Dst.Value: destid
10 txData += struct.pack('!i i i i', pduObj.Metadata.Type, pduObj.Metadata.Len,\ #pduObj.Metadata.Type: 3
11 pduObj.Metadata.Status, pduObj.Metadata.Remaining) #pduObj.Metadata.Len: 16
#pduObj.Metadata.Status: 0
#pduObj.Metadata.Remaining: 0
12 txData += struct.pack('!i i', pduObj.Msg.Type, pduObj.Msg.Len) #pduObj.Msg.Type: 6
#pduObj.Msg.Len: 27
13 txData += pduObj.Msg.Value #pduObj.Msg.Value: This is the message
14 return(txData)
I ran it with some example code (the example values are the comments on the side), and I get the following if I setup a raw netcat listener on the server side (just to see what the data looks like).
0000000 0000 0100 0000 1000 [6f73 7275 6563 6469] *brackets have "sourceid"
0000010 0000 0200 0000 0e00 [6564 7473 6469] 0000 *brackets have "destid"
0000020 0300 0000 1000 0000 0000 0000 0000 0000
0000030 0600 0000 1b00 [6854 7369 6920 2073 6874 *brackets have "This is the message"
0000040 2065 656d 7373 6761 0065]
I have tried doing the same (and used the advice of Java equivalent of Python's struct.pack? and Using Java's ByteBuffer to replicate Python's struct.pack).
I used the following code:
client = new Socket(server, port);
ObjectOutputStream dos = new ObjectOutputStream(new BufferedOutputStream(client.getOutputStream()));
ByteBuffer buffer = ByteBuffer.allocate(1000);
dos.writeInt(Src.Type); // int value 1
dos.writeInt(Src.Len); // int value 16
dos.writeUTF(Src.Value); // String value "sourceid"
dos.writeInt(Dst.Type); // int value 2
dos.writeInt(Dst.Len); // int value 14
dos.writeUTF(Dst.Value); // String value "destid"
dos.writeInt(Metadata.Type); // int value 3
dos.writeInt(Metadata.Len); // int value 16
dos.writeInt(Metadata.Status); // int value 0
dos.writeInt(Metadata.Remaining); // int value 0
dos.writeInt(Msg.Type); // int value 6
dos.writeInt(Msg.Len); // int value 27
dos.writeUTF(Msg.Value); // String value "this is the message"
dos.flush();
InputStream is = client.getInputStream();
byte[] buf = new byte[Constants.ResponseSize];
is.read(buf, 0, Constants.ResponseSize);
client.close();
However, I get the following.
0000000 edac 0500 4f77 0000 0100 0000 1000 0800
0000010 [6f73 7275 6563 6469] 0000 0200 0000 0e00 *brackets have "sourceid"
0000020 0600 [6564 7473 6469] 0000 0300 0000 1000 *brackets have "destid"
0000030 0000 0000 0000 0000 0000 0600 0000 1b00
0000040 1300 [6854 7369 6920 2073 6874 2065 656d *brackets have "This is the message"
0000050 7373 6761 0065]
0000055
Java seems to be adding quite a bit of extra. Like the first two bytes dont go with anything I put in the stream. Thats followed with my value of 1 (32 bits) and 16 (the next 32 bits), but then it has 0800 before the "sourceid".
What the heck is Java doing?? And how can I get it to pack more like python?
Use DataOutputStream, not ObjectOutputStream.
ObjectOutputStream is used to ship Java objects from one JVM to another, and is primarily used by java object serialization framework.
DataOutputStream writes everything in Big Endian.
You may have to be careful, though, with writeUTF. By spec, it prepends the length of the byte sequence. This may, or may not, be what you want.

Categories