Wireshark checksum does not match - java

I have written a function that computes the checksum for a given tcp packet. However, when I capture a tcp packet sent over ipv4 from wireshark and let my function compute its checksum, then its not the same checksum as in the wireshark captured packet. I checked and the bytes I give to the computeChecksum function are exactly the same as the tcp packet bytes i captured with wireshark.
I computed the checksum according to the RFC 793. Does anybody see if there's anything wrong in my code?
public long computeChecksum( byte[] buf, int src, int dst ){
int length = buf.length; // nr of bytes of the tcppacket in total.
int pseudoHeaderLength = 12; // nr of bytes of pseudoheader.
int i = 0;
long sum = 0;
long data;
buf[16] = (byte)0x0; // set checksum to 0 bytes
buf[17] = (byte)0x0;
// create the pseudoheader as specified in the rfc.
ByteBuffer pseudoHeaderByteBuffer = ByteBuffer.allocate( 12 );
pseudoHeaderByteBuffer.putInt( src );
pseudoHeaderByteBuffer.putInt( dst );
pseudoHeaderByteBuffer.put( (byte)0x0 ); // store the 0x0 byte
pseudoHeaderByteBuffer.put( (byte)PROTO_NUM_TCP ); // stores the protocol number
pseudoHeaderByteBuffer.putShort( (short) length ); // store the length of the packet.
byte[] pbuf = pseudoHeaderByteBuffer.array();
// loop through all 16-bit words of the psuedo header
int bytesLeft = pseudoHeaderLength;
while( bytesLeft > 0 ){
// store the bytes at pbuf[i] and pbuf[i+1] in data.
data = ( ((pbuf[i] << 8) & 0xFF00) | ((pbuf[i + 1]) & 0x00FF));
sum += data;
// Check if the sum has bit 17 or higher set by doing a binary AND with the 46 most significant bits and 0xFFFFFFFFFF0000.
if( (sum & 0xFFFFFFFF0000) > 0 ){
sum = sum & 0xFFFF; // discard all but the 16 least significant bits.
sum += 1; // add 1 (because we have to do a one's complement sum where you add the carry bit to the sum).
}
i += 2; // point to the next two bytes.
bytesLeft -= 2;
}
// loop through all 16-bit words of the TCP packet (ie. until there's only 1 or 0 bytes left).
bytesLeft = length;
i=0;
while( bytesLeft > 1 ){ // note that with the pseudo-header we could never have an odd byte remaining.
// We do do exactly the same as with the pseudo-header but then for the TCP packet bytes.
data = ( ((buf[i] << 8) & 0xFF00) | ((buf[i + 1]) & 0x00FF));
sum += data;
if( (sum & 0xFFFF0000) > 0 ){
sum = sum & 0xFFFF;
sum += 1;
}
i += 2;
bytesLeft -= 2;
}
// If the data has an odd number of bytes, then after adding all 16 bit words we remain with 8 bits.
// In that case the missing 8 bits is considered to be all 0's.
if( bytesLeft > 0 ){ // ie. there are 8 bits of data remaining.
sum += (buf[i] << 8 & 0xFF00); // construct a 16 bit word holding buf[i] and 0x00 and add it to the sum.
if( (sum & 0xFFFF0000) > 0) {
sum = sum & 0xFFFF;
sum += 1;
}
}
sum = ~sum; // Flip all bits (ie. take the one's complement as stated by the rfc)
sum = sum & 0xFFFF; // keep only the 16 least significant bits.
return sum;
}
If you don't see anything wrong with the code then let me know that too. In that case I know to look somewhere else for the problem.

I've tested your code and it works correctly. I've done the following:
Configure wireshark to "Validate the TCP checksum if possible" in order to avoid to do the test with a packet with an incorrect checksum.
Add the long type suffix L to the constant 0xFFFFFFFF0000 in order to avoid the compile time error integer number too large (Java 8).
Use an hexadecimal representation of a TCP segment coming from wireshark
String tcpSegment = "0050dc6e5add5b4fa9bf9ad8a01243e0c67c0000020405b4010303000101080a00079999000d4e0e";
Use a method to convert an hexadecimal string to a byte array
public static byte[] toByteArray(String strPacket) {
int len = strPacket.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(strPacket.charAt(i), 16) << 4)
+ Character.digit(strPacket.charAt(i + 1), 16));
}
return data;
}
Use a ByteBuffer to write the source and destination adress into an int
int src = ByteBuffer.wrap(toByteArray("c0a80001")).getInt();
int dst = ByteBuffer.wrap(toByteArray("c0a8000a")).getInt();
With this, I obtain a checksum of C67C, the same as in wireshark.
P.S.: There is an error in your code when you do
pseudoHeaderByteBuffer.putShort( (short) length );
you store the length in two's-complement inside the pseudo header which will be a problem if the length is greater than 2^15. You better used char which is 16 bit unsigned.

