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"
       *  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.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));
      }
}
stevebeechAsked:
Who is Participating?
 
WebstormCommented:

->
     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;
     }

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

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

Bye, Giant.
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
Giant2Commented:
And here:
http://www.java2s.com/Code/Java/Security/CRC.htm

Hope these links could help you.
Bye, Giant.
0
 
hoomanvCommented:
does anybody know whats the deference between CRC and CRC32 ?
0
 
Giant2Commented:
Maybe here there is an expanation:
http://en.wikipedia.org/wiki/Cyclic_redundancy_check
0
 
CEHJCommented:
Incidentally, taking those bytes as big-endian, with sun.misc.CRC16, i get

d0e3

Taking it as little-endian, i get

c1ea
0
 
hoomanvCommented:
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
0
 
hoomanvCommented:
>>> 16 bit
0
 
WebstormCommented:
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)
0
 
WebstormCommented:

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;
          }
     }
0
 
stevebeechAuthor 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
0
 
WebstormCommented:
:-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.