Skip to content

Instantly share code, notes, and snippets.

@sukima
Last active July 18, 2024 14:52
Show Gist options
  • Save sukima/5613286 to your computer and use it in GitHub Desktop.
Save sukima/5613286 to your computer and use it in GitHub Desktop.
A Super simple encryption cipher using XOR and Base64 in JavaScript
// XORCipher - Super simple encryption using XOR and Base64
//
// Depends on [Underscore](http://underscorejs.org/).
//
// As a warning, this is **not** a secure encryption algorythm. It uses a very
// simplistic keystore and will be easy to crack.
//
// The Base64 algorythm is a modification of the one used in phpjs.org
// * http://phpjs.org/functions/base64_encode/
// * http://phpjs.org/functions/base64_decode/
//
// Examples
// --------
//
// XORCipher.encode("test", "foobar"); // => "EgocFhUX"
// XORCipher.decode("test", "EgocFhUX"); // => "foobar"
//
// Copyright © 2013 Devin Weaver <suki@tritarget.org>
//
// This program is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What The Fuck You Want
// To Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
/* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, strict:true,
undef:true, unused:true, curly:true, browser:true, indent:2, maxerr:50 */
/* global _ */
(function(exports) {
"use strict";
var XORCipher = {
encode: function(key, data) {
data = xor_encrypt(key, data);
return b64_encode(data);
},
decode: function(key, data) {
data = b64_decode(data);
return xor_decrypt(key, data);
}
};
var b64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function b64_encode(data) {
var o1, o2, o3, h1, h2, h3, h4, bits, r, i = 0, enc = "";
if (!data) { return data; }
do {
o1 = data[i++];
o2 = data[i++];
o3 = data[i++];
bits = o1 << 16 | o2 << 8 | o3;
h1 = bits >> 18 & 0x3f;
h2 = bits >> 12 & 0x3f;
h3 = bits >> 6 & 0x3f;
h4 = bits & 0x3f;
enc += b64_table.charAt(h1) + b64_table.charAt(h2) + b64_table.charAt(h3) + b64_table.charAt(h4);
} while (i < data.length);
r = data.length % 3;
return (r ? enc.slice(0, r - 3) : enc) + "===".slice(r || 3);
}
function b64_decode(data) {
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, result = [];
if (!data) { return data; }
data += "";
do {
h1 = b64_table.indexOf(data.charAt(i++));
h2 = b64_table.indexOf(data.charAt(i++));
h3 = b64_table.indexOf(data.charAt(i++));
h4 = b64_table.indexOf(data.charAt(i++));
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
o1 = bits >> 16 & 0xff;
o2 = bits >> 8 & 0xff;
o3 = bits & 0xff;
result.push(o1);
if (h3 !== 64) {
result.push(o2);
if (h4 !== 64) {
result.push(o3);
}
}
} while (i < data.length);
return result;
}
function keyCharAt(key, i) {
return key.charCodeAt( Math.floor(i % key.length) );
}
function xor_encrypt(key, data) {
return _.map(data, function(c, i) {
return c.charCodeAt(0) ^ keyCharAt(key, i);
});
}
function xor_decrypt(key, data) {
return _.map(data, function(c, i) {
return String.fromCharCode( c ^ keyCharAt(key, i) );
}).join("");
}
exports.XORCipher = XORCipher;
})(this);
@groupunknown
Copy link

Do you have this script in PHP with the functionality of encrypting using random seed? @vanowm

@ReeganExE
Copy link

Another version that uses a simple hex encode/decode

TypeScript (JavaScript below)
const XORCipher = {
  encode(key: string, plaintext: string) {
    const bin = xor_encrypt(key, plaintext);
    const hex = Array.from(bin, (b) => b.toString(16).padStart(2, '0')).join('');
    return hex;
  },

  decode(key: string, hexString: string) {
    const hexes = hexString.match(/.{2}/g) as string[];
    const bin = Uint8Array.from(hexes, (byte) => parseInt(byte, 16));
    return xor_decrypt(key, bin);
  },
};

function keyCharAt(key: string, i: number) {
  return key.charCodeAt(Math.floor(i % key.length));
}

function xor_encrypt(key: string, plaintext: string) {
  const bin = new Uint8Array(plaintext.length);
  for (let i = 0; i < plaintext.length; i++) {
    bin[i] = plaintext.charCodeAt(i) ^ keyCharAt(key, i);
  }
  return bin;
}

function xor_decrypt(key: string, bin: Uint8Array) {
  return Array.from(bin, (c, i) => String.fromCharCode(c ^ keyCharAt(key, i))).join('');
}

const encoded = XORCipher.encode('the lost key', 'Dep Trai Co Gi Sai');
console.log('Encoded:', encoded);
console.log(XORCipher.decode('the lost key', encoded));
JavaScript Version
const XORCipher = {
  encode (key, plaintext) {
      const bin = xor_encrypt(key, plaintext);
      const hex = Array.from(bin, (b)=>b.toString(16).padStart(2, '0')).join('');
      return hex;
  },
  decode (key, hexString) {
      const hexes = hexString.match(/.{2}/g);
      const bin = Uint8Array.from(hexes, (byte)=>parseInt(byte, 16));
      return xor_decrypt(key, bin);
  }
};

function keyCharAt(key, i) {
  return key.charCodeAt(Math.floor(i % key.length));
}

function xor_encrypt(key, plaintext) {
  const bin = new Uint8Array(plaintext.length);
  for(let i = 0; i < plaintext.length; i++){
      bin[i] = plaintext.charCodeAt(i) ^ keyCharAt(key, i);
  }
  return bin;
}

function xor_decrypt(key, bin) {
  return Array.from(bin, (c, i)=>String.fromCharCode(c ^ keyCharAt(key, i))).join('');
}

const encoded = XORCipher.encode('the lost key', 'Dep Trai Co Gi Sai');
console.log('Encoded:', encoded);
console.log(XORCipher.decode('the lost key', encoded));

Disclaimer: not secure as OP mentioned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment