3

I need help with calculating of CCITT standard CRC with polynomial x^16 + x^12 + x^5 + 1 (0x1081) in Java. I have tried many examples on the internet but every one of them returns other values than the ones in the example.

For example for this array [0xFC] [05] [11] the result needs to be [27] [56].

Using this code:

public static void main(String[] args) {
        byte[] array = new byte[3];
        array[0] = (byte) 0xFC;
        array[1] = (byte) 0x05;
        array[2] = (byte) 0x11;
//        array[3] = (byte) 0x00;
//        array[4] = (byte) 0x00;

        System.out.println(Integer.toHexString(crc16(array)));
    }

    private static final int POLYNOMIAL = 0x1081;
    private static final int PRESET_VALUE = 0xFFFF;

    public static int crc16(byte[] data) {
        int current_crc_value = PRESET_VALUE;
        for (int i = 0; i < data.length; i++) {
            current_crc_value ^= data[i] & 0xFF;
            for (int j = 0; j < 8; j++) {
                if ((current_crc_value & 1) != 0) {
                    current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
                } else {
                    current_crc_value = current_crc_value >>> 1;
                }
            }
        }
        current_crc_value = ~current_crc_value;

        return current_crc_value & 0xFFFF;
    } 

I get result FA DE not [27] [56]

Using this code:

public static void main(String[] args) { 
        int crc = 0x0000;         
        int polynomial = 0x1081;   

        // byte[] testBytes = "123456789".getBytes("ASCII");

//        byte[] array = args[0].getBytes();
        byte[] array = new byte[3];
        array[0] = (byte) 0xFC;
        array[1] = (byte) 0x05;
        array[2] = (byte) 0x11;

        for (byte b : array) {
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b   >> (7-i) & 1) == 1);
                boolean c15 = ((crc >> 15    & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit) crc ^= polynomial;
             }
        }

        crc &= 0xffff;
        System.out.println("CRC16-CCITT = " + Integer.toHexString(crc));
    }

I get this CRC16-CCITT = 8dca

Using this code:

private final int polynomial = 0x1081;

    private int[] table = new int[256];

    public int ComputeChecksum(int[] bytes) {
        int crc = 0xffff;
        for (int i = 0; i < bytes.length; ++i) {
            int index = (crc ^ bytes[i]) % 256;
            crc = (crc >> 8) ^ table[index];
        }
        return crc;
    }

    public CRC162() {
        int value;
        int temp;
        for (int i = 0; i < table.length; ++i) {
            value = 0;
            temp = i;
            for (byte j = 0; j < 8; ++j) {
                if (((value ^ temp) & 0x0001) != 0) {
                    value = (value >> 1) ^ polynomial;
                } else {
                    value >>= 1;
                }
                temp >>= 1;
            }
            table[i] = value;
        }
    }

    public static void main(String[] args) {
        CRC162 c = new CRC162();
        int[] arr = new int[]{0xFC, 0x05, 0x11};
        System.out.println(Integer.toHexString(c.ComputeChecksum(arr)));
    }

I get this 521

Hope someone can help me. I need this for communication with device using ID003 protocol.

EDIT: Using this online calculator at http://www.lammertbies.nl/comm/info/crc-calculation.html for input FC0511 i get 0x2756 right from CRC-CCITT (Kermit).

AdrianES
  • 670
  • 3
  • 13
  • 29
  • Are you sure that [^ operator](http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html) does what you want it to do? – Oleg Estekhin Jul 11 '14 at 09:53
  • I am not sure at all, i found this function on stackoverflow and javaranch forums. – AdrianES Jul 11 '14 at 09:56
  • I think there's a definition problem : the representation of CCITT-CRC is effectively x^16 + x^12 + x^5 + 1, but this gives 0x1021 and not 0x1081 (source [Wikipedia on CRC](http://en.wikipedia.org/wiki/Cyclic_redundancy_check) – Serge Ballesta Jul 11 '14 at 11:43
  • It seems that there are a lot of variants of CRC ... Are you sure of what you want is that *for this array [0xFC] [05] [11] the result needs to be [27] [56]*. Because according to the progs found at http://www.lammertbies.nl/comm/info/crc-calculation.html, it is not the standard CCITT CRC, but the Kermit variant. – Serge Ballesta Jul 11 '14 at 12:54
  • @SergeBallesta, according to http://reveng.sourceforge.net/crc-catalogue/16.htm, the Kermit variant is the "true" CCITT-CRC. – gbmhunter Jun 08 '16 at 00:04

