验证失败(C#.NET HMACSHA256类)

时间:2017-10-19 14:39:30

标签: c# .net cryptography hmac hmacsha1

我正在尝试学习.NET API,并且我创建了一个程序,用于将源文件中的密钥与XML文件中的密钥进行比较。

我使用了以下exaple(第三种方法来修改文档:

https://docs.microsoft.com/en-gb/dotnet/api/system.security.cryptography.hmacsha256?view=netframework-4.7.1

现在我的程序运行但它总是说文件已被篡改,即使我完全确定它们不是因为我刚创建它们。

这是我的代码:

VerifyDocument.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Xml.Serialization;

public class VerifyDocument
{

public static void Main(string[] args)
{

XmlSerializer xml = new XmlSerializer(typeof(byte[]));
byte[] key;
string keyFile = args[1];
string sourceFile = args[0];
using (StreamReader reader = new StreamReader(keyFile)) {
  key = (byte[]) xml.Deserialize(reader);
}

bool err = false;

        using (HMACSHA256 hmac = new HMACSHA256(key)) // Initialize the keyed hash object.
        {

            byte[] storedHash = new byte[hmac.HashSize / 8]; // Create an array to hold the keyed hash value read from the file.

            using (FileStream inStream = new FileStream(sourceFile, FileMode.Open)) // Create a FileStream for the source file.
            {

                inStream.Read(storedHash, 0, storedHash.Length); // Read in the storedHash.

                byte[] computedHash = hmac.ComputeHash(inStream);
                // compare the computed hash with the stored value

                for (int i = 0; i < storedHash.Length; i++)
                {
                    if (computedHash[i] != storedHash[i])
                    {
                        err = true;
                    }
                }
            }
        }
        if (err)
        {
            Console.WriteLine("Hash values differ! Signed file has been tampered with!");

        }
        else
        {
            Console.WriteLine("Hash values agree -- no tampering occurred.");

        }

}

}

SignDocument.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Xml.Serialization;

public class HMACSHA256example
{    

   public static void Main(string[] args)
  {


    if (args.Length != 2) {
      Console.WriteLine("Usage: [mono] SignDocument.exe <filename> <key>");
      Environment.Exit(1);
    } else
    {
      XmlSerializer xml = new XmlSerializer(typeof(byte[]));
      byte[] key;
      string keyFile = args[1];
      string sourceFile = args[0];
      string destFile = sourceFile + ".hash";
      using (StreamReader reader = new StreamReader(keyFile)) {
        key = (byte[]) xml.Deserialize(reader);
      }

      using (HMACSHA256 hmac = new HMACSHA256(key)) // Initialize the keyed hash object.
      {
          using (FileStream inStream = new FileStream(sourceFile, FileMode.Open))
          {
              using (FileStream outStream = new FileStream(destFile, FileMode.Create))
              {

                  byte[] hashValue = hmac.ComputeHash(inStream); // Compute the hash of the input file.


                  outStream.Write(hashValue, 0, hashValue.Length); // Write the computed hash value to the output file.

          }
      }

    }

 }
 }
 }

CreateKey.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Xml.Serialization;

namespace COMP3911.Crypto {


class CreateKey {
static void Main(string[] args) {

  string input;

  if (args.Length == 0) {
    Console.WriteLine("Usage: [mono] CreateKey.exe <filename>");
    Environment.Exit(1);
  }

  byte[] secretkey = new Byte[64];
        //RNGCryptoServiceProvider is an implementation of a random number generator.
        using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
        {
            // The array is now filled with cryptographically strong random bytes.
            rng.GetBytes(secretkey);
        }


  // XML
  string keyfile = args[0] + ".key";
  using (StreamWriter output = new StreamWriter(keyfile, false)) {
    XmlSerializer xml = new XmlSerializer(typeof(byte[]));
    xml.Serialize(output, secretkey);
  }
}
}

}

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

您的&#34;签署&#34;程序读取inStream并仅将HMAC写入outStream

你的&#34;验证&#34;程序读取一个文件,并期望它是HMAC,然后是数据。

&#34;签署&#34;需要快退inStream,然后将其复制到outStream,或者您需要更改&#34;验证&#34;单独查看这两个文件。

答案 1 :(得分:0)

SignDocument.cs有错误。您正在编写签名但未能写入文件的其余部分。

它应该是这样的(大多数是从链接到的文档页面复制的):

using (HMACSHA256 hmac = new HMACSHA256(key)) // Initialize the keyed hash object.
{
    using (FileStream inStream = new FileStream(sourceFile, FileMode.Open))
    {
        using (FileStream outStream = new FileStream(destFile, FileMode.Create))
        {
            byte[] hashValue = hmac.ComputeHash(inStream); // Compute the hash of the input file.
            outStream.Write(hashValue, 0, hashValue.Length); // Write the computed hash value to the output file.

            inStream.Position = 0;
            int bytesRead;
            byte[] buffer = new byte[1024];
            do
            {
                bytesRead = inStream.Read(buffer, 0, 1024);
                outStream.Write(buffer, 0, bytesRead);
            } while (bytesRead > 0);

        }
    }
}

<强>更新

不确定为什么MSDN版本不使用CopyTo,但似乎更好:

byte[] hashValue = hmac.ComputeHash(inStream);
outStream.Write(hashValue, 0, hashValue.Length);

inStream.Position = 0;
inStream.CopyTo(outStream);