How to make a hash first N bytes of a file?

Using .net, I would like to be able to hash the first N bytes of potentially large files, but I cannot find a way to do this.

The ComputeHash function (I use SHA1) accepts a byte array or stream, but the stream seems to be the best way to do this, since I would prefer not to load a potentially large file into memory.

To be clear : I don't want to load a potentially large portion of the data into memory if I can help. If the file is 2 GB and I want the hash of the first 1 GB, this is a lot of RAM!

+3
source share
5 answers

CryptoStream - - :

var sha1 = SHA1Managed.Create();

FileStream fs = \\whatever
using (var cs = new CryptoStream(fs, sha1, CryptoStreamMode.Read))
{
    byte[] buf = new byte[16];
    int bytesRead = cs.Read(buf, 0, buf.Length);
    long totalBytesRead = bytesRead;

    while (bytesRead > 0 && totalBytesRead <= maxBytesToHash)
    {
        bytesRead = cs.Read(buf, 0, buf.Length);
        totalBytesRead += bytesRead;
    }
}

byte[] hash = sha1.Hash;
+6

FileStream, n MemoryStream, MemoryStream.

+1

, .

, Read , .

, - Read in , .

, , proxy , (FileStream ) Read , , . , , -1, , .

+1

, , .

, , .

Edit: Read the comments for recommendations on how to improve this implementation. End editing

public class LimitedStream : Stream
{
    private int current = 0;
    private int limit;
    private Stream stream;
    public LimitedStream(Stream stream, int n)
    {
        this.limit = n;
        this.stream = stream;
    }

    public override int ReadByte()
    {
        if (current >= limit)
            return -1;

        var numread = base.ReadByte();
        if (numread >= 0)
            current++;

        return numread;
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        count = Math.Min(count, limit - current);
        var numread = this.stream.Read(buffer, offset, count);
        current += numread;
        return numread;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void Flush()
    {
        throw new NotImplementedException();
    }

    public override long Length
    {
        get { throw new NotImplementedException(); }
    }

    public override long Position
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (this.stream != null)
        {
            this.stream.Dispose();
        }
    }
}

The following is an example of a stream in use that wraps a file stream but reduces the number of bytes read to the specified limit:

using (var stream = new LimitedStream(File.OpenRead(@".\test.xml"), 100))
{
    var bytes = new byte[1024];
    stream.Read(bytes, 0, bytes.Length);
}
+1
source

Source: https://habr.com/ru/post/1758755/


All Articles