11

I am currently designing a communication protocol for an embedded system. I've decided that authentication (but not encryption) is important, so I decided to add 4 bytes of truncated HMAC signature to every packet. At the same time, I also want to be able to do data verification to ensure that the data arrives correctly and hasn't been corrupted in transit. So I was thinking of appending a CRC32 to every packet. However, wouldn't the HMAC signature also be good enough for verifying the integrity of the packet?

Is there any point in adding both an HMAC signature and a CRC32? Or is an HMAC enough?

4
  • If you haven't read through them, it may be instructional to skim through some existing protocol specs. ETSI TS 138.212 includes a crc in § 5.1, but they're using it for CRC-aided polar and ldpc codes. Higher (MAC/IP) layers have more sophisticated integrity checks, which sounds like more what you're doing. There's no question though, if you're doing any CA-fec you should be using CRC because you'll be computing it multiple times per packet.
    – Steve Cox
    Feb 22, 2021 at 18:37
  • Why is encryption not important? We might not need to see the answer, but you would need to find it nevertheless. Feb 23, 2021 at 19:33
  • @OlegLobachev I don't really care if people see the data, but I do care that the device accepts commands from the right person
    – 9a3eedi
    Feb 24, 2021 at 5:52
  • 1
    @OlegLobachev a good example of this sort of requirement would be a civilian remote control drone protocol. If there is telemetry data or video payload you might want some of that encrypted, but the minutiae of how much throttle to apply to each rotor probably just needs to be authenticated, (and there might be FAA regulations that require you to send those commands in the clear)
    – Steve Cox
    Feb 24, 2021 at 11:32

6 Answers 6

22

The CRC32 does not give you any guarantees that the HMAC does not also give you. Put another way, the HMAC gives you all the guarantees the CRC32 gives you and more: the CRC32 protects against unintentional alteration due to common transmission problems such as noise and interference, the HMAC also protects against intentional alteration.

The CRC32, however, may be less compute-intensive to verify. So, if your communication channel is very noisy and your receiver device is CPU-constrained, it may make sense to use the additional CRC32 to quickly throw away corrupted packets without having to verify the more expensive HMAC and only do the expensive HMAC verification on packets you know were at least not corrupted during transmission.

This balance may tip, however, if your chosen CPU has built-in acceleration for the cryptographic primitives used in the HMAC.

In the particular case of a noisy channel, it would probably make even more sense to use an Error Correction Code or some other mechanism for Forward Error Correction like a Hamming or Reed-Solomon code instead of only a mere Error Detection Code like CRC32.

15
  • 3
    Though, if I recall correctly, CRCs give known guarantees about the sort of errors they always detect, e.g. odd numbers of errors, or errors up to some maximum length. For truncated cryptographic hashes, you probably won't have that, just the statistics.
    – ilkkachu
    Feb 22, 2021 at 18:47
  • 4
    @ilkkachu crc's can detect any errors that aren't congruent to 0 mod P (where P is the generator polynomial). They can always detect an odd number of errors because no odd polynomials = 0 mod P. They don't guarantee any detectability of any number of even errors because x^(n) = x^(n + 2^N - 1) mod P (N is the order of P), but their error detection performance within their period is considered to be excellent.
    – Steve Cox
    Feb 22, 2021 at 19:01
  • 9
    This is completely wrong. Not only does a 4 byte HMAC not provide security against intentional modification (only a full HMAC can do that), but it is more vulnerable to accidental collisions as an n-bit CRC is guaranteed to detect any burst errors up to length n + 1, with the sole exception of the case where the CRC polynomial divides the burst error polynomial.
    – forest
    Feb 23, 2021 at 1:20
  • 5
    Also, OP says this is for authentication, which is a security principle. Neither a CRC nor a truncated HMAC is sufficient for authentication.
    – forest
    Feb 23, 2021 at 1:47
  • 3
    @9a3eedi: No, it doesn't (at least not to any significant degree), not until the packet gets shorter than the MAC token. Feb 23, 2021 at 11:58
14

If you need secure authentication, use only the untruncated HMAC.

