A hash function maps data of an arbitrarily large size to a fixed size. This is essentially a unique fingerprint of the data. A cryptographic Hash Code uses a cryptographic function to generate a hash code. For example, Git repositories use an SHA-256 Hash as a fingerprint to ensure a remote repository is in sync with a master repository.
A cryptographic hash function also has the property that it is not possible to deduce a message from its hash. This is important for security because we might transmit the hash code of data, but don’t want to compromise the actual data.
A Message Authentication Code, or MAC is like a keyed hash. The MAC depends on both parties using the same key. One has to know the key to authenticate the message. A cryptographic hash like SHA-256 has no key. A unique set of data will always produce the same SHA-256 hash code for everyone.
The purpose of a Cyclic Redundancy Check (CRC) is different. CRCs are design to detect errors, not to provide a fingerprint. CRCs are not guaranteed to be unique or protect the security of the content. CRCs are just for error detection.
The most commonly used Cryptographic Hash is the Secure Hash Algorithm (SHA). There are variants called SHA-1 and SHA2. SHA-1 always uses a 160-bit digest. The digest is the output value from the hash algorithm. SHA-2 supports different digest sizes ranging from 224 to 512 bits. Rather confusingly, SHA-2 with a 256-bit digests is commonly abbreviated SHA-256 (perhaps it should have been called SHA2-256.)
So which SHA function to use? Before the NSA introduced SHA, Ronald Rivest designed the MD5 Message Digest Algorithm. Version 5 is still supported by TLS1.2.
There is some controversy regarding the security of MD5 and SHA-1. For both MD5 and SHA-1 there have been collisions found that limit the security to less than half the digest size. OK. What does this mean?
A collision just means that two sets of data can produce the same digest, or fingerprint. So hypothetically, the odds of having two data sets with the same digest for SHA-1 are slightly less than the ideal value of 1/(2^80). This only means that SHA-1 is not as secure as we thought it was.
There are no known successful preimage attacks on MD5 or SHA-1. A preimage attack tries to find a message with a specific hash. So in that respect, MD5 and SHA-1 are relatively secure.
MD5 is deprecated in TLS-1.2 and SHA-1 is deprecated in TLS-1.3. If you have a choice, I would recommend using SHA-256 (SHA-2 with a 256-bit digest.)
Because TLS connections depend on the capabilities of both parties, it is good to have support for legacy security modes to ensure that you can connect to host that does not support the latest security standards.
The Crypto module on the EFR32 devices and the Pearl and Jade Geckos supports SHA-1 and SHA-2 with a 224-bit or 256-bit digest. If you have a choice, I would recommend SHA-256, because it is just as fast as SHA-224. These devices also support the legacy MD5 Hash using the mbed-TLS software library.
So when should you use SHA? A good use for an embedded device is to use a secure hash for firmware validation. Suppose you have a secure bootloader and you want to make sure that your firmware image is valid. The bootloader might have the capability to calculate a SHA digest for the entire firmware image upon request. The host can compare the SHA digest to the expected value. Because it is a secure hash, we can freely give the digest to anyone that asks for it.
The previous blog discussed the CBC-MAC block cipher mode for authenticated encryption. There are other block cipher methods besides CBC-MAC. The Galois Counter mode is one that is increasing in popularity. This is the subject of the next blog post.