Javascript: calculate OpenSubtitles hash - getting wrong result - javascript

I am trying to calculate correct OpenSubtitles hash code for files in Javascript, but for big files it doesnt work correctly - so I asume, there is problem with size of file (overflow). OpenSubtitles hash with source codes is described here: http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
I am testing this code with Dummy RAR File (unpacked) - http://www.opensubtitles.org/addons/avi/dummy.rar, correct result is 61f7751fc2a72bfb but this code gives 61f7751ec2a72bfb - so there is some error. I am not good at Javascript. Also I found others got similar problems: http://forum.opensubtitles.org/viewtopic.php?f=8&t=13243 and maybe this works: https://github.com/ka2er/node-opensubtitles-api/blob/master/lib/opensubtitles.js
Question is, what is needed to change, so I get correct hash? Thanks.
function binl2hex(a)
{
var b = 255;
a[1] += a[0] >> 8;
a[0] = a[0] & b;
a[2] += a[1] >> 8;
a[1] = a[1] & b;
a[3] += a[2] >> 8;
a[2] = a[2] & b;
a[4] += a[3] >> 8;
a[3] = a[3] & b;
a[5] += a[4] >> 8;
a[4] = a[4] & b;
a[6] += a[5] >> 8;
a[5] = a[5] & b;
a[7] += a[6] >> 8;
a[6] = a[6] & b;
a[7] = a[7] & b;
for (var d = "0123456789abcdef", e = "", c = 7; c > -1; c--)
e += d.charAt(a[c] >> 4 & 15) + d.charAt(a[c] & 15);
return e
}
$(document).ready(function()
{
jQuery.event.props.push('dataTransfer');
$('#search_field').bind('drop', function(e)
{
var files = e.dataTransfer.files;
$.each(files, function(index, file)
{
if(files.length > 1)
{
$('#top_msg').attr('class', 'msg warn');
$('#top_msg').html('multiple files are <b>not supported</b> (yet)');
return false;
}
if (!files[index].type.match('video.*') && !files[index].name.match(/\.(mkv)$/i))
{
//|| !files[index].name.match('/mkv/i')
$('#top_msg').attr('class', 'msg warn');
$('#top_msg').html('search works only for <b>video</b> files.');
return false;
}
$('#top_msg').html('<b>File upload and hashing in progress</b>...');
$('#top_msg').attr('class', 'msg indicator');
var b = 65536;
fs = file.size;
var e = Array(8);
for (var a = fs, f = 0; f < 8; f++)
{
e[f] = a & 255;
a = a >> 8
}
a = fs;
var c = file.slice(0, b);
var g = new FileReader;
g.onloadend = function (h)
{
if (h.target.readyState == FileReader.DONE)
{
for (var f = h.target.result, d = 0; d < f.length; d++)
e[(d + 8) % 8] += f.charCodeAt(d);
c = file.slice(a - b);
var g = new FileReader;
g.onloadend = function (c)
{
var b = "languages";
if (c.target.readyState == FileReader.DONE)
{
f = c.target.result;
for (d = 0; d < f.length; d++)
e[(d + 8) % 8] += f.charCodeAt(d);
lang = $("#SubLanguageID").multiselect("getChecked").map(function()
{
return this.value
}).get().join(",");
if (lang == "")
lang = "all";
var url = "http://www.opensubtitles.org/" + $(location).attr('pathname').substr(1,2) + "/search/sublanguageid-" + lang + "/moviehash-" + binl2hex(e);
document.location = url;
}
};
g.readAsBinaryString(c)
}
};
g.readAsBinaryString(c)
});
});
});

Related

Hashing password authentication with JavaScript?