Related

How to find headers of MP3 audio clip?

The primary problem I am trying to solve here is to find the length of a MP3 audio clip given in the form of a byte array. In order to find the length, I need to find the number of frames in the clip. According to the MP3 spec, a frame is a byte with 11 consecutive bits set to 1; i.e a byte with a value of 255 and followed by a byte with it's 3 most significant bit set to 1 (decimal value 224). So essentially, once I find a byte value of 255, I am checking if the very next byte is of value 224. But given this criterion, I am not able to find any frame headers in the array. In addition, the referenced doc also mentioned that the next byte after 255 may at times have its 4 MSB set to 1. This way I should be searching for value 240 after 255. Both in either case, I am not able to locate any frame headers. Please advise if I am doing this correctly.
This is my code:
public class AudioUtils
{
public static int getAudioLength(byte[] audio, AudioFormat audioFormat, int samples, int sampleRate)
{
if (!audioFormat.getId().equals(AudioFormat.MP3))
throw new UnsupportedOperationException(String.format("Audio length computation for audio of format %s is not supported", audioFormat.getFormat()));
int frames = getNumberOfFrames(audio);
return ((frames * samples) / sampleRate);
}
private static int getNumberOfFrames(byte[] audio)
{
int frames = 0;
for (int i = 0; i < audio.length; i++)
{
byte b = audio[i];
int byteInt = b & 0xff; // convert byte to int
if (byteInt == 255)
{
// If there is another byte in the array
if (i + 1 < audio.length && (audio[i + 1] & 0xff) == 224)
{
// We have found an header. Increment the frames count.
frames++;
}
}
}
return frames;
}
}
Since sync word is only 11 bits and you don't know the contents of the remaining 5 bits, you need compare only the first 3 bits of the second byte. A common way to accomplish this is use the binary '&' operator to set the bits you want to ignore to 0 (called masking) and set those same bits to 0 in the constant you are trying to compare with.
In the example below, the second byte is masked with 0xe0 and compared with the same value.
for (int i = 0; i < audio.length - 1; i++)
{
if (audio[i] == 0xff && (audio[i+1] & 0xe0) == 0xe0)
{
frames++;
}
}

how to make a CRC in python for a serial device?

I have to build a serial comunication app using python, the old app is only working on windows xp and was written in C. Now i have to switch to linux and i dont have a working driver. I started to code it myself. I got the protocol from the producing company of the serial device.
The serial device receives and sends data wich is ended by a CRC. I'm new to python and i dont have a solution for this, maybe someone can help me.
This is the CRC alghoritm:
ALGORITHM FOR CRC CALCULATION
The two CRC bytes are calculated according to the formula x^15 + 1. In the calculation are included all data bytes plus the byte for block end. Every byte passes through the calculation register from teh MSB to LSB.
Three working bytes are used - S1, S0 and TR
S1 - Most significant byte from the CRC ( it is transmitted immediatelly after END)
S0 - Least significant byte from the CRC ( It is transmitted after S1)
TR - the current transmitted byte in the block.
The CRC is calculated as follows:
1. S1 and S0 are zeroed
2. TR is loaded with the current transmitted byte. The byte is transmitted.
3. Points 3.1 and 3.2 are executed 8 times:
3.1. S1, S0 and TR are shifted one bit to the left.
3.2. If the carry bit from S1 is 1, the MSB of S1 and LSB of S0 are inverted.
Points 2 and 3 are executed for all bytes, included in the calculation of the CRC - from the first byte after BEG up to and including byte END.
4. TR is loaded with 0 and point 3 is executed
5. TR is loaded with 0 and point 3 is executed
6. Byte S1 is transmitted
7. Byte S0 is transmitted
ALGORITHM FOR CRC CHECK ON RECEIVING
Three working bytes are used S1, S0 and RC
S1 - Most significant byte from the CRC ( it is received immediately after END)
S0 - Least significant byte from the CRC ( transmitted after S1)
RC - the current received byte in the block ( beginning from the first byte after BEG and ending 2 bytes after END).
The CRC is obtained as follows:
1. S1 and S0 are zeroed
2. RC is loaded with the current received byte
3. Points 3.1 and 3.2 are executed 8 times:
3.1. S1, S0 and RC are shifted 8 times to the left
3.2. if the MSB of S1 is 1 then MSB of S1 and LSB of S0 are inverted.
Points 2 and 3 are executed for all bytes, included in the calculation of the CRC - from the first byte after BEG up to and including 2 bytes after END.
S1 and S0 must be 0.
If there is someone wich can show me how to do it i'll be very gratefull.Thank you all.
EDIT 1:
I managed to get the same CRC procedure made by someone, but its made in java, i'm not that good with java. Maybe you can guide me into converting it in python. This is the code:
public class Crc {
public static final String CRC_NAME = "CRC-16-ECR";
private static final int POLYNOMIAL = 32769;
public static final int WIDTH = 16;
public static final int TOPBIT = 32768;
short CRC;
short[] crcTable = new short[256];
public Crc() {
this.crcInit();
}
private void crcInit() {
for(int dividend = 0; dividend < 256; ++dividend) {
int remainder = dividend << 8;
for(byte bit = 8; bit > 0; --bit) {
if((remainder & '耀') != 0) {
remainder = (remainder << 1 ^ '老') & '\uffff';
} else {
remainder = remainder << 1 & '\uffff';
}
}
this.crcTable[dividend] = (short)remainder;
}
}
public short crcFast(byte[] message, int nBytes) {
int remainder = 0;
for(int oneByte = 0; oneByte < nBytes; ++oneByte) {
int data = (message[oneByte] ^ remainder >> 8) & 255;
remainder = this.crcTable[data] ^ remainder << 8;
}
return (short)remainder;
}
}
#!/usr/bin/python
import sys
crc = 0
while True:
ch = sys.stdin.read(1)
if not ch:
break
crc ^= ord(ch) << 8
for _ in range(8):
crc = crc << 1 if (crc & 0x8000) == 0 else (crc << 1) ^ 0x8001
crc &= 0xffff
print(format(crc, '04x'))

