mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-20 23:06:16 -04:00
Add Bacon cipher decoding
This commit is contained in:
parent
8148c1a8a8
commit
77b098c5fe
5 changed files with 393 additions and 0 deletions
|
@ -85,6 +85,7 @@
|
|||
"Vigenère Decode",
|
||||
"To Morse Code",
|
||||
"From Morse Code",
|
||||
"Bacon Cipher Decode",
|
||||
"Bifid Cipher Encode",
|
||||
"Bifid Cipher Decode",
|
||||
"Affine Cipher Encode",
|
||||
|
|
37
src/core/lib/Bacon.mjs
Normal file
37
src/core/lib/Bacon.mjs
Normal file
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Bacon resources.
|
||||
*
|
||||
* @author Karsten Silkenbäumer [kassi@users.noreply.github.com]
|
||||
* @copyright Karsten Silkenbäumer 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Bacon definitions.
|
||||
*/
|
||||
|
||||
export const BACON_ALPHABET_REDUCED = "ABCDEFGHIKLMNOPQRSTUWXYZ";
|
||||
export const BACON_ALPHABET_COMPLETE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
export const BACON_TRANSLATION_01 = "0/1";
|
||||
export const BACON_TRANSLATION_AB = "A/B";
|
||||
export const BACON_TRANSLATION_CASE = "Case";
|
||||
export const BACON_TRANSLATION_AMNZ = "A-M/N-Z first letter";
|
||||
export const BACON_TRANSLATIONS = [
|
||||
BACON_TRANSLATION_01,
|
||||
BACON_TRANSLATION_AB,
|
||||
BACON_TRANSLATION_CASE,
|
||||
BACON_TRANSLATION_AMNZ,
|
||||
];
|
||||
export const BACON_CLEARER_MAP = {
|
||||
[BACON_TRANSLATIONS[0]]: /[^01]/g,
|
||||
[BACON_TRANSLATIONS[1]]: /[^ABab]/g,
|
||||
[BACON_TRANSLATIONS[2]]: /[^A-Za-z]/g,
|
||||
};
|
||||
export const BACON_NORMALIZE_MAP = {
|
||||
[BACON_TRANSLATIONS[1]]: {
|
||||
"A": "0",
|
||||
"B": "1",
|
||||
"a": "0",
|
||||
"b": "1"
|
||||
},
|
||||
};
|
108
src/core/operations/BaconCipherDecode.mjs
Normal file
108
src/core/operations/BaconCipherDecode.mjs
Normal file
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* BaconCipher operation.
|
||||
*
|
||||
* @author kassi [kassi@users.noreply.github.com]
|
||||
* @copyright Karsten Silkenbäumer 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import {
|
||||
BACON_ALPHABET_REDUCED, BACON_ALPHABET_COMPLETE,
|
||||
BACON_TRANSLATION_CASE, BACON_TRANSLATION_AMNZ, BACON_TRANSLATIONS, BACON_CLEARER_MAP, BACON_NORMALIZE_MAP
|
||||
} from "../lib/Bacon";
|
||||
|
||||
/**
|
||||
* BaconCipherDecode operation
|
||||
*/
|
||||
class BaconCipherDecode extends Operation {
|
||||
/**
|
||||
* BaconCipherDecode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Bacon Cipher Decode";
|
||||
this.module = "Default";
|
||||
this.description = "Bacon's cipher or the Baconian cipher is a method of steganography(a method of hiding a secret message as opposed to just a cipher) devised by Francis Bacon in 1605.[1][2][3] A message is concealed in the presentation of text, rather than its content.";
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/Bacon%27s_cipher";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Alphabet",
|
||||
"type": "option",
|
||||
"value": [BACON_ALPHABET_REDUCED, BACON_ALPHABET_COMPLETE]
|
||||
},
|
||||
{
|
||||
"name": "Translation",
|
||||
"type": "option",
|
||||
"value": BACON_TRANSLATIONS
|
||||
},
|
||||
{
|
||||
"name": "Invert Translation",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} input
|
||||
* @param {Object[]} args
|
||||
* @returns {String}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [alphabet, translation, invert] = args;
|
||||
// split text into groups of 5 characters
|
||||
|
||||
// remove invalid characters
|
||||
input = input.replace(BACON_CLEARER_MAP[translation], "");
|
||||
// normalize to unique alphabet
|
||||
if (BACON_NORMALIZE_MAP[translation] !== undefined) {
|
||||
input = input.replace(/./g, function (c) {
|
||||
return BACON_NORMALIZE_MAP[translation][c];
|
||||
});
|
||||
} else if (translation === BACON_TRANSLATION_CASE) {
|
||||
const codeA = "A".charCodeAt(0);
|
||||
const codeZ = "Z".charCodeAt(0);
|
||||
input = input.replace(/./g, function (c) {
|
||||
const code = c.charCodeAt(0);
|
||||
if (code >= codeA && code <= codeZ) {
|
||||
return "1";
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
});
|
||||
} else if (translation === BACON_TRANSLATION_AMNZ) {
|
||||
const words = input.split(" ");
|
||||
const letters = words.map(function (e) {
|
||||
const code = e[0].toUpperCase().charCodeAt(0);
|
||||
return code >= "N".charCodeAt(0) ? "1" : "0";
|
||||
});
|
||||
input = letters.join("");
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
input = input.replace(/./g, function (c) {
|
||||
return {
|
||||
"0": "1",
|
||||
"1": "0"
|
||||
}[c];
|
||||
});
|
||||
}
|
||||
|
||||
// group into 5
|
||||
const inputArray = input.match(/(.{5})/g) || [];
|
||||
|
||||
let output = "";
|
||||
for (let index = 0; index < inputArray.length; index++) {
|
||||
const code = inputArray[index];
|
||||
const number = parseInt(code, 2);
|
||||
output += number < alphabet.length ? alphabet[number] : "?";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
export default BaconCipherDecode;
|
|
@ -26,6 +26,7 @@ global.ENVIRONMENT_IS_WEB = function() {
|
|||
import TestRegister from "./TestRegister";
|
||||
import "./tests/BCD";
|
||||
import "./tests/BSON";
|
||||
import "./tests/BaconCipher";
|
||||
import "./tests/Base58";
|
||||
import "./tests/Base64";
|
||||
import "./tests/Base62";
|
||||
|
|
246
tests/operations/tests/BaconCipher.mjs
Normal file
246
tests/operations/tests/BaconCipher.mjs
Normal file
|
@ -0,0 +1,246 @@
|
|||
/**
|
||||
* BaconCipher tests.
|
||||
*
|
||||
* @author Karsten Silkenbäumer [kassi@users.noreply.github.com]
|
||||
* @copyright Karsten Silkenbäumer 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../TestRegister";
|
||||
import { BACON_ALPHABET_REDUCED, BACON_ALPHABET_COMPLETE, BACON_TRANSLATIONS } from "../../../src/core/lib/Bacon";
|
||||
|
||||
const alphabets = [BACON_ALPHABET_REDUCED, BACON_ALPHABET_COMPLETE];
|
||||
const translations = BACON_TRANSLATIONS;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Bacon Decode: no input",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[0], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet 0/1",
|
||||
input: "00011 00100 00010 01101 00011 01000 01100 00110 00001 00000 00010 01101 01100 10100 01101 10000 01001 10001",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[0], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet 0/1 inverse",
|
||||
input: "11100 11011 11101 10010 11100 10111 10011 11001 11110 11111 11101 10010 10011 01011 10010 01111 10110 01110",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[0], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet A/B lower case",
|
||||
input: "aaabb aabaa aaaba abbab aaabb abaaa abbaa aabba aaaab aaaaa aaaba abbab abbaa babaa abbab baaaa abaab baaab",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[1], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet A/B lower case inverse",
|
||||
input: "bbbaa bbabb bbbab baaba bbbaa babbb baabb bbaab bbbba bbbbb bbbab baaba baabb ababb baaba abbbb babba abbba",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[1], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet A/B upper case",
|
||||
input: "AAABB AABAA AAABA ABBAB AAABB ABAAA ABBAA AABBA AAAAB AAAAA AAABA ABBAB ABBAA BABAA ABBAB BAAAA ABAAB BAAAB",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[1], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet A/B upper case inverse",
|
||||
input: "BBBAA BBABB BBBAB BAABA BBBAA BABBB BAABB BBAAB BBBBA BBBBB BBBAB BAABA BAABB ABABB BAABA ABBBB BABBA ABBBA",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[1], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet case code",
|
||||
input: "thiS IsaN exampLe oF ThE bacON cIpher WIth upPPercasE letters tRanSLaTiNG to OnEs anD LoWErcase To zERoes. KS",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[2], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet case code inverse",
|
||||
input: "THIs iS An EXAMPlE Of tHe BACon CiPHER wiTH UPppERCASe LETTERS TrANslAtIng TO oNeS ANd lOweRCASE tO ZerOES. ks",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[2], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet case code",
|
||||
input: "A little example of the Bacon Cipher to be decoded. It is a working example and shorter than my others, but it anyways works tremendously. And just that's important, correct?",
|
||||
expectedOutput: "DECODE",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[3], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: reduced alphabet case code inverse",
|
||||
input: "Well, there's now another example which will be not only strange to read but sound weird for everyone not knowing what the thing is about. Nevertheless, works great out of the box.",
|
||||
expectedOutput: "DECODE",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[0], translations[3], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet 0/1",
|
||||
input: "00011 00100 00010 01110 00011 01000 01101 00110 00001 00000 00010 01110 01101 10110 01110 10001 01010 10010",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[0], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet 0/1 inverse",
|
||||
input: "11100 11011 11101 10001 11100 10111 10010 11001 11110 11111 11101 10001 10010 01001 10001 01110 10101 01101",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[0], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet A/B lower case",
|
||||
input: "aaabb aabaa aaaba abbba aaabb abaaa abbab aabba aaaab aaaaa aaaba abbba abbab babba abbba baaab ababa baaba",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[1], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet A/B lower case inverse",
|
||||
input: "bbbaa bbabb bbbab baaab bbbaa babbb baaba bbaab bbbba bbbbb bbbab baaab baaba abaab baaab abbba babab abbab",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[1], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet A/B upper case",
|
||||
input: "AAABB AABAA AAABA ABBBA AAABB ABAAA ABBAB AABBA AAAAB AAAAA AAABA ABBBA ABBAB BABBA ABBBA BAAAB ABABA BAABA",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[1], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet A/B upper case inverse",
|
||||
input: "BBBAA BBABB BBBAB BAAAB BBBAA BABBB BAABA BBAAB BBBBA BBBBB BBBAB BAAAB BAABA ABAAB BAAAB ABBBA BABAB ABBAB",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[1], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet case code",
|
||||
input: "thiS IsaN exampLe oF THe bacON cIpher WItH upPPercasE letters tRanSLAtiNG tO OnES anD LOwErcaSe To ZeRoeS. kS",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[2], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet case code inverse",
|
||||
input: "THIs iSAn EXAMPlE Of thE BACon CiPHER wiTh UPppERCASe LETTERS TrANslaTIng To zEroES and LoWERcAsE tO oNEs. Ks",
|
||||
expectedOutput: "DECODINGBACONWORKS",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[2], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet case code",
|
||||
input: "A little example of the Bacon Cipher to be decoded. It is a working example and shorter than the first, but it anyways works tremendously. And just that's important, correct?",
|
||||
expectedOutput: "DECODE",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[3], false]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Bacon Decode: complete alphabet case code inverse",
|
||||
input: "Well, there's now another example which will be not only strange to read but sound weird for everyone knowing nothing what the thing is about. Nevertheless, works great out of the box.",
|
||||
expectedOutput: "DECODE",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Bacon Cipher Decode",
|
||||
args: [alphabets[1], translations[3], true]
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
Loading…
Add table
Add a link
Reference in a new issue