Page 1 of 1

Hashing Code in Javascript + HTML5

Posted: Thu Sep 20, 2012 6:38 pm
by kirill
Hi,

I didn't find any Hashing Algo for Javascript in the wiki,
but here is an implementation:

Code: Select all

function OpenSubtitlesHash(uploadInput, callback){ function getHash(arrayBuffer) { var tmp; var fsize = arrayBuffer.byteLength; var arr = new Uint16Array(arrayBuffer, 0, 8192 * 4); var hash = { 3 : 0, 2 : 0, 1 : (fsize >> 16) & 0xFFFF, 0 : fsize & 0xFFFF }; var offset = fsize >= 65536 ? (fsize - 65536) : 0; for (var i = 0; i < 8192; i++) { hash = AddUINT64(hash, arr.subarray(i*4, i * 4 + 4)); } arr = new Uint8Array(arrayBuffer, offset, 8192 * 8); for (i = 0; i < 8192; i++) { tmp = arr.subarray(i * 8, i * 8 + 8); hash = AddUINT64(hash, { 0: (tmp[1] << 8) + tmp[0], 1: (tmp[3] << 8) + tmp[2], 2: (tmp[5] << 8) + tmp[4], 3: (tmp[7] << 8) + tmp[6] }); } return UINT64FormatHex(hash); } function AddUINT64(a, b) { var o = { 0 : 0, 1 : 0, 2 : 0, 3 : 0 }; var carry = 0; for (var i = 0; i < 4; i++) { if ((a[i] + b[i] + carry) > 0xffff ) { o[i] += (a[i] + b[i] + carry) & 0xffff; carry = 1; } else { o[i] += (a[i] + b[i] + carry); carry = 0; } } return o; } function UINT64FormatHex(n) { return parseInt(n[3], 10).toString(16) + parseInt(n[2], 10).toString(16) + parseInt(n[1], 10).toString(16) + parseInt(n[0], 10).toString(16); } uploadInput.onchange = function (e) { e.preventDefault(); var file = uploadInput.files[0], reader = new FileReader(); reader.onload = function (event) { var hash; try { hash = getHash(event.target.result); } catch(e) { hash = 'error'; } callback( hash ); }; reader.readAsArrayBuffer(file); return false; }; }
But it doesn't work with big files, because the file is read completely into memory first.
Is there any other implementation for Javascript which uses the HTML 5 FileReader API but with the .slice() method instead?

Re: Hashing Code in Javascript + HTML5

Posted: Sun Sep 23, 2012 12:12 pm
by kirill
I changed the code, so now it works with the slice method, but sometimes the hash is wrong. From my tests 7 out of 10 are hashed correctly. Does someone know where the problem is?

hash.htm

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>OpenSubtitlesHash HTML5/JS</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="opensubtitleshash.js"></script> <script type="text/javascript"> window.onload = function() { if(typeof window.FileReader !== 'undefined') { document.getElementById('status').innerHTML = 'File API & FileReader available'; var uploadInput = document.getElementById('file'); var callback = function (hash, size) { document.getElementById('hash').innerHTML = 'hash= ' + "'" + hash + "'" + ';' + ' size= ' + "'" + size + "'"; } ; OpenSubtitlesHash( uploadInput, callback ); } } </script> </head> <body> <p id="status">File API & FileReader API not supported</p> <p><input type="file" id="file"></p> <p id="hash"></p> </body> </html>
opensubtitleshash.js

Code: Select all

function OpenSubtitlesHash(uploadInput, callback){ function getHash(file, slice_1, slice_2) { var tmp; var fsize = file.size; var arr = new Uint16Array(slice_1); var hash = { 3 : 0, 2 : 0, 1 : (fsize >> 16) & 0xFFFF, 0 : fsize & 0xFFFF }; for (var i = 0; i < 8192; i++) { hash = AddUINT64(hash, arr.subarray(i*4, i * 4 + 4)); } arr = new Uint16Array(slice_2); for (var i = 0; i < 8192; i++) { hash = AddUINT64(hash, arr.subarray(i*4, i * 4 + 4)); } return UINT64FormatHex(hash); } function AddUINT64(a, b) { var o = { 0 : 0, 1 : 0, 2 : 0, 3 : 0 }; var carry = 0; for (var i = 0; i < 4; i++) { if ((a[i] + b[i] + carry) > 0xffff ) { o[i] += (a[i] + b[i] + carry) & 0xffff; carry = 1; } else { o[i] += (a[i] + b[i] + carry); carry = 0; } } return o; } function UINT64FormatHex(n) { return parseInt(n[3], 10).toString(16) + parseInt(n[2], 10).toString(16) + parseInt(n[1], 10).toString(16) + parseInt(n[0], 10).toString(16); } uploadInput.onchange = function (e) { e.preventDefault(); var file = uploadInput.files[0]; var slice1 = new FileReader(); var slice2 = new FileReader(); var slice_1; var slice_2; var hash; slice1.onload = function (event) { slice_1 = event.target.result; }; slice2.onload = function (event) { slice_2 = event.target.result; try { // Getting the hash result = getHash(file, slice_1, slice_2); // Zero Padding - making sure the returned hash has always a length of 16 var pad = "0000000000000000"; hash = (pad+result).slice(-pad.length); } catch(e) { console.log(e); hash = 'error'; } callback( hash, file.size ); }; if(file.slice){ slice1.readAsArrayBuffer(file.slice(0,65536)); slice2.readAsArrayBuffer(file.slice(file.size-65536, file.size)); } else if(file.mozSlice){ slice1.readAsArrayBuffer(file.mozSlice(0,65536)); slice2.readAsArrayBuffer(file.mozSlice(file.size-65536, file.size)); } else if(file.webkitSlice){ slice1.readAsArrayBuffer(file.webkitSlice(0,65536)); slice2.readAsArrayBuffer(file.webkitSlice(file.size-65536, file.size)); } return false; }; }

Re: Hashing Code in Javascript + HTML5

Posted: Thu Sep 27, 2012 5:23 pm
by oss
you can check this file http://static.opensubtitles.org/addons/ ... widgets.js

Let me know, if it helps you

Re: Hashing Code in Javascript + HTML5

Posted: Fri Sep 28, 2012 6:31 pm
by kirill
Yeah, thanks.That one works better

Re: Hashing Code in Javascript + HTML5

Posted: Tue Oct 16, 2012 7:04 pm
by oss

Re: Hashing Code in Javascript + HTML5

Posted: Wed Oct 31, 2012 11:20 am
by mcs_dodo
kirill would you mind to post here the whole working solution with working js hash function?

Re: Hashing Code in Javascript + HTML5

Posted: Sun Apr 14, 2013 10:30 am
by oss
it would also interests me, because I find out current implementation is somehow buggy