【问题标题】:Hashing multiple byte[]'s together into a single hash with C#?用 C# 将多个字节 [] 一起散列成一个散列?
【发布时间】:2011-04-27 13:43:33
【问题描述】:

我有三个字段:string Titlebyte[] Bodybyte[] Data,我想从中计算单个哈希值以确保它们没有被篡改或损坏。

在 Python 中,我可以连续使用几次md5.update() 来执行此操作。但我在 C# 中找不到类似的功能。要使用 MD5.ComputeHash(),我需要将所有源代码复制到单个字节 [] 中,这是我想避免的步骤。

如何将所有数据散列到一个散列中,而不必将数据复制到临时缓冲区中?

【问题讨论】:

  • 为什么不使用 temp 变量?
  • 顺便说一句,我猜python在后台创建了一个单字节数组......
  • 你知道MD5坏了,对吧?您说您正在使用哈希来检测篡改,但攻击者在不更改哈希的情况下篡改文档在计算上是可行的。您应该使用 SHA256 或其他不存在已知抗碰撞问题的哈希算法。

标签: c# hash


【解决方案1】:

.Net Standard 和 .Net Core 中也有使用IncrementalHash的解决方案

IncrementalHash sha256 = IncrementalHash.CreateHash(HashAlgorithmName.SHA256)

// For each block:
sha256.AppendData(block);

// Get the hash code
byte[] hash = sha256.GetHashAndReset();

正如 Eric Lippert 所指出的,为了更好的抗碰撞性,还要使用SHA256 而不是md5

【讨论】:

    【解决方案2】:

    几乎所有哈希算法的设计方式都是可以连续地输入多个块中的数据。结果与一次对整个数据进行哈希处理相同。

    创建一个实例,例如MD5CryptoServiceProvider 并为每个块调用TransformBlock Method,为最后一个块调用TransformFinalBlock Method

    MD5 md5 = new MD5CryptoServiceProvider();
    
    // For each block:
    md5.TransformBlock(block, 0, block.Length, block, 0);
    
    // For last block:
    md5.TransformFinalBlock(block, 0, block.Length);
    
    // Get the hash code
    byte[] hash = md5.Hash;
    

    【讨论】:

    • 看起来像是多种语言?
    • 你能提供一个代码示例吗?我看到了这种方法,但它的用途让我望而却步。例如,如何避免它覆盖以前的输出?
    • Transform(Final)Block 的工作方式与更新基本相同,即它使用新数据更新 MD5 实例的内部状态。我添加了一个示例(虽然未经测试)。
    【解决方案3】:

    使用普通的 .NET,我认为没有办法更新和 MD5 哈希。但是,Windows 在 crypt.dll 中定义了一个MD5Update 函数。我想你可以使用 Interop 来利用这一点。

    否则,在 .NET c# 中有一个等效的 PHP 实现,位于 SO:Problem porting PHP crypt() function to C#

    PS:我肯定会选择组合临时变量解决方案:-)

    【讨论】:

      【解决方案4】:

      对三个不同的值调用 ComputeHash 函数将创建三个不同的字节数组结果。然后必须以某种方式组合这些结果以产生单个哈希。没有办法绕过这个事实。它将在堆中创建三个新对象。它将计算一个哈希(一个相当慢的操作)三次而不是一次。

      我认为做你想做的最高效的方法就是继续将你的源值复制到一个单字节数组中并获取它的哈希值。

      您没有说明为什么要避免这种方法。我认为它在简单性和可维护性方面获胜。这是一种自我记录的、显而易见的方法。这是最高效的方法。我真的没有看到不利的一面。

      【讨论】:

      • 缺点是如果你有一个 1GB 的文件,那么你会将该 1GB 字节数组加载到内存中,而不是缓冲它以提高性能..
      【解决方案5】:

      您可以在哈希值上创建一个哈希。

      MD5 md5 =  System.Security.Cryptography.MD5.Create();
      byte[] totalHash= md5.ComputeHash(md5.ComputeHash(part1).Concat(md5t.computeHash(part2)));
      

      不创建字节数组的副本,而是对哈希的串联进行哈希处理。

      【讨论】:

      • +1:不知道为什么你得到-1'd,这是一个合理的解决方案IMO(虽然@dtb's更好:))。
      • 只是问自己为什么我得到-1。但我同意 dtb 更好:-)
      • 这会降低加密强度(在已经被削弱的 MD5 上),可能会显着地避免这种情况。 (不是我 -1'd 但我认为这就是原因)。我不相信它像 Guffa 的建议那样可怕,但以这种方式推出自己的加密货币并不是一个好主意(即使构建模块很好)
      • 究竟是如何降低加密强度的? (我不否认确实如此,只是想知道)。如果我们假设 MD5 是安全的(没有可重构的冲突),那么我在自己生成的哈希上运行算法的频率并不重要,它不会变得更安全,但也不会更少?
      • 因为某人不再需要在 XYZ 中查找碰撞,他们需要在 X、Y、Z 或 X'Y'Z 中查找碰撞(其中 V' 是哈希 (V))。
      【解决方案6】:

      您必须将它们全部组合在一个变量中,然后计算 MD5 哈希。我没有看到任何快捷方式。

      你看,这里提出的大多数解决方案只是尝试在同一行上运行多个命令(“一个衬里”)或实现一些东西来“在后台”组合你的字段,然后 Hash...

      【讨论】:

        猜你喜欢
        • 2023-03-15
        • 2015-12-14
        • 1970-01-01
        • 2016-09-04
        • 1970-01-01
        • 2011-02-15
        • 1970-01-01
        • 2018-11-07
        • 2016-12-27
        相关资源
        最近更新 更多