Simplest way to obfuscate and deobfuscate a string in JavaScript

50,754

Solution 1

You can use btoa() and atob(). btoa() is like base64_encode() and atob() like base64_decode().

Here is an example:

btoa('Some text'); // U29tZSB0ZXh0
atob('U29tZSB0ZXh0'); // Some text

Keep in mind that this is not a secure way to keep secrets. Base64 is a binary-to-text encoding scheme that represents binary data in an ASCII string format by translating it into a radix-64 representation.

Solution 2

It's worth noting that

(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]

evaluates to the string "fail" without ever looking like a string. Seriously, enter it into node and be amazed. You can spell anything in JavaScript by being crazy.

Solution 3

I'm obviously too late for an answer, but I was just working on another solution for the problem and base64 seemed to be to weak.

It works like this:

"abc;123!".obfs(13) // => "nopH>?@."
"nopH>?@.".defs(13) // => "abc;123!"

Code:

/**
 * Obfuscate a plaintext string with a simple rotation algorithm similar to
 * the rot13 cipher.
 * @param  {[type]} key rotation index between 0 and n
 * @param  {Number} n   maximum char that will be affected by the algorithm
 * @return {[type]}     obfuscated string
 */
String.prototype.obfs = function(key, n = 126) {
  // return String itself if the given parameters are invalid
  if (!(typeof(key) === 'number' && key % 1 === 0)
    || !(typeof(key) === 'number' && key % 1 === 0)) {
    return this.toString();
  }

  var chars = this.toString().split('');

  for (var i = 0; i < chars.length; i++) {
    var c = chars[i].charCodeAt(0);

    if (c <= n) {
      chars[i] = String.fromCharCode((chars[i].charCodeAt(0) + key) % n);
    }
  }

  return chars.join('');
};

/**
 * De-obfuscate an obfuscated string with the method above.
 * @param  {[type]} key rotation index between 0 and n
 * @param  {Number} n   same number that was used for obfuscation
 * @return {[type]}     plaintext string
 */
String.prototype.defs = function(key, n = 126) {
  // return String itself if the given parameters are invalid
  if (!(typeof(key) === 'number' && key % 1 === 0)
    || !(typeof(key) === 'number' && key % 1 === 0)) {
    return this.toString();
  }

  return this.toString().obfs(n - key);
};
Share:
50,754
Rich Jenks
Author by

Rich Jenks

Updated on July 09, 2022

Comments

  • Rich Jenks
    Rich Jenks almost 2 years

    I'm looking for a way to obfuscate and deobfuscate a string in JavaScript; by which I mean encryption and decryption when security is not an issue. Ideally something native to JS (like base64_encode() and base64_decode() in PHP) to "turn a string into something else and back again" without having to write a function.

    Any suggestions welcome!

  • Rich Jenks
    Rich Jenks over 11 years
    Seems to work in most modern browsers so suits my requirements perfectly. Thank you!
  • UpTheCreek
    UpTheCreek almost 11 years
    Worth noting that the encoded string will be larger than the non-encoded one.
  • Gant Laborde
    Gant Laborde over 6 years
    go into node and break it into its parts. It starts to make some morbid sense.
  • RedSparr0w
    RedSparr0w over 6 years
    Interesting! got it working with most letters! jsfiddle.net/pg07yf87/2 Edit: this site also does it for you jsfuck.com
  • Aniket Suryavanshi
    Aniket Suryavanshi over 6 years
    Cross browser support seems good now. caniuse.com/#search=btoa It's safe to use.
  • ethancrist
    ethancrist about 6 years
    Thank you. I love the use-cases for this.
  • Patrick Roberts
    Patrick Roberts about 6 years
    This code breaks for...in enumeration of strings, don't use this in production.
  • Gan Quan
    Gan Quan over 4 years
    @PatrickRoberts for ... in should always bundle with .hasOwnProperty(). You can also define obfs and defs without modifying String.prototype
  • Patrick Roberts
    Patrick Roberts over 4 years
    @GanQuan that was my point. The answer shouldn't be polluting builtin prototypes at all. The .hasOwnProperty() "good practice" (/s) came about due to the frequency of polluting builtins, not because it's actually made necessary by the language design itself. Because of how common it is for libraries to pollute builtins with arbitrary extensions like this, I think for...in has unfortunately become rarely, if ever, the appropriate choice for enumeration of anything, strings included.
  • Etienne Martin
    Etienne Martin about 4 years
    You have a nice little obfuscator but then it's exposed globally for anyone to see on the String prototype. Kinda beats the purpose.
  • Yetanotherjosh
    Yetanotherjosh about 3 years
    It is very important to note this will fail on strings containing unicode characters that do not belong to the 0-127 range of the ASCII character set, and therefore this function is insufficient for use on user input from almost any modern web app where people might use non-ascii chars. The MDN docs discuss how to deal with this, you must first convert the unicode characters to a byte string.
  • Robby Hoover
    Robby Hoover over 2 years
    Id like to add for anyone looking in the future, btoa and atob are deprecated and are only kept around for legacy web APIs, converting between base 64 encoded strings and binary data should be performed using Buffer.from(str, 'base64') and buf.toString('base64')