4 Answers4

7

x^16 + x^12 + x^5 + 1 is not 0x1081. It is 0x1021. x^5 is 20, not 80. (Note that the x^16 is dropped.)

Furthermore, the Kermit CRC that you need is reflected, so the polynomial is reversed giving 0x8408.

For this CRC, you initialize with zero and do not complement the result.

So modifying your first example accordingly, this computes what you want:

public static void main(String[] args) {
    byte[] array = new byte[3];
    array[0] = (byte) 0xFC;
    array[1] = (byte) 0x05;
    array[2] = (byte) 0x11;
    //        array[3] = (byte) 0x00;
    //        array[4] = (byte) 0x00;

    System.out.println(Integer.toHexString(crc16(array)));
}

private static final int POLYNOMIAL = 0x8408;
private static final int PRESET_VALUE = 0;

public static int crc16(byte[] data) {
    int current_crc_value = PRESET_VALUE;
    for (int i = 0; i < data.length; i++) {
        current_crc_value ^= data[i] & 0xFF;
        for (int j = 0; j < 8; j++) {
            if ((current_crc_value & 1) != 0) {
                current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
            } else {
                current_crc_value = current_crc_value >>> 1;
            }
        }
    }

    return current_crc_value & 0xFFFF;
}
Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • The preset value of 0 exposes a weakness in the algorithm. Data starting with an arbitrary number of zeros would have a CRC of zero until a 1 bit was detected. Many implementations use a preset of OxFFFF, which avoids this issue.. – Eric Jun 09 '16 at 15:53
  • 1
    Doesn't matter. If the other end is using a CRC like that, then you have to as well. – Mark Adler Jun 10 '16 at 06:28
  • maybe if both sides agree to use exact same code base on similar processor but this is not very practical. In practice (especially in automotive) many modules come together from different vendors and expect CCITT-CRC16 to return a compliant value in these situations and if you're using a non-compliant implementation then it does matter. This is pretty well known in the automotive circles. – Eric Jun 10 '16 at 15:29
  • Sorry, I couldn't parse that. – Mark Adler Jun 10 '16 at 15:32
  • Thank you for much for this code example. I was able to get the same result as on http://www.lammertbies.nl/comm/info/crc-calculation.html for input FC0511 i get 0x2756 right from CRC-CCITT (Kermit). – 456q Oct 16 '20 at 12:20
4

Here is another version of the Kermit CRC. This one is a direct translation from the C codes in http://www.lammertbies.nl/comm/info/crc-calculation.html. The optimisation is that a table of CRC value for any byte is pre-computed at class loading time, and so the remaining of CRC computations is much simpler.

public class Crc {

    private static final int POLYNOMIAL = 0x8408;
    private static final int PRESET = 0;
    static private int[] tab;

    static {
        tab = new int[256];
        for (int i = 0; i < 256; i++) {
            tab[i] = initial((byte) i);
        }
    }

    private static int initial(byte c) {
        int crc = 0;
        for (int j = 0; j < 8; j++) {
            if (((crc ^ c) & 1) == 1) {
                crc = ((crc >> 1) ^ POLYNOMIAL);
            } else {
                crc = (crc >> 1);
            }
            c = (byte) (c >> 1);
        }
        return crc;
    }

    private static int update_crc(int crc, byte c) {
        int cc = (0xff & c);

        int tmp = (crc ^ cc);
        crc = (crc >> 8) ^ tab[tmp & 0xff];

        return crc;
    }

    private static int swab(int n) {
        return (((n & 0xFF00) >> 8) + ((n & 0xFF) << 8));
    }

    public static int crc(String str) {
        return crcb(str.getBytes());
    }

    public static int crcb(byte... i) {
        int crc = PRESET;
        for (byte c : i) {
            crc = update_crc(crc, c);
        }
        return swab(crc);
    }

    public static void main(String[] args) {
        int crc = Crc.crcb((byte) 0xFC, (byte) 5, (byte) 0x11);
        System.out.println(Integer.toHexString(crc));
        crc = Crc.crc("123456789");
        System.out.println(Integer.toHexString(crc));
    }
}

The output is as expected :

2756
8921
Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
2

This is not mine but worked perfect for me, "DatatypeConverter" is something i already have in my proyect. This is a real world example for me and works.

