Reputation: 1571
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:
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
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