Password = base64 encoded(sha1(nonce+created+secret))
where:
nonce = 186269,
created = 2015-07-08T11:31:53+01:00,
secret = Ok4IWYLBHbKn8juM1gFPvQxadieZmS2
should give ZDg3MTZiZTgwYTMwYWY4Nzc4OGFjMmZhYjA5YzM3MTdlYmQ1M2ZkMw== as password. I am approaching with:
I need the JavaScript for this.
As per security standards this is still not good to perform such coding, one should always do this in backend programming language & get value from API Calls.
but you can use the sha1 function below to do sha1 hashing in JavaScript:
function sha1 (str) {
// discuss at: https://locutus.io/php/sha1/
// original by: Webtoolkit.info (https://www.webtoolkit.info/)
// improved by: Michael White (https://getsprink.com)
// improved by: Kevin van Zonneveld (https://kvz.io)
// input by: Brett Zamir (https://brett-zamir.me)
// note 1: Keep in mind that in accordance with PHP, the whole string is buffered and then
// note 1: hashed. If available, we'd recommend using Node's native crypto modules directly
// note 1: in a steaming fashion for faster and more efficient hashing
// example 1: sha1('Kevin van Zonneveld')
// returns 1: '54916d2e62f65b3afa6e192e6a601cdbe5cb5897'
let hash
try {
const crypto = require('crypto')
const sha1sum = crypto.createHash('sha1')
sha1sum.update(str)
hash = sha1sum.digest('hex')
} catch (e) {
hash = undefined
}
if (hash !== undefined) {
return hash
}
const _rotLeft = function (n, s) {
const t4 = (n << s) | (n >>> (32 - s))
return t4
}
const _cvtHex = function (val) {
let str = ''
let i
let v
for (i = 7; i >= 0; i--) {
v = (val >>> (i * 4)) & 0x0f
str += v.toString(16)
}
return str
}
let blockstart
let i, j
const W = new Array(80)
let H0 = 0x67452301
let H1 = 0xEFCDAB89
let H2 = 0x98BADCFE
let H3 = 0x10325476
let H4 = 0xC3D2E1F0
let A, B, C, D, E
let temp
// utf8_encode
str = unescape(encodeURIComponent(str))
const strLen = str.length
const wordArray = []
for (i = 0; i < strLen - 3; i += 4) {
j = str.charCodeAt(i) << 24 |
str.charCodeAt(i + 1) << 16 |
str.charCodeAt(i + 2) << 8 |
str.charCodeAt(i + 3)
wordArray.push(j)
}
switch (strLen % 4) {
case 0:
i = 0x080000000
break
case 1:
i = str.charCodeAt(strLen - 1) << 24 | 0x0800000
break
case 2:
i = str.charCodeAt(strLen - 2) << 24 | str.charCodeAt(strLen - 1) << 16 | 0x08000
break
case 3:
i = str.charCodeAt(strLen - 3) << 24 |
str.charCodeAt(strLen - 2) << 16 |
str.charCodeAt(strLen - 1) <<
8 | 0x80
break
}
wordArray.push(i)
while ((wordArray.length % 16) !== 14) {
wordArray.push(0)
}
wordArray.push(strLen >>> 29)
wordArray.push((strLen << 3) & 0x0ffffffff)
for (blockstart = 0; blockstart < wordArray.length; blockstart += 16) {
for (i = 0; i < 16; i++) {
W[i] = wordArray[blockstart + i]
}
for (i = 16; i <= 79; i++) {
W[i] = _rotLeft(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1)
}
A = H0
B = H1
C = H2
D = H3
E = H4
for (i = 0; i <= 19; i++) {
temp = (_rotLeft(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff
E = D
D = C
C = _rotLeft(B, 30)
B = A
A = temp
}
for (i = 20; i <= 39; i++) {
temp = (_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff
E = D
D = C
C = _rotLeft(B, 30)
B = A
A = temp
}
for (i = 40; i <= 59; i++) {
temp = (_rotLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff
E = D
D = C
C = _rotLeft(B, 30)
B = A
A = temp
}
for (i = 60; i <= 79; i++) {
temp = (_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff
E = D
D = C
C = _rotLeft(B, 30)
B = A
A = temp
}
H0 = (H0 + A) & 0x0ffffffff
H1 = (H1 + B) & 0x0ffffffff
H2 = (H2 + C) & 0x0ffffffff
H3 = (H3 + D) & 0x0ffffffff
H4 = (H4 + E) & 0x0ffffffff
}
temp = _cvtHex(H0) + _cvtHex(H1) + _cvtHex(H2) + _cvtHex(H3) + _cvtHex(H4)
return temp.toLowerCase()
}
// create sha1
var e = sha1('186269'+'2015-07-08T11:31:53+01:00'+'Ok4IWYLBHbKn8juM1gFPvQxadieZmS2');
console.log(e)
// to base64 encoding
var encoded = btoa(e)
console.log(encoded)
Function link: https://locutus.io/php/sha1/

Unknow json response from Sencha based api

I am having trouble decoding the following json response from a sencha based api.
I tried decoding it to base64 string but the end result was always malformed and has many unrecognized characters.
function handleServerReponse(a) {
if (a.substr(0, 5) == 'I:Qc[') {
var f = 5;
var e = (a.substr(5) + '').split('');
var d = [];
for (var b = e.length - 1; b >= 0; b--) {
d[b] = String.fromCharCode(e[b].charCodeAt(0) - f)
}
var c = d.join('');
//c = fix_utf8(base64_decode(c));
//c = base64_decode(c);
a = c
}
return a
}
function fix_utf8(c) {
var d = []
, a = 0
, b = 0
, e = 0
, f = 0;
while (a < c.length) {
b = c.charCodeAt(a);
if (b < 128) {
d.push(String.fromCharCode(b));
a++
} else {
if (b > 191 && b < 224) {
e = c.charCodeAt(a + 1);
d.push(String.fromCharCode((b & 31) << 6 | e & 63));
a += 2
} else {
e = c.charCodeAt(a + 1);
f = c.charCodeAt(a + 2);
d.push(String.fromCharCode((b & 15) << 12 | (e & 63) << 6 | f & 63));
a += 3
}
}
}
return d.join('')
}
function base64_decode(a) {
var e = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var f, j, n, l, m, h, i, d, b = 0, g = 0, k = '', c = [];
if (!a) {
return a
}
a += '';
do {
l = e.indexOf(a.charAt(b++));
m = e.indexOf(a.charAt(b++));
h = e.indexOf(a.charAt(b++));
i = e.indexOf(a.charAt(b++));
d = l << 18 | m << 12 | h << 6 | i;
f = d >> 16 & 255;
j = d >> 8 & 255;
n = d & 255;
if (h == 64) {
c[g++] = String.fromCharCode(f)
} else {
if (i == 64) {
c[g++] = String.fromCharCode(f, j)
} else {
c[g++] = String.fromCharCode(f, j, n)
}
}
} while (b < a.length);k = c.join('');
return k
}
function utf8_from_str(s) {
for(var i=0, enc = encodeURIComponent(s), a = []; i < enc.length;) {
if(enc[i] === '%') {
a.push(parseInt(enc.substr(i+1, 2), 16))
i += 3
} else {
a.push(enc.charCodeAt(i++))
}
}
return a
}
function utf8_to_str(a) {
for(var i=0, s=''; i<a.length; i++) {
var h = a[i].toString(16)
if(h.length < 2) h = '0' + h
s += '%' + h
}
return decodeURIComponent(s)
}
The js function above just tries to convert into utf-8 but there are still non-recognised characters in the resulting json.
The API response I'm trying to decode is
I:Qc[j~O~_]S6gMWNougj~OVhr>|_]O5jZyqjXN;NoZ}SYl~TYN}SnNxNp}{griuiM[p_XN;Nn5}RYhzRoZ9RV~Nn|nYLK5f]W6_LZnTnNRn99RY^~TYJnQHOYiLK5_XN;NpSGNn|nWpqVZ~N;No^|SRnQHOIf]W:NotnYJJlXp>RYJJnQHOff]GLf]_qNotnTYN|RhnQHOG_LW~_]SNotnSYZ7RHGIVZ:JYJ[RXZiN[HGJZnNxNqOm_LK~XZVnTnOVRYqHRYF8WXNxNqGZj]GqNotnZ5_XNn|n[]SqV7>p_[WuiL}qNotnZ7qz_7}qNJ_mg\qxjXGX_]Su_L[z^7ZnQHOH_\WNotnR~NxNpOmiLmNotnRnNxNqS}WsVnTnN~QIV6R~NxNp}{iKSujrZnTnN}SX|8RIFnQHORg8WYf]uqV\S~_]RnTnN|QoVnQHO__\K~Vs[ugMVnTnN}TY^7Nn|nf]SY^\6qY\KugLqz_5>~W]mqg]G5NotnYr=nQHOG[p5nTnNpRn|6SoFxSIF|Nn|nV]_mf\}m^r}qW]K6f]W:NotnOIVTH||RoVnQHOugp_{hr[ogL>i]OqNotnYr=nQHOR^]S5[MOmgsSr_]OX_\SJ^]WqY\>ziLm__\K~NotnV][sNIN|RYNnQHOR^]S5[MOmgsSr_]O\^\}6_XN;NnV}QIh8RH|6RIFnQHOuh5}uh8Wq_J_{hqSmgLZnTnOTg~NxNp}uh8WNou<Nrm~_\^nTnN{ioJ{hMO{hL[~iLqqh~>VRYqHRYF8WX>xf]S5h~O>QHOIg7:5^\S5h~N;j~Othr[rNotnQ8^}Q8G~g8GqhsWu_]R{ZIJ:VoJ|S5Z{hL[~h7>zh~>rf\[x_MR{Y8_qhs_u_]hnkX|nZLm{iL>[rqp_\>Nou<Nrm~_\^nTnN{ioJ{hMO{hL[~iLqqh~>VRYqHRYF8WX>|fL>5g8S7f\Wqg8RnkX|n[]GshrKp_Z}ugryLg8Oq^7}{h8[~_]RnTsxn_s[z^8Wug79nTnOofLKz_7[Yi\O^8OuhMWug79nQHOxf\:wiL[9iHN;NqGx_\K_XG[hLi~^\WqNs5xNq[|_8Om_L[Rf\:w[MOmgsSm^8Wug7:Nou<Nr_6grS5f\>zNotn^7mmgriqZ8[nh7S~f]G5f\>zNn|ngLqzf8WqjMVnTnOVgL[mh7Zl[]GshrKp_XO>QHO[hLi~^\WqYLqzf5qzir[iL6qgsWGgrKxj]Suh~N;j~Ori\:oiLq{gnN;NrSt^\:s_[S6^sSohrq|iLq{gnNxNr}ugry5_]m5NotnZL}q^]SqNK[|_8Om_LZnkX|n[]GshrKp_Z}ugryIg76|^]Om^r}qh~N;j~Ori\:oiLq{gnN;NrSt^\:s_[S6^sSohrq|iLq{gnNxNr}ugry5_]m5NotnZL}q^]SqNK[|_8Om_LZnk]6ikVBB

Decode encripted/base64 string

I am working on a project where I need to decode the following string:
I:Qc[j~O~_]S6gMWNougj~OVhr>|_]O5jZyqjXN;NoZ}SYl~TYN}SnNxNp}{griuiM[p_XN;Nn5}RYhzRoZ9RV~Nn|nYLK5f]W6_LZnTnNRn99RY^~TYJnQHOYiLK5_XN;NpSGNn|nWpqVZ~N;No^|SRnQHOIf]W:NotnYJJlXp>RYJJnQHOff]GLf]_qNotnTYN|RhnQHOG_LW~_]SNotnSYZ7RHGIVZ:JYJ[RXZiN[HGJZnNxNqOm_LK~XZVnTnOVRYqHRYF8WXNxNqGZj]GqNotnZ5_XNn|n[]SqV7>p_[WuiL}qNotnZ7qz_7}qNJ_mg\qxjXGX_]Su_L[z^7ZnQHOH_\WNotnR~NxNpOmiLmNotnRnNxNqS}WsVnTnN~QIV6R~NxNp}{iKSujrZnTnN}SX|8RIFnQHORg8WYf]uqV\S~_]RnTnN|QoVnQHO__\K~Vs[ugMVnTnN}TY^7Nn|nf]SY^\6qY\KugLqz_5>~W]mqg]G5NotnYr=nQHOG[p5nTnNpRn|6SoFxSIF|Nn|nV]_mf\}m^r}qW]K6f]W:NotnOIVTH||RoVnQHOugp_{hr[ogL>i]OqNotnYr=nQHOR^]S5[MOmgsSr_]OX_\SJ^]WqY\>ziLm__\K~NotnV][sNIN|RYNnQHOR^]S5[MOmgsSr_]O\^\}6_XN;NnV}QIh8RH|6RIFnQHOuh5}uh8Wq_J_{hqSmgLZnTnOTg~NxNp}uh8WNou<Nrm~_\^nTnN{ioJ{hMO{hL[~iLqqh~>VRYqHRYF8WX>xf]S5h~O>QHOIg7:5^\S5h~N;j~Othr[rNotnQ8^}Q8G~g8GqhsWu_]R{ZIJ:VoJ|S5Z{hL[~h7>zh~>rf\[x_MR{Y8_qhs_u_]hnkX|nZLm{iL>[rqp_\>Nou<Nrm~_\^nTnN{ioJ{hMO{hL[~iLqqh~>VRYqHRYF8WX>|fL>5g8S7f\Wqg8RnkX|n[]GshrKp_Z}ugryLg8Oq^7}{h8[~_]RnTsxn_s[z^8Wug79nTnOofLKz_7[Yi\O^8OuhMWug79nQHOxf\:wiL[9iHN;NqGx_\K_XG[hLi~^\WqNs5xNq[|_8Om_L[Rf\:w[MOmgsSm^8Wug7:Nou<Nr_6grS5f\>zNotn^7mmgriqZ8[nh7S~f]G5f\>zNn|ngLqzf8WqjMVnTnOVgL[mh7Zl[]GshrKp_XO>QHO[hLi~^\WqYLqzf5qzir[iL6qgsWGgrKxj]Suh~N;j~Ori\:oiLq{gnN;NrSt^\:s_[S6^sSohrq|iLq{gnNxNr}ugry5_]m5NotnZL}q^]SqNK[|_8Om_LZnkX|n[]GshrKp_Z}ugryIg76|^]Om^r}qh~N;j~Ori\:oiLq{gnN;NrSt^\:s_[S6^sSohrq|iLq{gnNxNr}ugry5_]m5NotnZL}q^]SqNK[|_8Om_LZnk]6ikVBB
I believe I was able to extract the following JavaScript functions that are needed to decode the string:
function handleServerReponse(a) {
if (a.substr(0, 5) == 'I:Qc[') {
var f = 5;
var e = (a.substr(5) + '').split('');
var d = [];
for (var b = e.length - 1; b >= 0; b--) {
d[b] = String.fromCharCode(e[b].charCodeAt(0) - f)
}
a = d.join('');
}
return a
}
function fix_utf8(c) {
var d = []
, a = 0
, b = 0
, e = 0
, f = 0;
while (a < c.length) {
b = c.charCodeAt(a);
if (b < 128) {
d.push(String.fromCharCode(b));
a++
} else {
if (b > 191 && b < 224) {
e = c.charCodeAt(a + 1);
d.push(String.fromCharCode((b & 31) << 6 | e & 63));
a += 2
} else {
e = c.charCodeAt(a + 1);
f = c.charCodeAt(a + 2);
d.push(String.fromCharCode((b & 15) << 12 | (e & 63) << 6 | f & 63));
a += 3
}
}
}
return d.join('')
}
function base64_decode(a) {
var e = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var f, j, n, l, m, h, i, d, b = 0, g = 0, k = '', c = [];
if (!a) {
return a
}
a += '';
do {
l = e.indexOf(a.charAt(b++));
m = e.indexOf(a.charAt(b++));
h = e.indexOf(a.charAt(b++));
i = e.indexOf(a.charAt(b++));
d = l << 18 | m << 12 | h << 6 | i;
f = d >> 16 & 255;
j = d >> 8 & 255;
n = d & 255;
if (h == 64) {
c[g++] = String.fromCharCode(f)
} else {
if (i == 64) {
c[g++] = String.fromCharCode(f, j)
} else {
c[g++] = String.fromCharCode(f, j, n)
}
}
} while (b < a.length);k = c.join('');
return k
}
function utf8_from_str(s) {
for(var i=0, enc = encodeURIComponent(s), a = []; i < enc.length;) {
if(enc[i] === '%') {
a.push(parseInt(enc.substr(i+1, 2), 16))
i += 3
} else {
a.push(enc.charCodeAt(i++))
}
}
return a
}
function utf8_to_str(a) {
for(var i=0, s=''; i<a.length; i++) {
var h = a[i].toString(16)
if(h.length < 2) h = '0' + h
s += '%' + h
}
return decodeURIComponent(s)
}
After different attemps/combinations this is how I am using the code:
var c = handleServerReponse('encoded string above');
c = base64_decode(c);
c = utf8_from_str(c);
c = utf8_to_str(c);
c = fix_utf8(c);
And this is the result I am getting. As you can notice, it seems to be a JSON string but is not decoded properly. Any hints on how I can decode it properly?
{"resultHȔ뜙\힒ٞHLMNM苈㛛隝YHLLMˌ펌C""¤ƗF燖FR#⠈蠄؈䄈ɍхє訉
谉%AL計؀Ӣ,"City":"LA JOLLA","ZipFive":"9201ȋٙ霒#⣓Sc4䄄TĔt傄E""¥&F$䂣⥃䣓tR"¥G熒#⥴e""¥W6T6憕F熆R#⥶榶ƒf層ቕͥᕹ픈ɉ䈎茈눐蝚#⣢"¥7gB#⣢ÃS2"¤ƷE6禒#⣓Ró"¤ƷE6禔
ɕ̈舀萈ɥᲂuilt":"1966","isS﹓憖洷$W斗B#⤦⢂$dң⢃"ÓcÃ"¤fᅉᕕŕ呤計и,024","inForeclo]\鈎蓛ȋ㘜ݕ蛜ٙ\䙴FFT�ᥑr":"Aug 2012","LastTransferXǖR#⢃ósÓ"¦紆緆VDf祶ƒ#⤦⢂$Ɨ7D詬顉梺"/v1/properties/P19B107E/lists"},"Cont`ݜȎ陈݌Kܜ뜙\횙\˔NP쌍ыܙ\웛싙ꖆG2䷦W'f旲'҂%淆噥ៈꜙb#⢷c燦熗'F旲僓䣓tR熆熷7fᕽ̉䰉U]Ʌᕱ幭퉕�͕ɕ̈鬉镹푥�艍ᅹ핍Ҙܚ\[ۈ눛淆W炣⥆ƅe UpgraH圙ܘYS浇&綖7F涤詬陕鍑ﮢ:"changeSubscriptkۈ눛[ꝙ^X\و\ܘYH圙ܘFTƖ洖禕ѵ幑酱卥̈鬉鞣tion":"chc陔ݘ옜ꜝ[ۈ눛[ꝙ^X\و\ܘYH圙ܘYS[ꐛۜ\蘛\Ȏ�F涢#⦶湝单鍍ɥQ彸谉᥹푕ᐈ艁ᕅ͔ᕁ퉅ᔉ嵵䀀

Understanding complicated javascript password algorithm

this is a javascript exercise, I need to know what is the correct password.
Can you understand it? it drives my nuts!
Do I need to compare the value against some generated bytecode?
I think when the right password guessed "Congratz!" messages will pop.
<script type="text/javascript">
</script>
Password: <input /><br />
<button>Check</button>
<script id="urchin">
(function() {
var h = [
function() {alert("booo")},
function() {alert(":(")},
function() {alert("Congratz!")},
function() {alert("almost there")},
function() {alert("alert(b[a]);")},
function() {alert("nahh")},
function() {alert("not even close")}
]
var g = function(d) {
var a, f, e, g, k, b = [];
for(a = 0;256 > a;a++) {
b[a] = a
}
f = "click"
e = 0;
d = "input";
g = document[("getElementsByTagName")]("input")["0"][("value")];
for(a = 0;256 > a;a++) {
e = (e + b[a] + f.charCodeAt(a % f[("length")])) % 256, b[a] ^= b[e], b[e] ^= b[a], b[a] ^= b[e]
}
a = e = 0;
f = "";
for(k = a;k < g.length;k += 2) {
a = (a + 1) % 256
e = (e + b[a]) % 256
b[a] ^= b[e]
b[e] ^= b[a]
b[a] ^= b[e]
f += String[("fromCharCode")](parseInt(g[("substr")](k, 2), 16) ^ b[(b[a] + b[e]) % 256])
}
a = f["charCodeAt"](f[("charCodeAt")](0) % f.length) % 6;
f != d + 256 && 2 == a && a++;
h[a]()
}
var d = document[("getElementsByTagName")]("button")["0"];
typeof d.addEventListener != typeof g ? d.attachEvent("onclick", g) : d[("addEventListener")]("click", g, !0);
d = document[("getElementById")]("urchin");
d[("parentNode")].removeChild(d);
c = function() {}
})();
</script>
The correct password is 956918b1820bc657.
The crackme is essentially RC4.
The following initializes the RC4 key table, with the key click, storing the result in b:
var a, f, e, g, k, b = [];
for(a = 0;256 > a;a++) {
b[a] = a
}
f = "click"
e = 0;
d = "input";
g = document[("getElementsByTagName")]("input")["0"][("value")];
for(a = 0;256 > a;a++) {
e = (e + b[a] + f.charCodeAt(a % f[("length")])) % 256, b[a] ^= b[e], b[e] ^= b[a], b[a] ^= b[e]
}
Encryption/decryption happens next using b, after converting the input from hex, storing the result in f:
a = e = 0;
f = "";
for(k = a;k < g.length;k += 2) {
a = (a + 1) % 256
e = (e + b[a]) % 256
b[a] ^= b[e]
b[e] ^= b[a]
b[a] ^= b[e]
f += String[("fromCharCode")](parseInt(g.substr(k, 2), 16) ^ b[(b[a] + b[e]) % 256])
}
Finally the decrypted string is compared with input256. a is just a checksum.
To reverse this process, just encrypt input256 using rc4, then convert it to hex.
You're welcome to post this to crackmes.de and crackmes.us, and cite where it came from.

Fastest general purpose Levenshtein Javascript implementation

I am looking for a good general purpose Levenshtein implementation in Javascript. It must be fast and be useful for short and long strings. It should also be used many times (hence the caching). The most important thing is that it calculates a plain simple Levenshtein distance. I came up with this:
var levenshtein = (function() {
var row2 = [];
return function(s1, s2) {
if (s1 === s2) {
return 0;
} else {
var s1_len = s1.length, s2_len = s2.length;
if (s1_len && s2_len) {
var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
while (i1 < s1_len)
row[i1] = ++i1;
while (i2 < s2_len) {
c2 = s2.charCodeAt(i2);
a = i2;
++i2;
b = i2;
for (i1 = 0; i1 < s1_len; ++i1) {
c = a + (s1.charCodeAt(i1) === c2 ? 0 : 1);
a = row[i1];
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
row[i1] = b;
}
}
return b;
} else {
return s1_len + s2_len;
}
}
};
})();
Now I have two questions:
Can this be faster? I know by writing out the first iteration of each loop one can gain about 20%.
Is this code well written to serve as general purpose code, to be used in a library for instance?
We had a competition for fun at work about making the fastest levenshtein implementation and I came up with a faster one. First of all, I must say that it was not easy to beat your solution which was the fastest to find "out there". :)
This is tested with node.js and it my benchmarks results indicates that this implementation is ~15% faster on small texts (random words size 2-10 characters) and over twice as fast on longer texts (with lengths 30+ containing random characters)
Note: I removed array caching of all implementations
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) {
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== k) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== k) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== k) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== k) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== s.charCodeAt(y)) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
On longer texts it will get almost up to 3 times the speed of your implementation if it initially cache the inner loop's s.charCodeAt(y) in an Uint32Array. Longer texts also seemed to benefit from using a Uint16Array as a the distance cost array. Here is the code for that solution
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h;
var p = new Uint16Array(n);
var u = new Uint32Array(n);
for (y = 0; y < n;) {
u[y] = s.charCodeAt(y);
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== u[y]) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== u[y]) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== u[y]) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== u[y]) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== u[y]) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
All benchmark results is from my tests and test-data might be different with your test-data.
The main 2 difference in this solution than to yours (and some other fast ones) I think is
Not always do compare of the characters in the inner loop if not necessary.
Sort of "Loop unrolling" in the outer loop doing 4 rows at a time in the levenshtein "matrix". This was a major performance win.
http://jsperf.com/levenshtein-distance/24
I will put this solution on github when I find the time :)
Update:
Finally, I put the solution on github
https://github.com/gustf/js-levenshtein. Its a bit modified/optimized but it is the same base algorithm.

Categories

Resources