C# 如何计算3 GB文件的校验和,但首先删除最后28个字节

C# 如何计算3 GB文件的校验和,但首先删除最后28个字节,c#,hash,C#,Hash,环境: 3 GB数据文件,末尾附加28字节SHA-1校验和 是否可以使用FileStream或其他类型的流来计算SHA-1校验和哈希,方法是将流从位置0读取到位置[x-28(附加校验和的长度)],而不首先从文件末尾物理删除附加校验和 目前,我们正在使用FileStream打开文件,然后使用BinaryReader读取文件,以查找并读取文件的最后28个字节 然后使用文件流再次打开文件,并将流的长度设置为-28字节,这将从文件中删除校验和 最后,我们将计算数据文件的校验和,并删除最后28个字节,然后

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

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

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

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

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


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

如果您知道您真正想要读取多少数据(即长度-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;
    }
}
public byte[]Sha1ExceptEnd(流输入,int-bytesToOmit)
{
long bytesToRead=input.Length-bytesToOmit;
byte[]buffer=新字节[16*1024];//一次最多散列16K
使用(SHA1 SHA1=SHA1.Create())
{
while(bytesToRead>0)
{
int thisPass=(int)Math.Min(buffer.Length,bytesToRead);
int bytesReadThisPass=input.Read(缓冲区,0,thisPass);

如果(bytesReadThisPass如果你知道你真正想要读取多少数据(即长度-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;
    }
}
public byte[]Sha1ExceptEnd(流输入,int-bytesToOmit)
{
long bytesToRead=input.Length-bytesToOmit;
byte[]buffer=新字节[16*1024];//一次最多散列16K
使用(SHA1 SHA1=SHA1.Create())
{
while(bytesToRead>0)
{
int thisPass=(int)Math.Min(buffer.Length,bytesToRead);
int bytesReadThisPass=input.Read(缓冲区,0,thisPass);

如果(bytesReadThisPass,一种奇特的方法是创建包装器流对象,该对象将读取给定底层流的子部分。通过这种方法,您将能够为FileStream的每个子部分构造其他对象(如读卡器)


更简单的方法是直接从您感兴趣的范围内的流中读取字节。

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


更简单的方法是直接从您感兴趣的范围内的流中读取字节。

我假设它们正在使用。@Lucero:对,而我的方法有点曲折-但最终达到了目的。Jon我正在使用SHA1CryptoServiceProvider并调用ComputeHash方法传入一个文件流。@hype8912:对-而您可以我要写一个长度限制流,这很棘手。试试我给你的代码吧-你可能想把它改编成
SHA1CryptoServiceProvider
,但它应该是可以的。@Jon,我猜(现在已经确认了)只是基于他们的描述。我会用和你一样的方法来解决手头的任务;+1;)我假设他们正在使用。@Lucero:对,而我的方法有点麻烦,但最终达到了目的。Jon我正在使用SHA1CryptoServiceProvider并调用传入文件流的ComputeHash方法。@hype8912:对-虽然您可以编写长度限制流,但这很棘手。请尝试我给出的代码,您可以这样做您可能想将其应用于
SHA1CryptoServiceProvider
,但它应该是可以的。@Jon,我的猜测(现在已确认)只是基于他们的描述。我会采用与您相同的方法来解决手头的任务;+1;)