0

I need to get the digest of an uploaded file in my AngularJS app, but the result digest is different from the file digest I get with bash.

I started using jshashes, but when I saw that the resultant hash (on the web app) was different from the one which I get locally using bash I decided to move to CryptoJS. But the result is the same,the hash from the uploaded file is still different.

Here's my code:

var reader = new FileReader();    
reader.readAsBinaryString(controller.file);
controller.fileHash = CryptoJS.SHA256(reader.result).toString(CryptoJS.enc.Hex);

As you can see the code is quite simple, just reads the uploaded file from the variable using FileReader and convert the value into a BinaryString, hash the content and finally assign the result to another controller valriable to show it in the html.

In my shell (local environment) to get the file digest I run the following command:

$ shasum -a 256 [path/to/file]

In order to upload files, i'm using ng-file-upload

What I'm missing? If anyone can help me or guide me to see the solution I will be very greatful.

Thank you in advance.

Update 1: As @destroyer said in the comments below readAsBinaryString is deprecated and it's an asynchronous method, so here's my actual code:

var reader = new FileReader();
reader.onload = function() {
    controller.fileHash = CryptoJS.SHA256(reader.result).toString(CryptoJS.enc.Hex);
};
reader.readAsArrayBuffer(controller.file);

I tried this solution in order to convert the ArrayBuffer object into a BinaryString. But the result is still wrong.

Update 2: Here's an image of a console log og the object I want to hash File object console.log

marc
  • 527
  • 6
  • 23
  • Can we see the "local" code? – pishpish Apr 24 '18 at 12:41
  • @destoryer I've just edited the question. To sum up, in my local environment I run this command: `$ shasum -a 256 [path/to/file]` – marc Apr 24 '18 at 12:57
  • 1
    I deleted my answer as I can't seem to help you: I've used [js-sha256](https://github.com/emn178/js-sha256) on `ArrayBuffer`s in the past without any problems. – pishpish Apr 24 '18 at 14:32
  • @destroyer you did it... thank you very much. It works. I've spend a couple of days trying to solve it, I don't know why I didn't find this library until now, but it works! If you write an answer with just a link to the library, I will vote it. – marc Apr 24 '18 at 15:18
  • Glad to help, the answer is back and updated. – pishpish Apr 24 '18 at 16:56

1 Answers1

1

readAsBinaryString is deprecated, you should use readAsArrayBuffer.

Either way, those functions start an asynchronous operation, the result of which you read inside the FileReader instance's load event.

var reader = new FileReader();    
reader.onload = function(){
  controller.fileHash = CryptoJS.SHA256(reader.result).toString(CryptoJS.enc.Hex);
};
reader.readAsArrayBuffer(controller.file);

Reflecting on our conversation in comments: the problem was that crypto-js does not operate on binary files, but on strings.

You can get a SHA256 implementation that supports ArrayBuffers directly in js-sha256.

pishpish
  • 2,574
  • 15
  • 22
  • @destroyer you are right. My mistake. Sorry. Even though the result is still wrong. I tryed to convert the result into a binary string, following the instructions in this (https://stackoverflow.com/a/32556944/2132144) response, but the result is still wrong. I don't know what I'm doing wrong. – marc Apr 24 '18 at 13:29
  • Are you sure `controller.file` is a `File`or `Blob`? – pishpish Apr 24 '18 at 13:40
  • @destroyer Yes, i'm pretty sure that it's a File. I'm going to update the original question with an image of a `console.log` of the object. Please, check it. – marc Apr 24 '18 at 13:59
  • One more thing that crosses my mind - try removing `.toString(CryptoJS.enc.Hex)` – pishpish Apr 24 '18 at 14:10
  • @destroyer the output is an WordArray Object. Teh documentation say that you need to convert into a string callint `.toString` method and passing an encoder. – marc Apr 24 '18 at 14:20