0

环境:3 GB 数据文件,末尾附加 28 字节 SHA-1 校验和。

是否可以使用 FileStream 或其他类型的流通过从位置 0 读取流到位置 [x - 28(附加校验和的长度)] 来计算 SHA-1 校验和哈希,而无需从物理上删除附加校验和文件末尾先?

目前我们正在使用 FileStream 打开文件,然后使用 BinaryReader 来查找和读取文件的最后 28 个字节。

然后使用 FileStream 再次打开文件并将流的长度设置为长度 - 28 字节,这将从文件中删除校验和。

最后,我们正在计算删除最后 28 个字节的数据文件的校验和,然后将其与我们从文件末尾删除的校验和进行比较,以确保校验和匹配。

基本上我想知道是否可以计算文件数据部分的校验和,而不必先删除附加的校验和。

4

2 回答 2

5

如果您知道您真正想要读取多少数据(即长度 - 28 字节),那么当您计算哈希时,只输入那么多数据。您还没有确切说明您是如何计算哈希的,但您通常可以重复地将更多数据“写入”到哈希计算中 - 只要您需要,就这样做,直到您到达最后 28 个字节。

样本:

public byte[] Sha1ExceptEnd(Stream input, int bytesToOmit)
{
    long bytesToRead = input.Length - bytesToOmit;
    byte[] buffer = new byte[16 * 1024]; // Hash up to 16K at a time
    using (SHA1 sha1 = SHA1.Create())
    {
        while (bytesToRead > 0)
        {
            int thisPass = (int) Math.Min(buffer.Length, bytesToRead);
            int bytesReadThisPass = input.Read(buffer, 0, thisPass);
            if (bytesReadThisPass <= 0)
            {
                throw new IOException("Unexpected end of data");
            }  
            sha1.TransformBlock(buffer, 0, bytesReadThisPass, buffer, 0);
            bytesToRead -= bytesReadThisPass;
        }
        // Flush the hash
        sha1.TransformFinalBlock(buffer, 0, 0);
        return sha1.Hash;
    }
}
于 2012-07-06T21:38:52.843 回答
0

花哨的方法是创建包装器 Stream 对象,该对象将读取给定底层流的子部分。这样,您就可以为 FileStream 的每个子部分构造其他对象(如阅读器)。

在您感兴趣的范围内直接从流中读取字节会容易得多。

于 2012-07-06T21:40:25.723 回答