javascriptencodingdecoding

deduce some matching ENCODE function from existing DECODE function


in some web project i found some DECODE function in javascript.
that is to kind of decrypt some obfuscated string.

i lost the source code of the matching counterpart - the ENCODE function.
and i just don't get how to deduce it from the decoding logic.

/// decrypt helper function
function decryptCharcode(n, start, end, offset) {
    n = n + offset;
    if (offset > 0 && n > end) {
        n = start + (n - end - 1);
    } else if (offset < 0 && n < start) {
        n = end - (start - n - 1);
    }
    return String.fromCharCode(n);
}

/// decrypt string
function decryptString(enc, offset) {
    var dec = "";
    var len = enc.length;
    for(var i=0; i < len; i++) {
        var n = enc.charCodeAt(i);
        if (n >= 0x2B && n <= 0x3A) {
            dec += decryptCharcode(n, 0x2B, 0x3A, offset); // 0-9 . , - + / :
        } else if (n >= 0x40 && n <= 0x5A) {
            dec += decryptCharcode(n, 0x40, 0x5A, offset); // A-Z @
        } else if (n >= 0x61 && n <= 0x7A) {
            dec += decryptCharcode(n, 0x61, 0x7A, offset); // a-z
        } else {
            dec += enc.charAt(i);
        }
    }
    return dec;
}

/// the main function
function decodeMyString(s) {
    console.log( decryptString(s, -3) );
}

in the code there is "decodeMyString".
and i can't figure out how to code the counterpart "encodeMyString".

i have searched all over the web. the "decoding" actually was generated by TYPO3 CMS as some functin called "linkTo_UnCryptMailto". but i wasn't able to find out how it's doing the "encoding".


Solution

  • It's a rotation aka Caesar cipher. With the offset of -3, "a" always comes out as "x", "b" as "y", "c" as "z", "d" as "a", and so on.

    Your "encrypt" function could be just the reverse offset of your "decrypt":

    function encodeMyString(s) {
        console.log( decryptString(s, 3) );
    }
    

    Demonstration:

    /// decrypt helper function
    function decryptCharcode(n, start, end, offset) {
        n = n + offset;
        if (offset > 0 && n > end) {
            n = start + (n - end - 1);
        } else if (offset < 0 && n < start) {
            n = end - (start - n - 1);
        }
        return String.fromCharCode(n);
    }
    
    /// decrypt string
    function decryptString(enc, offset) {
        var dec = "";
        var len = enc.length;
        for(var i=0; i < len; i++) {
            var n = enc.charCodeAt(i);
            if (n >= 0x2B && n <= 0x3A) {
                dec += decryptCharcode(n, 0x2B, 0x3A, offset); // 0-9 . , - + / :
            } else if (n >= 0x40 && n <= 0x5A) {
                dec += decryptCharcode(n, 0x40, 0x5A, offset); // A-Z @
            } else if (n >= 0x61 && n <= 0x7A) {
                dec += decryptCharcode(n, 0x61, 0x7A, offset); // a-z
            } else {
                dec += enc.charAt(i);
            }
        }
        return dec;
    }
    
    function decodeMyString(s) {
        return decryptString(s, -3);
    }
    
    function encodeMyString(s) {
        return decryptString(s, 3);
    }
    
    
    let x = "this is not a secure cipher";
    console.log("original: ",x);
    let y = encodeMyString(x);
    console.log("encoded: ", y);
    let z = decodeMyString(y);
    console.log("decoded: ", z);