Optional Option
Optional Option

Reputation: 1571

Using IBuffer to compute hash of the file in UWP

I cannot figure out how to compute hash of big file in UWP. Hashing algorithm accepts IBuffer interface as data parameter which has no way to get data from the stream. There are only two ways that both seem like dead ends:

  1. Loading entire file into memory would not work as file may be too big.
  2. Implementing some kind of stream reader with IBuffer interface does not seem viable either as IBuffer only has two properties: Length and Capacity.

Here is condensed sample from MSDN which shows how to use algorithm when data is in the string.

IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg);
string hex = CryptographicBuffer.EncodeToHexString(buffHash);

How can I calculate MD5 hash of a big file in UWP without coding my own algorithm or using third-party component?

Upvotes: 1

Views: 790

Answers (1)

Sunteen Wu
Sunteen Wu

Reputation: 10627

Hashing algorithm accepts IBuffer interface as data parameter which has no way to get data from the stream.

We can directly read buffer from file by FileIO.ReadBufferAsync method. And then you can hash it. Code as follows:

   StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/P408.mp4"));
   IBuffer filebuffer = await FileIO.ReadBufferAsync(file);
   //IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
   HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
   IBuffer buffHash = objAlgProv.HashData(filebuffer);
   string hex = CryptographicBuffer.EncodeToHexString(buffHash);

Implementing some kind of stream reader with IBuffer interface does not seem viable either as IBuffer only has two properties: Length and Capacity

The IInputStream.ReadAsync method can read stream to buffer. It provides buffer parameter to read InputStream to buffer. If you want to read a large file, you can define the capacity of buffer to section reading the file. Code as follows:

HashAlgorithmProvider alg = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/P408.mp4"));
var stream = await file.OpenStreamForReadAsync();
var inputStream = stream.AsInputStream();
uint capacity = 100000000;
Windows.Storage.Streams.Buffer buffer = new Windows.Storage.Streams.Buffer(capacity);
var hash = alg.CreateHash();
while (true)
{
    await inputStream.ReadAsync(buffer, capacity, InputStreamOptions.None);
    if (buffer.Length > 0)
        hash.Append(buffer);
    else
        break;
}
string hashText = CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset()).ToUpper();
inputStream.Dispose();
stream.Dispose();

More details please reference the official sample.

Upvotes: 4

Related Questions