2016-09-22 5 views
1

私は、最初のHMACといくつかのデータが結合された第2のHMACを作成したいユースケースがあります。CryptoStreamでインスタンスを再利用すると、HMACSHA512のハッシュが異なる

私は1ウント2は、同じハッシュを作成しているので、これは混乱して、テストケース3は間違っ HMACを作成している理由を理解したいと思います。

コード:

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== 

答えて

1

:3で同じことを行うには、これを試してみてください。 2つのアプローチは、それぞれが持つ他のステートマシンについての前提を妨げるようです。

1つのアプローチを使用してもよいし、もう1つのアプローチを使用しても問題ありませんが、それらを混合することは熱くなりません。

CryptoStreamの代わりにHashAlgorithm.ComputeHash(Stream)を使用した場合、3番目のケースがうまくいくはずです。

+0

これは、CryptoStreamに関するリンクされた質問です。http://stackoverflow.com/q/39637026/1776231 –

+0

無効な状態になった場合、ステートマシンは例外をスローするべきではありませんか? –

+0

さて、最大の問題は、TransformFinalBlockがInitialize()を呼び出さないため、ハッシュがデータなし状態にリセットされないことです。もう一つの方向は、ComputeHashがTransformBlockのデータをふりをする前のTransformBlockと同様の問題があります。これがアプリケーションのバグであることがわかりますが、これらの動作に依存するアプリケーションはバグと見なします。 (ComputeHash(Array.Empty )を呼び出して状態をリセットすることができます) – bartonjs

1

3を除くすべてのメソッドでは、あなたが最初のハッシュ計算と二番目の間、あなたのHMACを再初期化しているためです。 ComputeHashへの呼び出しで(CryptoStreamで使用される)TransformBlock/TransformFinalBlockにあなたが混在通話あなたの第三の場合

{ 
    // 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)}"); 
} 
+0

In(1)私はctor HMACSHA512を1回呼び出すので、そこにhmacを再初期化しませんでした。それとも、私は何かが恋しいですか? –

関連する問題