Unable to correctly generate checksum

I am trying to calculate a simple checksum and then I'm doing a checksum test.
public void readfile()
{
byte counter = 0;
byte[] data = new byte[68];
while(x.hasNextInt())
{
data[counter++] = (byte)x.nextInt();
if(counter == 67)
break;
}
int sum = 0;
for (int i = 0; i < 67; i++)
sum += (data[i] & 0xFF);
System.out.println((int)(sum & 0xFF)); //checksum
//perform checksum test.
data[counter] = (byte)(sum & 0xFF);
sum = 0;
for (int i = 0; i < 68; i++)
sum += (data[i] & 0xFF);
System.out.println((int)(sum & 0xFF)); //checksum test
}
I am reading the first 67 integer values of a file and saving them inside a byte array. All the integers are < 256. The variable 'x' is the file that I am reading. However, when I perform the checksum test, the value outputted isn't 0. I am not able to diagnose where I am computing incorrectly.
I'm not sure what you're trying to do.
You get the first 67 characters, calculate a checksum, and then assume that those 67, plus the checksum, is 0. It is not. You're ADDING the checksum, not subtracting it.
So if the checksum is not 0 or 128, you end up with a value that is twice the checksum. Right?

How can i credit or debit more than 1 byte to/from card?

I am newbie applets and i used from this link: working with Java Card
Wallet for creating an Wallet project.
I before could credit card amount by this command : 80 30 00 00 01 1A 00.
I now want add '5000' to the present amount. As you know 5000 in hex equals
with '1388' that is 2 byte. So i must send 2 byte data 13 and 88 to the card.
I create bellow command and sent it to card but i get '67 00 Wrong lenght' as
response.
80 30 00 00 02 13 88 00
How can i credit or debit more than 1 byte to/from card?
You'll have to change the code of the Applet you're pointing to of course:
if ((numBytes != 1) || (byteRead != 1)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); // constant with value 0x6700
}
So you must make sure that it allows for 2 bytes to be send, then you can use the Util.getShort method to convert to the bytes to a 16 bit signed value (using big endian two complement notation, as usual).
Replace the creadit() method, with this one. But remember that you must use two byte value for crediting you walled henceforth. (even for values less than 255 or 0xFF. i.e. you must use 0x00FF to debit you wallet with 255$ )
private void credit(APDU apdu) {
// access authentication
if (!pin.isValidated()) {
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
}
byte[] buffer = apdu.getBuffer();
// Lc byte denotes the number of bytes in the
// data field of the command APDU
byte numBytes = buffer[ISO7816.OFFSET_LC];
// indicate that this APDU has incoming data
// and receive data starting from the offset
// ISO7816.OFFSET_CDATA following the 5 header
// bytes.
byte byteRead = (byte) (apdu.setIncomingAndReceive());
// it is an error if the number of data bytes
// read does not match the number in Lc byte
if ((numBytes != 2) || (byteRead != 2)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// get the creditBytes
byte[] creditBytes = new byte[2];
creditBytes[0]=buffer[ISO7816.OFFSET_CDATA];
creditBytes[1]=buffer[ISO7816.OFFSET_CDATA+1];
// convert 2 byte of creatBytes to a single short value.
short creditAmount = Util.getShort(creditBytes,(short)0);
// check the credit amount
if ((creditAmount > MAX_TRANSACTION_AMOUNT) || (creditAmount < 0)) {
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
}
// check the new balance
if ((short) (balance + creditAmount) > MAX_BALANCE) {
ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
}
// credit the amount
balance = (short) (balance + creditAmount);
}
I propose using BCD addition and BCD subtraction, as follow:
Each byte represent two BCD, e.g. 0x99 represent 99 instead of 153.
All data included in the addition and subtraction shall have the same length, e.g. 6 bytes will represents 12 digits. This should cover most cases, but if you need more, simply change your constant.
Your applet performs loop through the bytes to do the addition or subtraction. Encode and decode operation from BCD to the value and vice versa are needed before and after the operation.
Here is sample for the implementation. It is not tested yet, but should give you idea of how it works:
public class BCD {
public static final short NUMBER_OF_BYTES = 6;
static void add(byte[] augend, byte[] addend, byte[] result) {
byte carry = 0;
short temp = 0;
for (short i = (short) (NUMBER_OF_BYTES - 1); i >= 0; i--) {
temp = (short) (decode(augend[i]) + decode(addend[i]) + carry);
carry = (byte) ((temp > 100) ? 1 : 0);
result[i] = encode((byte) temp);
}
if (carry == 1) {
// TODO: result more than maximum
// you can set all digits to 9 or throw exception
}
}
static void subtract(byte[] minuend, byte[] subtrahend, byte[] result) {
byte borrow = 0;
short temp = 0;
for (short i = (short) (NUMBER_OF_BYTES - 1); i >= 0; i--) {
temp = (short) (100 + decode(minuend[i]) - decode(subtrahend[i]) - borrow);
borrow = (byte) ((temp < 100) ? 1 : 0);
result[i] = encode((byte) temp);
}
if (borrow == 1) {
// TODO: subtrahend > minuend,
// you can set all digits to 0 or throw exception
}
}
static byte encode(byte value) {
value %= 100; // only convert two digits, ignore borrow/carry
return (byte) (((value / 10) << 4) | (value % 10));
}
static byte decode(byte bcdByte) {
byte highNibble = (byte) ((bcdByte >> 4) & 0x0F);
byte lowNibble = (byte) (bcdByte & 0x0F);
if ((highNibble > 9) || (lowNibble > 9)) {
// found 'A' to 'F' character which should be invalid
// you can change this line, e.g. throwing exception
return 0;
}
return (byte) ((highNibble * 10) + lowNibble);
}
}

Java convert long to 4 bytes

How do I convert long to 4 bytes? I am receiving some output from a C program and it uses unsigned long. I need to read this output and convert this to 4 bytes.
However, java uses signed long which is 64 bits. Is there any way to do this conversion?
To read 4 bytes as an unsigned 32-bit value, assuming it is little endian, the simplest thing to do is to use ByteBuffer
byte[] bytes = { 1,2,3,4 };
long l = ByteBuffer.wrap(bytes)
.order(ByteOrder.LITTLE_ENDIAN).getInt() & 0xFFFFFFFFL;
While l can be an signed 64-bit value it will only be between 0 and 2^^32-1 which is the range of a unsigned 32-bit value.
You can use the java.nio.ByteBuffer. It can parse the long, and it does the byte ordering for you.
You can code a loop where you divide the "long" by 256, take the rest, then you have the "Least Significant Byte" ...
(depending on whether you want little-endian or big-endian you can loop forwards or backwards)
long l = (3* 256 * 256 * 256 + 1 * 256 *256 + 4 * 256 + 8);
private byte[] convertLongToByteArray(long l) {
byte[] b = new byte[4];
if(java.nio.ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN){
for (int i=0; i<4; i++) {
b[i] = (byte)(l % 256) ;
l = l / 256;
}
}else{
for (int i=3; i>=0; i--) {
b[i] = (byte)(l % 256) ;
l = l / 256;
}
}
return b;
}

Categories

Resources