# CRC creation problem.

Here's my situation:

I have a string in Hex format:

C8005106FA0603041609150000000000050000000000050000000000000030303030303100000500082602000000000000000000000000000200000001000000000100000000000000000000000000000000520103

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"
*
*@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.substring(2 * i, 2 * i + 1), 16);
// [x,y)
byte secondNibble = Byte.parseByte(hexStr.substring(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("Original Hex String: " + hexstring);

byte[] ba = toBinArray(hexstring);
System.out.println("Converted to Byte array");

System.out.println("Reconversion 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));
}
}
###### Who is Participating?

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Commented:
Here's the way Sun does it. Maybe you can compare:

http://mindprod.com/jgloss/crc.html
Commented:
See here to calculate a checksum.
http://javaalmanac.com/egs/java.util.zip/CalculateChecksum.html

Bye, Giant.
Commented:
And here:
http://www.java2s.com/Code/Java/Security/CRC.htm

Bye, Giant.
Commented:
does anybody know whats the deference between CRC and CRC32 ?
Commented:
Maybe here there is an expanation:
http://en.wikipedia.org/wiki/Cyclic_redundancy_check
Commented:
Incidentally, taking those bytes as big-endian, with sun.misc.CRC16, i get

d0e3

Taking it as little-endian, i get

c1ea
Commented:
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
Commented:
>>> 16 bit
Commented:
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)
Commented:

->
private final static int poly = 0x8408;

private static int[] crcTable = new int[256];
static {
// initialise scrambler table
for (int i = 0; i < 256; i++) {
int fcs = 0;
int d = i ;
for (int k = 0; k < 8; k++) {
if (((fcs ^ d) & 0x0001) != 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 = 0;
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)) & 0xff] ^ (work >>> 8)) &
0xffff;
}
return (short) work;
}

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Commented:

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;
}
}
Author Commented:
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
Commented:
:-)
###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.