Calculate the hash of Blob using JavaScript
Asked Answered
R

2

12

I want to compare two Blobs to see if there are changes between them.

One way of doing this is by calculating the hash of the blobs and then comparing them, e.g.:

hash(firstBlob) === hash(secondBlob)

How can I calculate the hash of a Blob and check against another hash to see if they have changed?

Renwick answered 17/12, 2013 at 0:2 Comment(0)
H
10

I know this is kind of old but for someone looking for a better and newer solution please use the Crypto API and a SHA-256 or higher variant for the algorithm since MD5 has exploitable flaws.

var a = new FileReader();
a.readAsArrayBuffer(blob);
a.onloadend = function () {
  let hashPromise = crypto.subtle.digest("SHA-256", a.result);// it outputs a promise
};
Highwrought answered 15/5, 2020 at 15:36 Comment(0)
T
12

You can use the FileReader API to get the contents of the blob for comparison. If you have to use CryptoJS for this, you can use readAsBinaryString:

var a = new FileReader();
a.readAsBinaryString(blob);
a.onloadend = function () {
  console.log(CryptoJS.MD5(CryptoJS.enc.Latin1.parse(a.result)));
};

Note that readAsBinaryString is deprecated, so if you can use another library, such as SparkMD5, you could use an array buffer instead:

var a = new FileReader();
a.readAsArrayBuffer(blob);
a.onloadend = function () {
  console.log(SparkMD5.ArrayBuffer.hash(a.result));
};
Thumbnail answered 17/12, 2013 at 0:14 Comment(7)
@RaymondWu: seems you're correct, fixed the answer. Thanks!Thumbnail
you sould define the onloadend method before the call to readAsBinaryString or readAsArrayBuffer : otherwise, with a small enough buffer, you might get the onloadend event handler registered after the event was triggeredWingover
@Thierry: I don't think that's ever happened in my experience -- IIRC readAs* is defined to be asynchronous, which means the onloadend function will be defined before the event is called.Thumbnail
Asynchronous doesn't mean that. Asynchronous means it might run after the next instruction. It might also run before. In this particular case, we observe that most of the time it running after the next instruction. It is not guaranteed though.Wingover
@Wingover if that was the case, then this would be the case no matter what: blog.izs.me/post/59142742143/designing-apis-for-asynchronyThumbnail
Well, it is extremely interesting reading, but the guys are discussing how an API should be implemented either async or sync but not both depending on the case. It does not say that every API either async or sync. Then if you look at the javascript spec of readAsArrayBuffer : w3c.github.io/FileAPI/#readAsArrayBuffer it does not mention anywhere that the API must be async. So the behavior will be browser depend. Setting onloadend before calling readAsArrayBuffer will not trigger any issue and is valid, and will not be subject to 'strange' issues (reproductible in debug in firefx)Wingover
Since the behavior is browser specific, and may be async, it's best to assume it is. Therefore, it's best to set the event handlers before calling the function that will lead to the event being emitted.Halfhour
H
10

I know this is kind of old but for someone looking for a better and newer solution please use the Crypto API and a SHA-256 or higher variant for the algorithm since MD5 has exploitable flaws.

var a = new FileReader();
a.readAsArrayBuffer(blob);
a.onloadend = function () {
  let hashPromise = crypto.subtle.digest("SHA-256", a.result);// it outputs a promise
};
Highwrought answered 15/5, 2020 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.