mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-23 08:16:17 -04:00
123 lines
3.8 KiB
JavaScript
123 lines
3.8 KiB
JavaScript
/**
|
|
* @author Daniel Temkin [http://danieltemkin.com]
|
|
* @author Thomas Leplus [https://www.leplus.org]
|
|
* @copyright Crown Copyright 2021
|
|
* @license Apache-2.0
|
|
*/
|
|
|
|
import Operation from "../Operation.mjs";
|
|
|
|
/**
|
|
* ROT8000 operation.
|
|
*/
|
|
class ROT8000 extends Operation {
|
|
|
|
/**
|
|
* ROT8000 constructor
|
|
*/
|
|
constructor() {
|
|
super();
|
|
this.name = "ROT8000";
|
|
this.module = "Default";
|
|
this.description = "The simple Caesar-cypher encryption that replaces each Unicode character with the one 0x8000 places forward or back along the alphabet.";
|
|
this.infoURL = "https://rot8000.com/info";
|
|
this.inputType = "string";
|
|
this.outputType = "string";
|
|
this.args = [];
|
|
}
|
|
|
|
/**
|
|
* @param {byteArray} input
|
|
* @param {Object[]} args
|
|
* @returns {byteArray}
|
|
*/
|
|
run(input, args) {
|
|
// Inspired from https://github.com/rottytooth/rot8000/blob/main/rot8000.js
|
|
// these come from the valid-code-point-transitions.json file generated from the c# proj
|
|
// this is done bc: 1) don't trust JS's understanging of surrogate pairs and 2) consistency with original rot8000
|
|
const validCodePoints = {
|
|
"33": true,
|
|
"127": false,
|
|
"161": true,
|
|
"5760": false,
|
|
"5761": true,
|
|
"8192": false,
|
|
"8203": true,
|
|
"8232": false,
|
|
"8234": true,
|
|
"8239": false,
|
|
"8240": true,
|
|
"8287": false,
|
|
"8288": true,
|
|
"12288": false,
|
|
"12289": true,
|
|
"55296": false,
|
|
"57344": true
|
|
};
|
|
const bmpSize = 0x10000;
|
|
const rotList = {}; // the mapping of char to rotated char
|
|
const hiddenBlocks = [];
|
|
let startBlock = 0;
|
|
for (const key in validCodePoints) {
|
|
if (Object.prototype.hasOwnProperty.call(validCodePoints, key)) {
|
|
if (validCodePoints[key] === true)
|
|
hiddenBlocks.push({ start: startBlock, end: parseInt(key, 10) - 1 });
|
|
else
|
|
startBlock = parseInt(key, 10);
|
|
}
|
|
}
|
|
const validIntList = []; // list of all valid chars
|
|
let currValid = false;
|
|
for (let i = 0; i < bmpSize; i++) {
|
|
if (validCodePoints[i] !== undefined) {
|
|
currValid = validCodePoints[i];
|
|
}
|
|
if (currValid) validIntList.push(i);
|
|
}
|
|
const rotateNum = Object.keys(validIntList).length / 2;
|
|
// go through every valid char and find its match
|
|
for (let i = 0; i < validIntList.length; i++) {
|
|
rotList[String.fromCharCode(validIntList[i])] =
|
|
String.fromCharCode(validIntList[(i + rotateNum) % (rotateNum * 2)]);
|
|
}
|
|
let output = "";
|
|
for (let count = 0; count < input.length; count++) {
|
|
// if it is not in the mappings list, just add it directly (no rotation)
|
|
if (rotList[input[count]] === undefined) {
|
|
output += input[count];
|
|
continue;
|
|
}
|
|
// otherwise, rotate it and add it to the string
|
|
output += rotList[input[count]];
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Highlight ROT8000
|
|
*
|
|
* @param {Object[]} pos
|
|
* @param {number} pos[].start
|
|
* @param {number} pos[].end
|
|
* @param {Object[]} args
|
|
* @returns {Object[]} pos
|
|
*/
|
|
highlight(pos, args) {
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Highlight ROT8000 in reverse
|
|
*
|
|
* @param {Object[]} pos
|
|
* @param {number} pos[].start
|
|
* @param {number} pos[].end
|
|
* @param {Object[]} args
|
|
* @returns {Object[]} pos
|
|
*/
|
|
highlightReverse(pos, args) {
|
|
return pos;
|
|
}
|
|
}
|
|
|
|
export default ROT8000;
|