diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 4f23c0d3..661e0f70 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -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", diff --git a/src/core/operations/BaconCipherDecode.mjs b/src/core/operations/BaconCipherDecode.mjs new file mode 100644 index 00000000..1ed86b4a --- /dev/null +++ b/src/core/operations/BaconCipherDecode.mjs @@ -0,0 +1,136 @@ +/** + * @author kassi [kassi@noreply.com] + * @copyright KS 2018 + * @license Apache-2.0 + */ + +import Operation from '../Operation'; +import OperationError from "../errors/OperationError"; + +/** + * 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': ['ABCDEFGHIKLMNOPQRSTUWXYZ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] + }, + { + 'name': 'Translation', + 'type': 'option', + 'value': ['0/1', 'A/B', 'Case', 'A-M/N-Z'] + }, + { + 'name': 'Invert Translation', + 'type': 'boolean', + 'value': false + } + ]; + } + + /** + * @param {String} input + * @param {Object[]} args + * @returns {String} + */ + run(input, args) { + const [alphabet, translation, invert] = args; + const regexAM = /[A-M]/; + const regexNZ = /[N-Z]/; + // split text into groups of 5 characters + var groups = []; + var group = ""; + + for (let index = 0; index < input.length; index++) { + const char = input[index]; + console.log(char); + + if (char.toLowerCase() != char.toUpperCase()) { + switch (translation) { + case "0/1": + group = group + char; + break; + case "A/B": + if (char == "A") { + group = group + "1"; + } else if (char == "B") { + group = group + "0"; + } + break; + case "Case": + if (char == char.toUpperCase()) { + group = group + "1"; + } else { + group = group + "0"; + } + break; + case "A-M/N-Z": + if (char.match(regexAM)) { + group = group + "1"; + } + else if (char.match(regexNZ)) { + group = group + "0" + } + break; + default: + break; + } + + if (group.length == 5) { + groups.push(group); + group = ""; + } + } + } + + // Padding + if (group.length > 0) { + group = (group + "0000").substr(0, 5); + groups.push(group); + } + + let output = ""; + const byteLen = 5; + for (let index = 0; index < groups.length; index++) { + var group = groups[index]; + if (invert) { + group = group.replace(/[01]/g, function (m) { + return { + '0': '1', + '1': '0' + }[m]; + }); + } + // calculate binary value + var number; + for (let i = 0; i < group.length; i += byteLen) { + number = parseInt(group.substr(i, byteLen), 2); + } + var char; + if (number < alphabet.length) { + char = alphabet[number]; + } else { + char = "?" + } + output += char; + } + return output; + } +} + +export default BaconCipherDecode;