Babak Farhang
Babak Farhang

Reputation: 109

Javascript: Use <input type="file"/> to compute SHA256 file hash

Motivation: I want to make a browser-based hashing utility so users can compute file hashes without installing software.

The approach I'm considering is a static page with "a file upload button" (except no upload takes place): the user picks a file, and the script computes and displays its hash.

So let's say we have this element on the page:

<input id="file-hasher" type="file" />

This creates a button that allows the users of the web page to select a file via an OS "File open..." dialog in the browser.

Let's say the user clicks said button, selects a file in the dialog, then clicks the "Ok" button to close the dialog.

The selected file name is now stored in:

document.getElementById("file-hasher").value

Here, I'm hoping to use a library like https://github.com/bitwiseshiftleft/sjcl/ to compute the hash of the chosen file. Is there a way to do this or does the browser's security model get in the way?

Upvotes: 2

Views: 4065

Answers (2)

mti2935
mti2935

Reputation: 12027

Yes, you can select a file using the file element, and take a hash of the file locally, 'in-browser', using javascript. The browser's security model does not prevent this; and the hash function from the native Web Crypto API can be used, so there is no need for any external crypto libraries.

Here is a working example:

function hashfile() {
  readbinaryfile(fileselector.files[0])
    .then(function(result) {
      result = new Uint8Array(result);
      return window.crypto.subtle.digest('SHA-256', result);
    }).then(function(result) {
      result = new Uint8Array(result);
      var resulthex = Uint8ArrayToHexString(result);
      divresult.innerText = 'result: ' + resulthex;
    });
}

function readbinaryfile(file) {
  return new Promise((resolve, reject) => {
    var fr = new FileReader();
    fr.onload = () => {
      resolve(fr.result)
    };
    fr.readAsArrayBuffer(file);
  });
}

function Uint8ArrayToHexString(ui8array) {
  var hexstring = '',
    h;
  for (var i = 0; i < ui8array.length; i++) {
    h = ui8array[i].toString(16);
    if (h.length == 1) {
      h = '0' + h;
    }
    hexstring += h;
  }
  var p = Math.pow(2, Math.ceil(Math.log2(hexstring.length)));
  hexstring = hexstring.padStart(p, '0');
  return hexstring;
}
<h2>File Hash</h2>
<div>
  Select file to take hash of:
  <br/>
  <input type="file" id="fileselector" onchange="javascript:hashfile();">
</div>
<br/>
<div id="divresult"></div>

Upvotes: 7

Babak Farhang
Babak Farhang

Reputation: 109

The standard browser security model allows you to have the user pick a file and do what you will with it. I'm an older guy and thought surely this kinda mingling with a user's parts would require additional hoops/consent. So @ceving 's answer was best: "Do it and you will see."

Here's a link to a good article: https://humanwhocodes.com/blog/2012/05/08/working-with-files-in-javascript-part-1/

Apologies for not trying first before posting.

Upvotes: 0

Related Questions