Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
TLS Cryptography In-Depth

You're reading from   TLS Cryptography In-Depth Explore the intricacies of modern cryptography and the inner workings of TLS

Arrow left icon
Product type Paperback
Published in Jan 2024
Publisher Packt
ISBN-13 9781804611951
Length 712 pages
Edition 1st Edition
Arrow right icon
Authors (2):
Arrow left icon
Dr. Roland Schmitz Dr. Roland Schmitz
Author Profile Icon Dr. Roland Schmitz
Dr. Roland Schmitz
Dr. Paul Duplys Dr. Paul Duplys
Author Profile Icon Dr. Paul Duplys
Dr. Paul Duplys
Arrow right icon
View More author details
Toc

Table of Contents (30) Chapters Close

Preface 1. Part I Getting Started
2. Chapter 1: The Role of Cryptography in the Connected World FREE CHAPTER 3. Chapter 2: Secure Channel and the CIA Triad 4. Chapter 3: A Secret to Share 5. Chapter 4: Encryption and Decryption 6. Chapter 5: Entity Authentication 7. Chapter 6: Transport Layer Security at a Glance 8. Part II Shaking Hands
9. Chapter 7: Public-Key Cryptography 10. Chapter 8: Elliptic Curves 11. Chapter 9: Digital Signatures 12. Chapter 10: Digital Certificates and Certification Authorities 13. Chapter 11: Hash Functions and Message Authentication Codes 14. Chapter 12: Secrets and Keys in TLS 1.3 15. Chapter 13: TLS Handshake Protocol Revisited 16. Part III Off the Record
17. Chapter 14: Block Ciphers and Their Modes of Operation 18. Chapter 15: Authenticated Encryption 19. Chapter 16: The Galois Counter Mode 20. Chapter 17: TLS Record Protocol Revisited 21. Chapter 18: TLS Cipher Suites 22. Part IV Bleeding Hearts and Biting Poodles
23. Chapter 19: Attacks on Cryptography 24. Chapter 20: Attacks on the TLS Handshake Protocol 25. Chapter 21: Attacks on the TLS Record Protocol 26. Chapter 22: Attacks on TLS Implementations 27. Bibliography
28. Index
29. Other Books You Might Enjoy

11.6 MAC versus CRC

Can we construct a MAC without a cryptographic hash function and without a secret key? Let’s take a look at the Cyclic Redundancy Check (CRC), which is popular error-detecting code used in communication systems to detect accidental errors in messages sent over a noisy or unreliable communication channel.

The working principle of error-detecting code is for the sender to encode their plaintext message in a redundant way. The redundancy, in turn, allows the receiver to detect a certain number of errors – that is, accidental bit flips – in the message they receive. The theory of channel coding, pioneered in the 1940s by the American mathematician Richard Hamming, aims to find code that has minimal overhead (that is, the least redundancy) but, at the same time, has a large number of valid code words and can correct or detect many errors.

CRC is so-called cyclic code, that is, a block code where a circular shift of every code word yields another valid code word. The use of cyclic code for error detection in communication systems was first proposed by the American mathematician and computer scientist Wesley Peterson in 1961.

Cyclic code encodes the plaintext message by attaching to it a fixed-length check value based on the remainder of a polynomial division of the message’s content. The receiving party repeats that calculation and checks whether the received check value is equal to the computed check value.

The algebraic properties of cyclic code make it suitable for efficient error detection and correction. Cyclic code is simple to implement and well suited to detect so-called burst errors. Burst errors are contiguous sequences of erroneous bits in communication messages and are common in many real-world communication channels.

CRC code is defined using a generator polynomial g(x) with binary coefficients 0 and 1. The plaintext message, encoded as another polynomial m(x), is divided by the generator polynomial. The CRC is then computed by discarding the resulting quotient polynomial and taking the remainder polynomial r(x) as CRC, which is subsequently appended to the plaintext as a checksum. The whole arithmetic is done within the finite field 𝔽2, therefore the coefficients of the remainder polynomial are also 0 and 1.

As an example, we can compute an 8-bit CRC using the generator polynomial g(x) = x2 + x + 1. To encode a message, we encode it as a polynomial, divide it by the generator polynomial x2 + x + 1, and take the remainder of this division as the CRC check value to be appended to the plaintext message.

So, to encode a two-byte message 0x0102, Bob would interpret it as the polynomial m(x) = x8 + x, divide it by x2 + x + 1 using polynomial division, and get a remainder polynomial r(x) = 1. In hexadecimal notation, the remainder has the value 0x01. He would then append the remainder value as the CRC check value and transmit the message 0x010201 to Alice.

Upon receiving the message, Alice would perform the same computation and check whether the received CRC value 0x01 is equal to the computed CRC value. Let’s assume there was an error during transmission – an accidental bit flip – so that Alice received the message 0x010101. In that case, the CRC value computed by Alice would be 0x02 and Alice would detect the transmission error.

At first glance, this looks very similar to a MAC and, especially in systems that already support CRCs, it might be tempting to use CRC as a replacement for a MAC. Don’t! Recall that MACs are built on top of cryptographic hash functions, and cryptographic hash functions are collision-resistant. CRCs, on the other hand, are not collision resistant.

As an example, Listing 11.1 shows the Python code for computing CRC-8. This CRC uses generator polynomial x2 + x + 1 and outputs an 8-bit CRC value.

Listing 11.1: Python code for computing CRC-8 using generator polynomial x2+x+1

def crc8(data, n, poly, crc=0):
   g = 1 << n | poly  # Generator polynomial
   for d in data:
       crc ^= d << (n - 8)
       for _ in range(8):
           crc <<= 1
           if crc & (1 << n):
               crc ^= g

   return crc

Now, if you compute CRC-8 checksum values for different 2-byte messages using the code shown in Listing 11.2, you can quickly verify yourself that messages 0x020B, 0x030C, 0x0419, and many others have the same CRC value of 0x1B.

Listing 11.2: Python code to compute CRC-8 for different 2-byte messages

for i in range(0,256):
   for j in range(0, 256):
       if crc8([i,j], 8, 0x07) == 0x1b:
           print(f"Message {hex(i)}, {hex(j)} has CRC 0x1b")

Consequently, if Alice and Bob were to use CRCs to protect their message integrity against malicious attacker Mallory rather than accidental transmission errors, it would be very easy for Mallory to find messages that have an identical CRC check value. That, in turn, would allow Mallory to exchange a message that Bob sent to Alice without her noticing it (and vice versa). And that is exactly the reason why a MAC needs to be collision-resistant. Moreover, and maybe even more importantly, even if Mallory cannot be bothered to find collisions for the CRC value already in place, he can simply compute the matching CRC value for a message of his choice and replace both the message and the CRC. This is possible because there is no secret information going into the CRC. To summarize, a CRC will only protect you against accidental, random transmission errors, but not against an intelligent attacker.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image