序列化和散列

时间:2016-11-07 18:21:01

标签: c# sql database security hash

我试图考虑数据完整性。我有一个对象,我将序列化到数据库中。一旦它被序列化,我就会把它的哈希值存储起来并将数据存储在数据库中作为一个单独的列。

然后当我从db获取数据时,我可以检查哈希值,然后在哈希值匹配时反序列化数据。

有没有意义,或者我只是在浪费CPU?是否存在其他方法来存储序列化对象,然后验证数据是否未在数据库中被篡改。存储数据的程序可能与读取数据的程序不同。

我的具体示例是创建一个EmailMessage对象(因为System.Net.Mail.MailMessage无法序列化),序列化它并创建哈希。两者都存储在数据库中。后来我可以使用序列化的EmailMessage和哈希。我检索EmailMessage并创建另一个哈希。如果原始哈希与新哈希相同,则填充MailMessage对象并发送它。否则,创建一个TamperedWithException()。

以下代码是我用来制作哈希的代码。我正在使用json.net进行序列化。

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);
    }
}

此特定表尚未加密。攻击者可以进行更改并创建另一个哈希。这是为什么我认为可能有更好的方法来实现这一目标的一部分。

以下是序列化:

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));
    }
}

2 个答案:

答案 0 :(得分:0)

只要保密,盐就可以提供帮助。但这是一个问题,因为它也必须可供合法签名者使用,因此可能对攻击者可用。哈希盐是不是甚至不打扰哈希。我的攻击:读取数据,进行更改,创建新哈希,保存修改后的数据并散列回数据库。

有这种攻击的解决方案,但你必须定义你所保护的和你的保护价值。哈希值通常适用于数据,因为它们不能同时存在。例如,Apple在一个频道上提供他们的更新,并将哈希值通过电子邮件发送到他们的安全电子邮件列表,这是一个单独的频道。

如果没有严格的访问限制和HSM等硬件,通常无法确保所有攻击者的安全。即使这样,也有一些国家的预算庞大,最终Rubber-hose cryptanalysis

答案 1 :(得分:0)

如果我能正确理解你的情况,你的恐惧就是有人可以:

  1. 可以访问数据库
  2. 实现“防篡改”架构的基础知识
  3. 意识到它基于普通的MD5哈希
  4. 伪造修改后的对象
  5. 用伪造的原始对象替换原始对象,用伪造对象的MD5替换原始哈希
  6. 在这种情况下最可怕的是攻击者只需要访问单个系统即数据库,就可以欺骗防篡改机制。

    第一次尝试使其变得不那么容易,可能是在应用程序系统中添加“密钥”:在代码中,您可以向要散列的字符串添加固定前缀(salt),以便攻击者需要访问数据库和这个“秘密”信息来篡改数据。

    然而,正如@zaph明确强调的那样,这一点非常强大,因为它可以使攻击者保密(已经能够访问您的数据库)。

    更糟糕的是,在写入数据的应用程序中,这个“salt”不是必需的,但它也应该与读取数据的应用程序共享,正如你所建议的那样

      

    存储数据的程序可能与读取数据的程序不同。

    如果我们想进一步使方案复杂化,我们可以使用“公钥”系统:MD5将在使用“编写应用程序”私钥存储之前加密,因此“阅读应用程序”可以读取并验证消息对象无法伪造新的哈希值。

    ...但是如果我们深入了解这一点,那么在StackOverflow中你最好从其他人那里获得安全建议而不是随机的人(我):-)