Assuming you don't care about security (which would be the case if you used a 4-byte HMAC), a CRC is actually better for detecting small accidental errors. An n-bit CRC is guaranteed to detect any burst error up to n + 1 bits in length, with the sole exception of a burst error whose polynomial divides the CRC polynomial, in which case the probability of the error going undetected is 1 (i.e. always goes through undetected). For detecting small errors, a CRC is superior. For larger errors which do not divide the CRC polynomial, they are equal, providing a 2-n probability of failure.

Note that this assumes the size of the digest is the same, i.e. CRC64 vs an 8-byte (64-bit) truncated HMAC or CRC32 vs a 4-byte (32-bit) truncated HMAC. Be aware that neither 64 bits nor 32 bits is sufficient to protect against an intentional error that bypasses detection.

10

The purpose of a Message Authentication Code (MAC), of which the HMAC is an example, is to prove both the authenticity and the integrity of the message.

The integrity protection is often framed as a protection against modification of the message by attackers, but it works equally for detecting accidental modification by bit-flips in the transport of the message. Thus, you don't need an additional CRC check to detect those bit-flips.

3

CRC in addition to HMAC is pointless if you only verify the checksum at the final recipient, i.e. as a purely end-to-end protocol. However, it can be useful if the checksum is verified at intermediate steps that don't know the secret key. In particular, if the message is relayed through several hops, intermediate hops can delete messages with an invalid CRC.

Once the message has arrived at the final recipient, a CRC allows you to cheaply discard corrupted messages. This aspect is rarely useful in practice. If you're worried about accidental corruption, error correction codes will give you better results than a CRC: resending is a lot more expensive than fixing an error. If you're worried about a denial of service by a flood of invalid message, using a CRC doesn't really gain much: you might save a tiny amount of CPU power because CRC is faster to calculate than HMAC, but an attacker who can flood your CPU can typically flood your radio receiver anyway. One case where this is not true and a CRC can help is if your receiver consists of a fast application CPU combined with a slow secure element, and only the secure element has the HMAC key.

Note that a 32-bit MAC is very short and is only good if you don't mind that it's possible to attack a fleet of devices with a small, but nonzero rate of success. If you deploy a million devices and they can each process one message per second, a somewhat resourceful adversary can inject several fake messages every day. How bad this is depends on how much you can tolerate the occasional fake.

2
  • 1
    Re: "If you're worried about a denial of service by a flood of invalid message, using a CRC doesn't really gain much": I don't think a CRC gains anything in that case, because it's easy for the attacker to generate invalid messages that pass the CRC.
    – ruakh
    Feb 23, 2021 at 6:01
  • What if it's one or two devices, with a short lifetime of a month or two, and very high latency and low bandwidth?
    – 9a3eedi
    Feb 23, 2021 at 12:20
0

If you think about adding 32 bit CRC and 32 bit truncated HMAC: 32 bit truncated HMAC may be just about forgeable. Calculating HMAC not for the message, but message + CRC, might make it bit harder. What makes it a lot harder to forge would be to throw away the CRC and use a 64 bit truncated HMAC.

-1

Use the right tool for the job.

CRCs provide superior error detection to a same size HMAC function because CRCs detect all burst errors less than the CRC size and all odd numbered of bits errors.

Its also faster to compute CRCs.

3
  • 3
    If I didn't need the authentication, I would've kept the CRC only as it's much faster (important for embedded). However, I do need authentication, so should I keep both?
    – 9a3eedi
    Feb 22, 2021 at 9:43
  • 1
    @9a3eedi If you do need authentication, then you should use only the full-length HMAC (despite what the currently accepted but incorrect as-is answer says).
    – forest
    Feb 23, 2021 at 2:41
  • HMAC detects all burst errors with probability that is essentially 1. If you use a 256-bit HMAC digest, the chances that HMAC fails to detect a burst error is lower than the chances of a cosmic ray causing a bitflip error in memory that causes your computation to be erroneous in some other way. If you use a 32-bit HMAC, the chances of failing to detect a burst error are 1/2^32, which is so small that it's not really worth optimizing for.
    – D.W.
    Feb 23, 2021 at 4:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.