当使用CryptoStream重用实例时,HMACSHA512会产生不同的哈希值

时间:2016-09-22 16:12:07

标签: c# .net cryptography hmac

我有一个用例,我想创建第二个HMAC,其中第一个HMAC和一些数据被合并。

我想了解为什么测试用例3正在创建错误的 hmac,这令人困惑,因为1和2正在创建相同的哈希值。

代码:

void Main()
{
    { // 0. Create a HMAC 
        byte[] keyHmac = new byte[] { 255 };
        var hmac = new HMACSHA512(keyHmac); // 1st HMACSHA512 ctor
        var result = hmac.ComputeHash(new byte[] { 1, 2, 3 });
        Console.Out.WriteLine($"0. - {Convert.ToBase64String(result)}");
    }

    Console.Out.WriteLine("\r\nThe following MACs should be all equal!\r\n");

    { // 1. Create a HMAC than add a byte to the result and create a second HMAC
        byte[] keyHmac = new byte[] { 255 };
        var hmac = new HMACSHA512(keyHmac); // 1st HMACSHA512 ctor
        var result = hmac.ComputeHash(new byte[] { 1, 2, 3 });
        result = hmac.ComputeHash(result.Concat(new byte[] { 7 }).ToArray());
        Console.Out.WriteLine($"1. - {Convert.ToBase64String(result)}");
    }

    { // 2. Create a HMAC than add a byte to the result and create a second HMAC with a new instance
        byte[] keyHmac = new byte[] { 255 };
        var hmac = new HMACSHA512(keyHmac);  // 1st HMACSHA512 ctor
        var result = hmac.ComputeHash(new byte[] { 1, 2, 3 });
        hmac = new HMACSHA512(keyHmac);  // 2nd HMACSHA512 ctor
        result = hmac.ComputeHash(result.Concat(new byte[] { 7 }).ToArray());
        Console.Out.WriteLine($"2. - {Convert.ToBase64String(result)}");
    }

    { // 3. Create a HMAC from a stream than add a byte to the result and create a second HMAC
        byte[] keyHmac = new byte[] { 255 };
        var hmac = new HMACSHA512(keyHmac);
        using (var resultStream = new MemoryStream())
        {
            using (var hmacStream = new CryptoStream(resultStream, hmac, CryptoStreamMode.Write))
            {
                new MemoryStream(new byte[] { 1, 2, 3 }).CopyTo(hmacStream);
            }
        }

        var result = hmac.Hash;
        result = hmac.ComputeHash(result.Concat(new byte[] { 7 }).ToArray());

        Console.Out.WriteLine($"3. - {Convert.ToBase64String(result)}");
    }


    { // 4. Create a HMAC from a stream than add a byte to the result and create a second HMAC with a new instance
        byte[] keyHmac = new byte[] { 255 };
        var hmac = new HMACSHA512(keyHmac);
        using (var resultStream = new MemoryStream())
        {
            using (var hmacStream = new CryptoStream(resultStream, hmac, CryptoStreamMode.Write))
            {
                new MemoryStream(new byte[] { 1, 2, 3 }).CopyTo(hmacStream);
            }
        }

        var result = hmac.Hash;
        hmac = new HMACSHA512(keyHmac);
        result = hmac.ComputeHash(result.Concat(new byte[] { 7 }).ToArray());

        Console.Out.WriteLine($"4. - {Convert.ToBase64String(result)}");
    }
}

输出:

0. - J0x6KRHzGh1nTLL+a+pL8H9PJyl1b9/rL7D0j3S1DBpMduct37uMi0mBFEOdkfrLs2Ipn39yoV6GaRoEK+hU7A==

The following MACs should be all equal!

1. - mVd7YQ7AbmRfH57AprAuU1vlSuOucvg+NbUFl7eNurPuvGS/Xrko2Kz3d9vUGXr0P287dOgEKQJDNfMkN2xi5Q==
2. - mVd7YQ7AbmRfH57AprAuU1vlSuOucvg+NbUFl7eNurPuvGS/Xrko2Kz3d9vUGXr0P287dOgEKQJDNfMkN2xi5Q==
3. - DVncxk/dEYhmmpK5qEnVg0Pc0/MUe8APbAiyZrh+ba35oGv2TGCkFco3gFVZ2gl+h3DpcqP7VbmuthBmCvSKlg==
4. - mVd7YQ7AbmRfH57AprAuU1vlSuOucvg+NbUFl7eNurPuvGS/Xrko2Kz3d9vUGXr0P287dOgEKQJDNfMkN2xi5Q==

2 个答案:

答案 0 :(得分:1)

那是因为在除了3之外的所有方法中,你在第一个哈希计算和第二个哈希计算之间重新初始化你的hmac。要在3中执行相同的操作,请尝试以下操作:

{
    // 3. Create a HMAC from a stream than add a byte to the result and create a second HMAC
    byte[] keyHmac = new byte[] {255};
    var hmac = new HMACSHA512(keyHmac);
    using (var resultStream = new MemoryStream()) {
       using (var hmacStream = new CryptoStream(resultStream, hmac, CryptoStreamMode.Write)) {
           new MemoryStream(new byte[] {1, 2, 3}).CopyTo(hmacStream);
        }
    }

    var result = hmac.Hash;
    hmac = new HMACSHA512(keyHmac);
    result = hmac.ComputeHash(result.Concat(new byte[] {7}).ToArray());

    Console.Out.WriteLine($"{Convert.ToBase64String(result)}");
}

答案 1 :(得分:1)

在第3种情况下,您通过拨打TransformBlock来混淆TransformFinalBlock / CryptoStream(由ComputeHash使用)的来电。这两种方法似乎都干扰了另一种方法对状态机的假设。

使用一种方法或另一种方法很好,但混合它们并不会那么热。

如果不是使用CryptoStream而是使用HashAlgorithm.ComputeHash(Stream),那么第三种情况应该有效。

相关问题