*  Reads in a sequence of bytes and prints out its 16 bit
*  Cylcic Redundancy Check (CRC-CCIIT 0xFFFF).
*
*  1 + x + x^5 + x^12 + x^16 is irreducible polynomial.

import javax.xml.bind.DatatypeConverter;

public class CRC16CCITT {

    public static void main(String[] args) {
        int crc = 0xFFFF; // initial value
        int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12), in your case: 0x1081

        // CRC of this should be 28570
        byte[] testBytes = DatatypeConverter.parseHexBinary("00000000000000000000FA00000002009F1D19B87475445E1122330000000000"); 

        for (byte b : testBytes) {
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit)
                    crc ^= polynomial;
            }
        }

        crc &= 0xffff;
        System.out.println("CRC16-CCITT = " + Integer.toHexString(crc));
        // 6F9A = 28570
    }

}
mjk
  • 2,443
  • 4
  • 33
  • 33
Leandro S
  • 91
  • 1
  • 5
1
    /**
 * converts the given String to CRC16
 * 
 * @param inputStr
 *            - the input string to get the CRC
 * @param polynomial
 *            - the polynomial (divisor)
 * @param crc
 *            - the CRC mask
 * @param isHex
 *            - if true, treat input string as hex, otherwise, treat as
 *            ASCII
 * @return
 */
public static String getCRC16CCITT(String inputStr, int polynomial,
        int crc, boolean isHex) {

    int strLen = inputStr.length();     
    int[] intArray;

    if (isHex) {
        if (strLen % 2 != 0) {
            inputStr = inputStr.substring(0, strLen - 1) + "0"
                    + inputStr.substring(strLen - 1, strLen);
            strLen++;
        }

        intArray = new int[strLen / 2];
        int ctr = 0;
        for (int n = 0; n < strLen; n += 2) {
            intArray[ctr] = Integer.valueOf(inputStr.substring(n, n + 2), 16);
            ctr++;
        }
    } else {
        intArray = new int[inputStr.getBytes().length];
        int ctr=0;
        for(byte b : inputStr.getBytes()){
            intArray[ctr] = b;
            ctr++;
        }
    }

    // main code for computing the 16-bit CRC-CCITT
    for (int b : intArray) {
        for (int i = 0; i < 8; i++) {
            boolean bit = ((b >> (7 - i) & 1) == 1);
            boolean c15 = ((crc >> 15 & 1) == 1);
            crc <<= 1;
            if (c15 ^ bit)
                crc ^= polynomial;
        }
    }

    crc &= 0xFFFF;
    return Integer.toHexString(crc).toUpperCase();
}

Works for both ASCII and HEX computation.

public static void main(String args[]) {

    String testStr = "9142656";

    // XModem ASCII
    System.out.println("CRC-CCITT (XModem) Ascii: "
            + getCRC16CCITT(testStr, 0x1021, 0x0000, false));

    // 0xFFFF ASCII
    System.out.println("CRC-CCITT (0xFFFF) Ascii: "
            + getCRC16CCITT(testStr, 0x1021, 0xFFFF, false));

    // 0x1D0F ASCII
    System.out.println("CRC-CCITT (0x1D0F) Ascii: "
            + getCRC16CCITT(testStr, 0x1021, 0x1D0F, false));

    // XModem Hex
    System.out.println("CRC-CCITT (XModem) Hex: "
            + getCRC16CCITT(testStr, 0x1021, 0x0000, true));

    // 0xFFFF Hex
    System.out.println("CRC-CCITT (0xFFFF) Hex: "
            + getCRC16CCITT(testStr, 0x1021, 0xFFFF, true));

    // 0x1D0F Hex
    System.out.println("CRC-CCITT (0x1D0F) Hex: "
            + getCRC16CCITT(testStr, 0x1021, 0x1D0F, true));

}

Output:

CRC-CCITT (XModem) Ascii: 87F4
CRC-CCITT (0xFFFF) Ascii: 763A
CRC-CCITT (0x1D0F) Ascii: 9F86
CRC-CCITT (XModem) Hex: 57FF
CRC-CCITT (0xFFFF) Hex: D33F
CRC-CCITT (0x1D0F) Hex: 59EF

Solution is based from the sample found in princeton university http://introcs.cs.princeton.edu/java/61data/CRC16CCITT.java

Jan Bobis
  • 11
  • 1