Last active
December 21, 2024 03:07
-
-
Save sukima/5613286 to your computer and use it in GitHub Desktop.
A Super simple encryption cipher using XOR and Base64 in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 <[email protected]> | |
// | |
// 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); |
Do you have this script in PHP with the functionality of encrypting using random seed? @vanowm
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
This version generates random encrypted string, meaning even when supplied identical text and key, the generated text will always be different every time it's encrypted (there is 1 in 65534^6 chance it might repeat)
This version accepts an optional third parameter "seed". This parameter will be used to randomize the encrypted output. If an empty string used as seed (or any static string) it will generate static (non-random) encryption output. If no seed provided (undefined) a random generated seed of 6 characters will be used. Provided
XORCipher.seed(
nn
)
function can be used to generate random nn long seed. The seed can only contain characters with 1-65535 charcodei.e.
XORCipher.encode("test", "foobar", XORCipher.seed(10));
will encrypt with 10 characters long seedDemo:
https://jsfiddle.net/vanowm/7suyfgo4/