在C#中生成运行哈希(或校验和)?

前言:

我正在进行具有validation提交阶段的数据导入。 我们的想法是:第一阶段允许从各种来源获取数据,然后在数据库上运行各种插入/更新/validation操作。 提交将回滚,但会生成“validation哈希/校验和”。 提交阶段是相同的,但是,如果“validation散列/校验和”相同,则将提交操作。 (数据库将在适当的隔离级别下运行。)

限制:

  • 输入读取和操作仅向前读取一次
  • 不想预先创建流(例如,写入MemoryStream是不可取的),因为可能存在大量数据。 (它适用于我们的服务器/负载,但假装内存有限。)
  • 不想“创造我自己的”。 (我知道可用的代码,如Damien的CRC-32 ,我可以使用/修改,但更喜欢“标准”。)

而我(我想)正在寻找:

一种基于输入+操作生成哈希(例如SHA1或MD5?)或校验和(例如CRC32但希望更多)的方法。 (输入/操作本身可以被散列为更适合校验和生成的值,但是能够“写入steam”会很好。)

所以,问题是:

如何在C#中生成Running Hash(或Checksum)?

此外,虽然可以针对Running操作修改CRC32实现,但是运行SHAx或MD5哈希呢?

我是否缺少某种方便的Stream方法而不是可以用作适配器?

(批评是受欢迎的,但也请在适用的情况下回答上述内容。此外,我不想处理线程。;-)

哈希具有构建和完成阶段。 您可以在构建阶段推送任意数量的数据。 可以根据需要拆分数据。 最后,完成哈希操作并获取哈希值。

您可以使用可写的CryptoStream来编写数据。 这是最简单的方法。

您可以多次调用HashAlgorithm.TransformBlock ,然后调用TransformFinalBlock将为您提供所有块的结果。

填充输入(通过从蒸汽中读取x个字节)并使用每个块调用TransformBlock

编辑(来自msdn示例):

 public static void PrintHashMultiBlock(byte[] input, int size) { SHA256Managed sha = new SHA256Managed(); int offset = 0; while (input.Length - offset >= size) offset += sha.TransformBlock(input, offset, size, input, offset); sha.TransformFinalBlock(input, offset, input.Length - offset); Console.WriteLine("MultiBlock {0:00}: {1}", size, BytesToStr(sha.Hash)); } 

抱歉,我没有任何可用的示例,但对于您来说,您基本上用自己的块替换input ,那么size将是该块中的字节数。 您必须自己跟踪偏移量。

您可以使用MD5CryptoServiceProvider的ComputeHash方法生成MD5哈希。 它需要一个流作为输入。

创建一个内存或文件流,将哈希输入写入,然后在完成后调用ComputeHash方法。

 var myStream = new MemoryStream(); // Blah blah, write to the stream... myStream.Position = 0; using (var csp = new MD5CryptoServiceProvider()) { var myHash = csp.ComputeHash(myStream); } 

编辑:避免构建大量Streams的一种可能性是在循环中反复调用它并对结果进行异或运算:

 // Assuming we had this somewhere: Byte[] myRunningHash = new Byte[16]; // Later on, from above: for (var i = 0; i < 16; i++) // I believe MD5 are 16-byte arrays. Edit accordingly. myRunningHash[i] = myRunningHash[i] ^ [myHash[i]; 

编辑#2:最后,在@ usr的答案的基础上,你可以使用HashCore和HashFinal:

 using (var csp = new MD5CryptoServiceProvider()) { // My example here uses a foreach loop, but an // event-driven stream-like approach is // probably more what you are doing here. foreach (byte[] someData in myDataThings) csp.HashCore(someData, 0, someData.Length); var myHash = csp.HashFinal(); } 

这是规范的方式:

 using System; using System.Security.Cryptography; using System.Text; public void CreateHash(string sSourceData) { byte[] sourceBytes; byte[] hashBytes; //create Bytearray from source data sourceBytes = ASCIIEncoding.ASCII.GetBytes(sSourceData); // calculate 16 Byte Hashcode hashBytes = new MD5CryptoServiceProvider().ComputeHash(sourceBytes); string sOutput = ByteArrayToHexString(hashBytes); } static string ByteArrayToHexString(byte[] arrInput) { int i; StringBuilder sOutput = new StringBuilder(arrInput.Length); for (i = 0; i < arrInput.Length - 1; i++) { sOutput.Append(arrInput[i].ToString("X2")); } return sOutput.ToString(); }