【问题标题】:Calculating MD5 hash of a partial stream计算部分流的 MD5 哈希
【发布时间】:2011-08-27 19:41:45
【问题描述】:

我有一个以自定义文件格式存储的大型数据集 (~1GB),其中最后 16 个字节是文件所有先前字节的 MD5 哈希。

我想使用 HashAlgorithm.ComputeHash(Stream) 对照嵌入式 MD5 验证此文件的 MD5,但是这将计算整个文件的哈希值,包括最后 16 字节的哈希值,这显然不起作用。

如何计算流的 PART 的 MD5 哈希?我知道我可以将流读入一个数组并将其传递给 HashAlgorithm.ComputeHash(Bytes),但是在内存中复制这 1GB 数据的开销是令人望而却步的。

【问题讨论】:

  • 请注意 MD5 不再是一种安全的哈希算法
  • 我使用它只是为了验证文件在磁盘或内存中没有损坏,所以这不是问题。

标签: .net stream iostream


【解决方案1】:

取自here,您还可以通过其他方式获得。

制作一个部分文件流类,读取你想要的大小并对其进行哈希处理。

 class PartialFileStream : FileStream
{
    public PartialFileStream(string path, FileMode mode, long startPosition, long endPosition): base(path, mode)
{
  base.Seek(startPosition, SeekOrigin.Begin);
  ReadTillPosition = endPosition;
}

public long ReadTillPosition { get; set; }

public override int Read(byte[] array, int offset, int count)
{
 if (base.Position >= this.ReadTillPosition)
   return 0;

 if (base.Position + count > this.ReadTillPosition)
   count = (int)(this.ReadTillPosition - base.Position);

 return base.Read(array, offset, count);
  }
}

【讨论】:

  • PartialFileStream 的用户仍然可以在段外进行Seek。此外,Length 和 Position 属性与段不匹配,但与文件的属性不匹配。
  • 我已经发布了my solution,它应该可以解决我之前评论中提到的问题。
【解决方案2】:

您可以使用FileStream.Seek 选项来寻找流的特定位置并从那里读取。

【讨论】:

  • 他的问题是不同的 - 他可以寻找但他不想散列流的末尾。当然,如果哈希可以在文件的开头,他可以使用 seek 并对其余部分进行哈希。
【解决方案3】:

我发现自己在 6 个月内第二次需要这个,所以发布我的部分输入流的解决方案。

class PartialStream: Stream {
    public Stream Source { get; }
    public long Offset { get; }
    public override long Length { get; }

    private long End => Offset + Length;

    public override bool CanRead => true;

    public override bool CanSeek => false;

    public override bool CanWrite => false;

    public override long Position {
        get => Source.Position - Offset;
        set => throw new NotSupportedException();
    }

    public PartialStream(Stream source, long length) {
        Offset = source.Position;
        Length = length;
    }

    public PartialStream(Stream source, long offset, long length, bool seekToOffset = true) {
        if (seekToOffset) source.Seek(offset, SeekOrigin.Begin);
        Offset = offset;
        Length = length;
    }

    public override int Read(byte[] array, int offset, int count) {
        if (Source.Position >= End) return 0;

        if (Source.Position + count > End)
            count = (int)(End - Source.Position);

        return Source.Read(array, offset, count);
    }

    public override void Flush() => throw new NotSupportedException();
    public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
}

【讨论】:

    猜你喜欢
    • 2012-04-14
    • 1970-01-01
    • 2011-12-08
    • 2017-01-27
    • 1970-01-01
    • 2011-06-14
    • 2015-12-18
    • 2012-07-12
    • 1970-01-01
    相关资源
    最近更新 更多