DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Introducing RAI Audit Kit: Evidence-Grade Responsible AI Audits in Python
  • I Was Tired of Flying Blind With AI Agents, So I Built AgentDog
  • Prompt Injection Is Real, So I Built a Python Firewall for LLM Pipelines
  • Building Threat Intelligence Pipelines Using Python, APIs, and Elasticsearch

Trending

  • 7 Technology Waves I’ve Seen in 30 Years of Software — Will AI Be the Next Real Transformation?
  • The Hidden Cost of AI Tokens: Engineering Patterns for 10x Resource Efficiency
  • Engineering Closed-Loop Graph-RAG Systems, Part 4: Evaluating a Graph-RAG System
  • 5 Failure Patterns That Break AI Chatbots in Production
  1. DZone
  2. Coding
  3. Languages
  4. Forging an SHA-1 MAC Using a Length-Extension Attack in Python

Forging an SHA-1 MAC Using a Length-Extension Attack in Python

Cryptographers have long been aware of the vulnerabilities in SHA-1, yet it's still in use. Read on to learn how easy it is to hack and why you shouldn't use it.

By 
Mantej Singh Rajpal user avatar
Mantej Singh Rajpal
·
Aug. 14, 17 · Analysis
Likes (2)
Comment
Save
Tweet
Share
5.8K Views

Join the DZone community and get the full member experience.

Join For Free

Image title

SHA-1 (Secure Hash Algorithm 1) is broken. It has been since 2005. And yet, that hasn’t stopped its continued use. For example, until early 2017 most internet browsers still supported SHA-1. As though to confirm that SHA-1 was really, truly dead, researchers from CWI Amsterdam and Google announced at the end of February 2017 they had performed a successful collision attack against SHA-1.

In this article, we’ll learn how to break an SHA1-keyed message authentication code (MAC), part of the authentication message that confirms the message came from the stated sender. This is useful for impersonating someone else. But first, some background.

What Is SHA-1?

SHA-1 is a cryptographic hashing algorithm designed by the United States National Security Agency back in the early 1990s. It is used to create a message digest, which in cryptography is a one-way mathematical algorithm that takes data of any size and maps it to a bit string of a fixed size (a hash function). So, feed SHA-1 an arbitrary amount of data and it will produce a 20-character message digest. Whether you input “Synopsys,” “I love cryptography!”, or Act I from Shakespeare’s Hamlet, the result will always be exactly 20 bytes.

People have used (and still use) SHA-1 to produce MACs. We’re going to break an SHA-1 MAC that has been prefixed with a key. Namely:

message digest = SHA1(key || message)

Given the message digest and message, it shouldn’t be possible to modify the message and produce a new corresponding message digest. That is, unless, there is complete knowledge of the key. This isn’t actually the case.

In this example, we’ll take the message “user=mantej;” and generate an SHA-1 message digest under an unknown key. We’ll continue to reverse engineer the hash, and use the result to create a valid message digest for the message “user=mantej; … ;admin=true” without any knowledge of the key.

But before we do that, let’s find an SHA-1 implementation and make a couple modifications.

Modifying SHA-1

For our example, we’ll use a pure-Python implementation of SHA-1 from StackExchange, and compare its output to an online SHA-1 calculator to verify correctness.

Forging a SHA-1 MAC using a length-extension attack in Python

Figure 1. SHA-1 magic numbers

Now, a 160-bit SHA-1 hash is actually just made up of five internal 32-bit registers. These registers usually start at magic numbers (Figure 1).

We’re going to modify the function definition so that we can pass in an SHA-1 message digest and ‘re-create’ its state. We accomplish this by breaking our message digest into five 32-bit values (Figure 2), and passing in those values as function parameters in order to override the default magic numbers (Figure 3). By setting our own register values, we’re able to ‘pick up where we left off’ and append an arbitrary amount of data to the original message.

Forging a SHA-1 MAC using a length-extension attack in Python

Figure 2. Breaking SHA-1 digest into five 32-bit registers

Forging a SHA-1 MAC using a length-extension attack in Python

Figure 3. Overriding default magic numbers

Additionally, we need to append the bit-length of our forged message (Figure 4). Specifically, we need to compute length(key || original message with padding || new message). We can’t immediately compute this value since, if you recall, the key is completely unknown to us. Not to worry. So, let’s just brute-force–that is, bombard it with possibilities–for key length (Figure 5).
Forging a SHA-1 MAC using a length-extension attack in Python

Figure 4. Inject bit-length of our forged message for length-extension attacks

Forging a SHA-1 MAC using a length-extension attack in Python

Figure 5. Brute-forcing for key length

Performing the Attack

Let’s use a validate function that takes the forged message and forged message digest as input, computes SHA-1(key || forged message), and compares it to the forged digest. If they are identical (i.e., mission success!), validate() returns true. It looks something like this:
Forging a SHA-1 MAC using a length-extension attack in Python

Figure 6. Validates our forged message digest under the secret key

For the sake of completeness, here’s the forge_message function:
Forging a SHA-1 MAC using a length-extension attack in Python

Figure 7. Forges a message utilizing technique discussed above

Lastly, we’ll write a program that takes the message “user=mantej;” and generates an SHA-1 hash under a randomly generated secret key between 1 and 32 bytes. Utilizing everything described above, I’m going to brute-force for key length, append “;admin=true” to the original message, and generate a valid MAC under the secret key–without any knowledge of the key itself.

And. Here. We. Go.
Forging a SHA-1 MAC using a length-extension attack in Python

Figure 8. Performing the length extension attack

Moral of the story? Only use SHA1(key || message) as a MAC if security isn’t important.

32-bit Python (language)

Published at DZone with permission of Mantej Singh Rajpal. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Introducing RAI Audit Kit: Evidence-Grade Responsible AI Audits in Python
  • I Was Tired of Flying Blind With AI Agents, So I Built AgentDog
  • Prompt Injection Is Real, So I Built a Python Firewall for LLM Pipelines
  • Building Threat Intelligence Pipelines Using Python, APIs, and Elasticsearch

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook