diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 4fac84c9..e9fe3399 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -86,6 +86,8 @@ "Bifid Cipher Decode", "Affine Cipher Encode", "Affine Cipher Decode", + "A1Z26 Cipher Encode", + "A1Z26 Cipher Decode", "Atbash Cipher", "Substitute", "Derive PBKDF2 key", diff --git a/src/core/operations/A1Z26CipherDecode.mjs b/src/core/operations/A1Z26CipherDecode.mjs new file mode 100644 index 00000000..2a9f9ce7 --- /dev/null +++ b/src/core/operations/A1Z26CipherDecode.mjs @@ -0,0 +1,63 @@ +/** + * @author Jarmo van Lenthe [github.com/jarmovanlenthe] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; +import OperationError from "../errors/OperationError"; + +/** + * A1Z26 Cipher Decode operation + */ +class A1Z26CipherDecode extends Operation { + + /** + * A1Z26CipherDecode constructor + */ + constructor() { + super(); + + this.name = "A1Z26 Cipher Decode"; + this.module = "Ciphers"; + this.description = "Converts alphabet order numbers into their corresponding alphabet character.

e.g. 1 becomes a and 2 becomes b."; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Delimiter", + type: "option", + value: DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"); + + if (input.length === 0) { + return []; + } + + const bites = input.split(delim); + let latin1 = ""; + for (let i = 0; i < bites.length; i++) { + if (bites[i] < 1 || bites[i] > 26) { + throw new OperationError("Error: all numbers must be between 1 and 26."); + } + latin1 += Utils.chr(parseInt(bites[i], 10) + 96); + } + return latin1; + } + +} + +export default A1Z26CipherDecode; diff --git a/src/core/operations/A1Z26CipherEncode.mjs b/src/core/operations/A1Z26CipherEncode.mjs new file mode 100644 index 00000000..d1202d83 --- /dev/null +++ b/src/core/operations/A1Z26CipherEncode.mjs @@ -0,0 +1,61 @@ +/** + * @author Jarmo van Lenthe [github.com/jarmovanlenthe] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {DELIM_OPTIONS} from "../lib/Delim"; + +/** + * A1Z26 Cipher Encode operation + */ +class A1Z26CipherEncode extends Operation { + + /** + * A1Z26CipherEncode constructor + */ + constructor() { + super(); + + this.name = "A1Z26 Cipher Encode"; + this.module = "Ciphers"; + this.description = "Converts alphabet characters into their corresponding alphabet order number.

e.g. a becomes 1 and b becomes 2.

Non-alphabet characters are dropped."; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Delimiter", + type: "option", + value: DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"); + let output = ""; + + const sanitizedinput = input.toLowerCase(), + charcode = Utils.strToCharcode(sanitizedinput); + + for (let i = 0; i < charcode.length; i++) { + const ordinal = charcode[i] - 96; + + if (ordinal > 0 && ordinal <= 26) { + output += ordinal.toString(10) + delim; + } + } + return output.slice(0, -delim.length); + } + +} + +export default A1Z26CipherEncode; diff --git a/test/tests/operations/Ciphers.mjs b/test/tests/operations/Ciphers.mjs index fdc98a3a..a46f50a9 100644 --- a/test/tests/operations/Ciphers.mjs +++ b/test/tests/operations/Ciphers.mjs @@ -110,6 +110,39 @@ TestRegister.addTests([ } ], }, + { + name: "A1Z26 Encode: normal", + input: "This is the test sentence.", + expectedOutput: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5", + recipeConfig: [ + { + op: "A1Z26 Cipher Encode", + args: ["Space"] + } + ], + }, + { + name: "A1Z26 Decode: normal", + input: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5", + expectedOutput: "thisisthetestsentence", + recipeConfig: [ + { + op: "A1Z26 Cipher Decode", + args: ["Space"] + } + ], + }, + { + name: "A1Z26 Decode: error", + input: "20 8 9 27", + expectedOutput: "Error: all numbers must be between 1 and 26.", + recipeConfig: [ + { + op: "A1Z26 Cipher Decode", + args: ["Space"] + } + ], + }, { name: "Atbash: no input", input: "",