C# Cautionary Tale — The dangers of SHA256 reuse

James Woodall
2 min readDec 14, 2017

Update: Based on feedback by Thibaut Le Guilly, it seems my answer can be simplified using the ThreadStatic attribute. See here.

Original: I’ve been working on a spare-time project that hashes some data using SHA256; nothing exciting or particularly groundbreaking. However, during the course of this project I noticed that every now and then, the results from my hashing algorithm were not what I expected.

Different hash results for the same input

The software I am writing is really simple. It stores a record of data in Azure Table Storage. For every row inside Table Storage you need a Partition Key and a Row key. In my implementation I’m hashing an input value and using the resulting hash as my Partition Key. So far so good.

Recently I noticed that sometimes the software would warn that some records couldn’t be found but after a refresh, they re-appeared. Odd.

A bit of logging later (and using some carefully crafted telemetry statements) I could see that in some circumstances the hashing algorithm I was using produced slightly different outputs!

The code I was using for my hasher can be found here.

As you can see, I use the standard Dot Net Core SHA256 algorithm but when coding I decided that by storing my SHA256 object for reuse I would somehow save some CPU cycles by not recreating it over and over again.

It turns out, I was wrong.

I experimented with a simple console app and confirmed my suspicions. By reusing the engine I was corrupting the state; so when used concurrently, the results would be different.

In my sample app I tried 2 things.

  1. Using parallel tasks, try 10 hashes (using a shared engine)
  2. Using parallel tasks, try 10 hashes (using a new engine every time)

The results were as follows. Of the 10 attempts using the shared engine, 7 attempts produced different hash values. When using the new engine instance, all of the hashes for successful.

As usual, a few lines of code and a major problem is fixed. For reference here is my new hashing code.

So the moral of this tale, use a new engine every time or it’ll bite you.

--

--

James Woodall
James Woodall

Written by James Woodall

James has been working in software development for several years and loves programming for web and wearable devices.

Responses (4)