stevebeech
asked on
CRC creation problem.
Here's my situation:
I have a string in Hex format:
C8005106FA0603041609150000 0000000500 0000000005 0000000000 0000303030 3030310000 0500082602 0000000000 0000000000 0000000200 0000010000 0000010000 0000000000 0000000000 0000000052 0103
and I need to calculate a CRC for it, which I know should be 8DDE.
However, my code gives the result as: CD51
Can anyone spot where I've gone wrong? (I'm using the CCITT version of CRC 16bit generation I think) Here's my class (called like "java CRC16 C800510.......")
public class CRC16 {
/** generator polynomial */
private final static int poly = 0x1021;
/*
x16 + x12 + x5 + 1 generator polynomial
*/
/*
0x8408 used in European X.25
*/
/** scrambler lookup table for fast computation. */
private static int[] crcTable = new int[256];
static {
// initialise scrambler table
for (int i = 0; i < 256; i++) {
int fcs = 0;
int d = i << 8;
for (int k = 0; k < 8; k++) {
if (((fcs ^ d) & 0x8000) != 0) {
fcs = (fcs << 1) ^ poly;
} else {
fcs = (fcs << 1);
}
d <<= 1;
fcs &= 0xffff;
}
crcTable[i] = fcs;
}
}
/**
* Calc CRC with CCITT method.
*
*@param b byte array to compute CRC on
*@return 16-bit CRC, unsigned
*/
public static short crc16(byte[] b) {
// loop, calculating CRC for each byte of the string
int work = 0xffff;
for (int i = 0; i < b.length; i++) {
// xor the next data byte with the high byte of what we have so far to
// look up the scrambler.
// xor that with the low byte of what we have so far.
// Mask back to 16 bits.
work = (crcTable[(b[i] ^ (work >>> 8)) & 0xff] ^ (work << 8)) &
0xffff;
}
return (short) work;
}
/**
* Convert a byte[] array to readable string format. This makes the "hex"
* readable!
*
*@param in byte[] buffer to convert to string format
*@return result String buffer in String format
*/
public static String byteArrayToHexString(byte in[]) {
byte ch = 0x00;
int i = 0;
if (in == null || in.length <= 0) {
return null;
}
String pseudo[] = {"0", "1", "2",
"3", "4", "5", "6", "7", "8",
"9", "A", "B", "C", "D", "E",
"F"};
StringBuffer out = new StringBuffer(in.length * 2);
while (i < in.length) {
ch = (byte) (in[i] & 0xF0);
// Strip off high nibble
ch = (byte) (ch >>> 4);
// shift the bits down
ch = (byte) (ch & 0x0F);
// must do this is high order bit is on!
out.append(pseudo[(int) ch]);
// convert the nibble to a String Character
ch = (byte) (in[i] & 0x0F);
// Strip off low nibble
out.append(pseudo[(int) ch]);
// convert the nibble to a String Character
i++;
}
String rslt = new String(out);
return rslt;
}
/**
* Description of the Method
*
*@param hexStr Description of the Parameter
*@return Description of the Return Value
*/
public static byte[] toBinArray(String hexStr) {
byte bArray[] = new byte[hexStr.length() / 2];
for (int i = 0; i < (hexStr.length() / 2); i++) {
byte firstNibble = Byte.parseByte(hexStr.subs tring(2 * i, 2 * i + 1), 16);
// [x,y)
byte secondNibble = Byte.parseByte(hexStr.subs tring(2 * i + 1, 2 * i + 2), 16);
int finalByte = (secondNibble) | (firstNibble << 4);
// bit-operations only with numbers, not bytes.
bArray[i] = (byte) finalByte;
}
return bArray;
}
/**
* Description of the Method
*
*@param a Description of the Parameter
*@return Description of the Return Value
*/
public static String ShortToHex(long a) {
String hex = "0123456789ABCDEF";
char[] digits = new char[4];
for (int k = (3); k >= 0; k--) {
digits[k] = hex.charAt((int) (a & 15));
a = a >>> 4;
}
return new String(digits);
}
/**
* Description of the Method
*
*@param args Description of the Parameter
*/
public static void main(String args[]) {
if (args.length != 1) {
System.out.println("Usage: java CRC16 parameter - where parameter is a Hex string (e.g. AF34BD");
System.exit(-1);
}
String hexstring = args[0];
System.out.println("Origin al Hex String: " + hexstring);
byte[] ba = toBinArray(hexstring);
System.out.println("Conver ted to Byte array");
System.out.println("Reconv ersion gives: " + byteArrayToHexString(ba));
System.out.println("Now calculating CRC....");
short x = crc16(ba);
String str = Integer.toBinaryString(x);
System.out.println("Binary representation of CRC: " + str);
System.out.println("Now converting to a two byte array");
byte[] byte_array = str.getBytes();
String q = byteArrayToHexString(byte_ array);
System.out.println("Hex value of 2 byte array (short): " + q);
System.out.println("Hex Val of Short: " + ShortToHex(x));
}
}
I have a string in Hex format:
C8005106FA0603041609150000
and I need to calculate a CRC for it, which I know should be 8DDE.
However, my code gives the result as: CD51
Can anyone spot where I've gone wrong? (I'm using the CCITT version of CRC 16bit generation I think) Here's my class (called like "java CRC16 C800510.......")
public class CRC16 {
/** generator polynomial */
private final static int poly = 0x1021;
/*
x16 + x12 + x5 + 1 generator polynomial
*/
/*
0x8408 used in European X.25
*/
/** scrambler lookup table for fast computation. */
private static int[] crcTable = new int[256];
static {
// initialise scrambler table
for (int i = 0; i < 256; i++) {
int fcs = 0;
int d = i << 8;
for (int k = 0; k < 8; k++) {
if (((fcs ^ d) & 0x8000) != 0) {
fcs = (fcs << 1) ^ poly;
} else {
fcs = (fcs << 1);
}
d <<= 1;
fcs &= 0xffff;
}
crcTable[i] = fcs;
}
}
/**
* Calc CRC with CCITT method.
*
*@param b byte array to compute CRC on
*@return 16-bit CRC, unsigned
*/
public static short crc16(byte[] b) {
// loop, calculating CRC for each byte of the string
int work = 0xffff;
for (int i = 0; i < b.length; i++) {
// xor the next data byte with the high byte of what we have so far to
// look up the scrambler.
// xor that with the low byte of what we have so far.
// Mask back to 16 bits.
work = (crcTable[(b[i] ^ (work >>> 8)) & 0xff] ^ (work << 8)) &
0xffff;
}
return (short) work;
}
/**
* Convert a byte[] array to readable string format. This makes the "hex"
* readable!
*
*@param in byte[] buffer to convert to string format
*@return result String buffer in String format
*/
public static String byteArrayToHexString(byte in[]) {
byte ch = 0x00;
int i = 0;
if (in == null || in.length <= 0) {
return null;
}
String pseudo[] = {"0", "1", "2",
"3", "4", "5", "6", "7", "8",
"9", "A", "B", "C", "D", "E",
"F"};
StringBuffer out = new StringBuffer(in.length * 2);
while (i < in.length) {
ch = (byte) (in[i] & 0xF0);
// Strip off high nibble
ch = (byte) (ch >>> 4);
// shift the bits down
ch = (byte) (ch & 0x0F);
// must do this is high order bit is on!
out.append(pseudo[(int) ch]);
// convert the nibble to a String Character
ch = (byte) (in[i] & 0x0F);
// Strip off low nibble
out.append(pseudo[(int) ch]);
// convert the nibble to a String Character
i++;
}
String rslt = new String(out);
return rslt;
}
/**
* Description of the Method
*
*@param hexStr Description of the Parameter
*@return Description of the Return Value
*/
public static byte[] toBinArray(String hexStr) {
byte bArray[] = new byte[hexStr.length() / 2];
for (int i = 0; i < (hexStr.length() / 2); i++) {
byte firstNibble = Byte.parseByte(hexStr.subs
// [x,y)
byte secondNibble = Byte.parseByte(hexStr.subs
int finalByte = (secondNibble) | (firstNibble << 4);
// bit-operations only with numbers, not bytes.
bArray[i] = (byte) finalByte;
}
return bArray;
}
/**
* Description of the Method
*
*@param a Description of the Parameter
*@return Description of the Return Value
*/
public static String ShortToHex(long a) {
String hex = "0123456789ABCDEF";
char[] digits = new char[4];
for (int k = (3); k >= 0; k--) {
digits[k] = hex.charAt((int) (a & 15));
a = a >>> 4;
}
return new String(digits);
}
/**
* Description of the Method
*
*@param args Description of the Parameter
*/
public static void main(String args[]) {
if (args.length != 1) {
System.out.println("Usage:
System.exit(-1);
}
String hexstring = args[0];
System.out.println("Origin
byte[] ba = toBinArray(hexstring);
System.out.println("Conver
System.out.println("Reconv
System.out.println("Now calculating CRC....");
short x = crc16(ba);
String str = Integer.toBinaryString(x);
System.out.println("Binary
System.out.println("Now converting to a two byte array");
byte[] byte_array = str.getBytes();
String q = byteArrayToHexString(byte_
System.out.println("Hex value of 2 byte array (short): " + q);
System.out.println("Hex Val of Short: " + ShortToHex(x));
}
}
See here to calculate a checksum.
http://javaalmanac.com/egs/java.util.zip/CalculateChecksum.html
Bye, Giant.
http://javaalmanac.com/egs/java.util.zip/CalculateChecksum.html
Bye, Giant.
And here:
http://www.java2s.com/Code/Java/Security/CRC.htm
Hope these links could help you.
Bye, Giant.
http://www.java2s.com/Code/Java/Security/CRC.htm
Hope these links could help you.
Bye, Giant.
does anybody know whats the deference between CRC and CRC32 ?
Maybe here there is an expanation:
http://en.wikipedia.org/wiki/Cyclic_redundancy_check
http://en.wikipedia.org/wiki/Cyclic_redundancy_check
Incidentally, taking those bytes as big-endian, with sun.misc.CRC16, i get
d0e3
Taking it as little-endian, i get
c1ea
d0e3
Taking it as little-endian, i get
c1ea
i have already calculated the CRC32 of the givven hex string and that was 59a817f9
the asker said it should be 8DDE, so he can not produce that checksum with java.util.zip.crc32 either
he needs a 16 checksum instead
the asker said it should be 8DDE, so he can not produce that checksum with java.util.zip.crc32 either
he needs a 16 checksum instead
>>> 16 bit
Hi stevebeech,
I just tested your string into my hex editor with CRC calculation :
init value=FFFF xor=0 key=1021 highbit first -> crc-16 = CD51 (the value you get)
init value=0000 xor=0 key=8408 lowbit first -> crc-16 = 8DDE (the value you want)
I just tested your string into my hex editor with CRC calculation :
init value=FFFF xor=0 key=1021 highbit first -> crc-16 = CD51 (the value you get)
init value=0000 xor=0 key=8408 lowbit first -> crc-16 = 8DDE (the value you want)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
And your static initialisation can be simplified :
static {
// initialise scrambler table
for (int i = 0; i < 256; i++) {
int fcs = i;
for (int k = 0; k < 8; k++) {
if ((fcs & 0x0001) != 0) {
fcs = (fcs >>> 1) ^ poly;
} else {
fcs = (fcs >>> 1);
}
fcs &= 0xffff;
}
crcTable[i] = fcs;
}
}
ASKER
You don't know how happy you've made me, Webstorm.
I'd figured that I'd got the wrong initializer, thought that the poly needed to be reflected, but hadn't figured the bit ordering was wrong.
Just one error in your code:
work = (crcTable[(b[i] ^ work)) & 0xff] ^ (work >>> 8)) & 0xffff;
should be:
work = (crcTable[(b[i] ^ work) & 0xff] ^ (work >>> 8)) & 0xffff;
Apart from that it works like a dream - you get all the points!
Cheers,
Steve
I'd figured that I'd got the wrong initializer, thought that the poly needed to be reflected, but hadn't figured the bit ordering was wrong.
Just one error in your code:
work = (crcTable[(b[i] ^ work)) & 0xff] ^ (work >>> 8)) & 0xffff;
should be:
work = (crcTable[(b[i] ^ work) & 0xff] ^ (work >>> 8)) & 0xffff;
Apart from that it works like a dream - you get all the points!
Cheers,
Steve
:-)
http://mindprod.com/jgloss/crc.html