Daniel Gale Daniel Gale - 27 days ago 14
SQL Question

Serialization and hashing

I was trying to think about data integrity. I have an object that I'm going to serialize into the db. Once it's serialized I was going to take a hash of it and store it with the data as a separate column in the DB.

Then when I get the data from the db I could check the hash and then deserialize the data if the hashes match.

Is there a point to that or am I just wasting CPU? Are there other methods of storing a serialized object and then verifying that the data was not tampered with in the database. The program storing the data may not be the same as the program reading the data.

My specific example is creating an EmailMessage object (since System.Net.Mail.MailMessage cannot be serialized), serializing it and creating the hash. Both are stored in the database. Later I can take the serialized EmailMessage and the hash. I retrieve the EmailMessage and create another hash. If the original hash is the same as the new hash then populate a MailMessage object and send it. Otherwise, create a TamperedWithException().

The code below is what I am using to make the hash. I am using json.net to do the serializing.

public static class MD5HashHelper
{
public static string CreateHash(string str)
{
string hash;
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
hash = BitConverter.ToString(
md5.ComputeHash(Encoding.UTF8.GetBytes(str))
).Replace("-", String.Empty);
}
return hash;
}
public static bool CompareWithHash(this string str, string hash)
{
string strHash = CreateHash(str);

return strHash.Equals(hash,StringComparison.Ordinal);
}
}


This particular table is not encrypted yet. An attacker could make a change and create another hash. This is part of why I think there are probably better ways to do this.

Below is the serialization:

public static class JSONHelper
{
public static string ToJSON(this object obj)
{
string json = JsonConvert.SerializeObject(obj);
return json;
}

public static T JSONToObject<T>(this string json)
{
Object obj = JsonConvert.DeserializeObject<T>(json);
return (T)Convert.ChangeType(obj, typeof(T));
}
}

Answer

A salt could help as long as it is kept secret. But that is a problem because it also has to be available to the legitimate signer and thus will probably be available to an attacker. Is the hash salt is not don't even bother with the hash. My attack: read the data, make my changes, create a new hash, save the modified data and hash back to the DB.

There are solutions to such an attack but you have to define the value of what you are protecting and from whom. Hashes generally work for data when they are not both available together. An example, Apple provides their updates on one channel and emails the hashes to their security email list, a seperate channel.

Trying to be secure from all attackers is generally not possible without severe access restrictions and hardware such as HSMs. Even then there are nations states with huge budgets and in the end Rubber-hose cryptanalysis.

Comments