function decrypt(ciphertext, password) {
    var v = new Array(2), k = new Array(4), s = "", i;

    for (var i = 0; i < 4; i++) k[i] = Str4ToLong(password.slice(i * 4, (i + 1) * 4));

    ciphertext = unescCtrlCh(ciphertext);
    for (i = 0; i < ciphertext.length; i += 8) {
        v[0] = Str4ToLong(ciphertext.slice(i, i + 4));
        v[1] = Str4ToLong(ciphertext.slice(i + 4, i + 8));
        decode(v, k);
        s += LongToStr4(v[0]) + LongToStr4(v[1]);
    }
    s = s.replace(/\0+$/, '');
    return unescape(s);
}
function decode(v, k) {
    var y = v[0], z = v[1];
    var delta = 0x9E3779B9, sum = delta * 32;

    while (sum != 0) {
        z -= (y << 4 ^ y >>> 5) + y ^ sum + k[sum >>> 11 & 3];
        sum -= delta;
        y -= (z << 4 ^ z >>> 5) + z ^ sum + k[sum & 3];
    }
    v[0] = y; v[1] = z;
}
function Str4ToLong(s) {
    var v = 0;
    for (var i = 0; i < 4; i++) v |= s.charCodeAt(i) << i * 8;
    return isNaN(v) ? 0 : v;
}

function LongToStr4(v) {
    var s = String.fromCharCode(v & 0xFF, v >> 8 & 0xFF, v >> 16 & 0xFF, v >> 24 & 0xFF);
    return s;
}
function unescCtrlCh(str) {
    return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1, -1)); });
}

