Skip to content

Instantly share code, notes, and snippets.

@nealfennimore
Last active December 28, 2019 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nealfennimore/b2c4a77a93b7a841b338deba195cf16e to your computer and use it in GitHub Desktop.
Save nealfennimore/b2c4a77a93b7a841b338deba195cf16e to your computer and use it in GitHub Desktop.
XOR encryption and decryption
/**
* Convert character string to binary
*
* @param {String} str Character string
* @returns Binary String
*/
function toBinary(str) {
let binary = '';
for (let i = 0, l = str.length; i < l; i++) {
binary += str.codePointAt(i).toString(2).padStart(8, '0');
}
return binary;
}
console.assert(
toBinary('a') === '01100001'
);
console.assert(
toBinary('abc') === '011000010110001001100011'
);
/**
* Convert binary string to character string
*
* @param {String} binary Binary String
* @returns Character String
*/
function toText(binary){
let str = '';
for (let i = 0, l = binary.length / 8; i < l; i++) {
const start = i * 8;
const byte = binary.slice(start, start + 8);
const codePoint = parseInt(byte, 2);
str += String.fromCodePoint(codePoint);
}
return str;
}
console.assert(
toText('01100001') === 'a'
);
console.assert(
toText('011000010110001001100011') === 'abc'
);
/**
* Perform exclusive OR operation
*
* @param {Number|String} a
* @param {Number|String} b
* @returns {Number} 0 or 1
*/
function xor(a, b) {
return +(a !== b);
}
console.assert(
xor(1, 0) === 1
);
console.assert(
xor(0, 1) === 1
);
console.assert(
xor(1, 1) === 0
);
console.assert(
xor(0, 0) === 0
);
/**
* Perform XOR operations on two strings
*
* @param {String} key Key to XOR
* @param {String} text Text to XOR
* @returns {String} XOR'd string
*/
function xorStrings(key, text){
const keyBin = toBinary(key);
const keyLength = keyBin.length;
const textBin = toBinary(text);
const textLength = textBin.length;
let xorText = '';
for (let i = 0; i < textLength; i++) {
const ctElement = textBin[i];
const keyElement = keyBin[i % keyLength];
xorText += xor(ctElement, keyElement).toString();
}
return xorText;
}
console.assert(
xorStrings('a', 'b') === '00000011'
);
console.assert(
xorStrings('b', 'a') === '00000011'
);
console.assert(
xorStrings('abc', 'cba') === '000000100000000000000010'
);
/**
* Encrypt text using key
*
* @param {String} key
* @param {String} clearText
* @returns {String} Encrypted text
*/
function encrypt(key, clearText){
return toText( xorStrings( key, clearText ) );
}
console.assert(
encrypt('a', 'bc') === ''
);
/**
* Decrypt encrypted text using key
*
* @param {String} key
* @param {String} cipherText
* @returns {String} Decrypted text
*/
function decrypt(key, cipherText) {
return toText( xorStrings(key, cipherText) );
}
console.assert(
decrypt( 'key', encrypt( 'key', 'abc' ) ) === 'abc'
);
console.assert(
decrypt('whatever', encrypt('whatever', 'what is this sentence huh')) === 'what is this sentence huh'
);
console.assert(
decrypt('abc', encrypt('abc', 'cba')) === 'cba'
);
console.assert(
decrypt('wrong-key', encrypt('whatever', 'I should not work')) !== 'I should not work'
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment