mrhooray / crc-rs

Rust implementation of CRC(16, 32, 64) with support of various standards

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

which is CRC-16-CCITT?

clouds56 opened this issue · comments

How to calculate the well known CRC-16-CCITT with poly = 0x1021?
according to https://www.lammertbies.nl/comm/info/crc-calculation and http://srecord.sourceforge.net/crc16-ccitt.html, we shall get 0xE5CC or 0x29B1 for bytes b"123456789", but I could not manage to get it.
The combination I've tried the combination of poly in [0x8408, 0x1021] and init in [0, !0x1D0F], but with no luck.

  fn digest_crc(init: u16, poly: u16, input: &[u8]) -> u16 {
    use crc::crc16::Hasher16;
    let mut digest = crc::crc16::Digest::new_with_initial(poly, init);
    digest.write(input);
    !digest.sum16()
  }
  let input = b"123456789";
  digest_crc(0, 0x1021, input);
  digest_crc(0, 0x8408, input);
  digest_crc(!0x1D0F, 0x1021, input);
  digest_crc(!0x1D0F, 0x8408, input);

I even tried poly of [0x811, 0x8810] according to this https://en.wikipedia.org/wiki/Cyclic_redundancy_check.

@clouds56 Similar issue, I couldn't get the right combo using crc-rs 1.8. But crc16 AUG_CCITT matches the 0xE5CC output and CCITT-FALSE matched 0x29B1.

// crc16 = "0.4"

const TEST_CASES : &[(&[u8], u16)] = &[
    (b"123456789", 0xE5CC),
    (&[65], 0x9479),
    (&[3, 5, 11], 1730),
    (&['A' as u8; 256], 0xE938),
];

for &(input, expected) in TEST_CASES.iter() {
    let mut state = crc16::State::<crc16::AUG_CCITT>::new();
    state.update(input);
    assert_eq!(state.get(), expected);
}

assert_eq!(crc16::State::<crc16::CCITT_FALSE>::calculate(b"123456789"), 0x29B1);

@osialr , thanks for the link, according to code in crc16
I think there's 2 way to calculate crc (maybe just like little endian and big endian, while it is about bit order other than byte order),

// (BIT_REVERSE_TABLE[(crc & 0xFF) as usize] << 8) | BIT_REVERSE_TABLE[(crc >> 8) as usize]
crc = ((crc >> 8) | ((msg[i] as u16) << 8)) ^ $table[(crc & 0xff) as usize]

and

crc = ((crc << 8) | (msg[i] as u16)) ^ $table[((crc >> 8) & 0xFF) as usize];

I think it impossible to use this crc crate to get 0xE5CC or 0x29B1 now.

Please see #45 and #48 and help us get traction there. It requires quite an investment and it would be ideal to do it when related pieces are stabilized in Rust.

If you're interested in taking a phased approach and improve compatibility on top current implementation, you're welcome to contribute.

@clouds56 this should be possible with the v2 API. I have a working draft @ #55 but it requires Rust beta (for if/loop statements in const_fn).

#55 has been merged. @clouds56 could you check out the latest master?

@mrhooray wdyt about publishing a release candidate 2.0.0-rc.1?

Published 2.0.0-rc.1. There were some timeouts/hiccups - please help check from your end.

So, in the end, in crc-v2.1.0, which is the right one for CRC16-CCITT?

Upon a closer look at the catalogue sources, sounds like this is the one:

https://github.com/akhilles/crc-catalog/blob/95b87f3e7d6b411084ed1190ababc10206bc7b81/src/catalog.rs#L60

/* slightly trimmed from rusty details */
CRC_16_IBM_3740 { poly: 0x1021, init: 0xffff, refin: false, refout: false, xorout: 0x0000, check: 0x29b1, residue: 0x0000 };

http://srecord.sourceforge.net/crc16-ccitt.html

This page presents accurate implementations (long-hand and programmed) of the 16-bit CRC-CCITT specification, which is:

  • Width = 16 bits
  • Truncated polynomial = 0x1021
  • Initial value = 0xFFFF
  • Input data is NOT reflected
  • Output CRC is NOT reflected
  • No XOR is performed on the output CRC

Am I right?

In which case, why won't we have an alias for it?

CCITT is confusing because it's commonly misrepresented. You probably want CRC-16/KERMIT if init=0x0000 and CRC-16/IBM-3740 if init=0xffff.

We shouldn't have an alias for CCITT because it's not clear what the "correct" poly and init values are. It's better to use the less ambiguous terms.