From 2b3968490456d728eaf4a47297e672312d047727 Mon Sep 17 00:00:00 2001 From: Flavio Diez Date: Sun, 26 Jan 2020 19:48:03 +0100 Subject: [PATCH 1/5] Added run method of Rail Fence Cipher encoding --- src/core/config/Categories.json | 1 + src/core/operations/RailFenceCypherDecode.mjs | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/core/operations/RailFenceCypherDecode.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 53ca796d..cc9268fc 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -95,6 +95,7 @@ "Affine Cipher Decode", "A1Z26 Cipher Encode", "A1Z26 Cipher Decode", + "Rail Fence Cipher Decode", "Atbash Cipher", "Substitute", "Derive PBKDF2 key", diff --git a/src/core/operations/RailFenceCypherDecode.mjs b/src/core/operations/RailFenceCypherDecode.mjs new file mode 100644 index 00000000..1c9c67b5 --- /dev/null +++ b/src/core/operations/RailFenceCypherDecode.mjs @@ -0,0 +1,98 @@ +/** + * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Rail Fence Cypher Decode operation + */ +class RailFenceCypherDecode extends Operation { + + /** + * RailFenceCypherDecode constructor + */ + constructor() { + super(); + + this.name = "Rail Fence Cypher Decode"; + this.module = "Ciphers"; + this.description = "Decodes Strings that were created using the Rail fence Cypher provided a key and an offset"; + this.infoURL = "https://en.wikipedia.org/wiki/Rail_fence_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "number", + value: 2 + }, + { + name: "Offset", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [key] = args; + // const [key, offset] = args; + + let cipher = input; + + const rest = cipher.length % key; + + if (rest !== 0) { + cipher = cipher + (" ".repeat(rest)); + } + + const blockLen = cipher.length / key; + + let plaintext = ""; + + for (let i = 0; i < blockLen; i++) { + for (let j = 0; j < key; j++) { + plaintext += cipher[i + (j * blockLen)]; + } + } + + return plaintext; + } + + /** + * Highlight Rail Fence Cypher Decode + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Rail Fence Cypher Decode 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 RailFenceCypherDecode; From ce638de9b1c500ea53589133c1aebb2ad802e965 Mon Sep 17 00:00:00 2001 From: Flavio Diez Date: Mon, 27 Jan 2020 14:43:00 +0100 Subject: [PATCH 2/5] Corrected padding and added error cases --- src/core/operations/RailFenceCypherDecode.mjs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/operations/RailFenceCypherDecode.mjs b/src/core/operations/RailFenceCypherDecode.mjs index 1c9c67b5..20a8a4f2 100644 --- a/src/core/operations/RailFenceCypherDecode.mjs +++ b/src/core/operations/RailFenceCypherDecode.mjs @@ -48,10 +48,16 @@ class RailFenceCypherDecode extends Operation { let cipher = input; + if (key < 2) { + return "Key has to be bigger than 2"; + } else if (key > cipher.length) { + return "Key should be smaller than the cipher's length"; + } + const rest = cipher.length % key; if (rest !== 0) { - cipher = cipher + (" ".repeat(rest)); + cipher = cipher + (" ".repeat(key-rest)); } const blockLen = cipher.length / key; From 3b3034c79ba4783745236edcdaea567c6183faba Mon Sep 17 00:00:00 2001 From: Flavio Diez Date: Mon, 27 Jan 2020 14:43:31 +0100 Subject: [PATCH 3/5] Tests for Rail Cipher Encode --- tests/operations/tests/Ciphers.mjs | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/operations/tests/Ciphers.mjs b/tests/operations/tests/Ciphers.mjs index 62cbaa54..0232a14d 100644 --- a/tests/operations/tests/Ciphers.mjs +++ b/tests/operations/tests/Ciphers.mjs @@ -3,6 +3,7 @@ * * @author Matt C [matt@artemisbot.uk] * @author n1474335 [n1474335@gmail.com] + * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com] * * @copyright Crown Copyright 2018 * @license Apache-2.0 @@ -418,4 +419,37 @@ TestRegister.addTests([ } ], }, + { + name: "Rail Fence Cypher Decode: normal", + input: "Cytgah sTEAto rtn rsligcdsrporpyi H r fWiigo ovn oe", + expectedOutput: "Cryptography is THE Art of Writing or solving codes", + recipeConfig: [ + { + "op": "Rail Fence Cypher Decode", + "args": [2, 0] + } + ], + }, + { + name: "Rail Fence Cypher Decode: key has to be bigger than 2", + input: "Cytgah sTEAto rtn rsligcdsrporpyi H r fWiigo ovn oe", + expectedOutput: "Key has to be bigger than 2", + recipeConfig: [ + { + "op": "Rail Fence Cypher Decode", + "args": [1, 0] + } + ], + }, + { + name: "Rail Fence Cypher Decode: key has to be smaller than input's length", + input: "shortinput", + expectedOutput: "Key should be smaller than the cipher's length", + recipeConfig: [ + { + "op": "Rail Fence Cypher Decode", + "args": [22, 0] + } + ], + }, ]); From 3a4f1c26ca85c5dfcf7a93a4a9c285cfc73c9478 Mon Sep 17 00:00:00 2001 From: Flavio Diez Date: Mon, 27 Jan 2020 15:02:39 +0100 Subject: [PATCH 4/5] Add Rail Fence Cipher Encode --- src/core/config/Categories.json | 1 + src/core/operations/RailFenceCypherEncode.mjs | 96 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/core/operations/RailFenceCypherEncode.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index cc9268fc..0d68efe8 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -95,6 +95,7 @@ "Affine Cipher Decode", "A1Z26 Cipher Encode", "A1Z26 Cipher Decode", + "Rail Fence Cipher Encode", "Rail Fence Cipher Decode", "Atbash Cipher", "Substitute", diff --git a/src/core/operations/RailFenceCypherEncode.mjs b/src/core/operations/RailFenceCypherEncode.mjs new file mode 100644 index 00000000..8da1830b --- /dev/null +++ b/src/core/operations/RailFenceCypherEncode.mjs @@ -0,0 +1,96 @@ +/** + * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Rail Fence Cypher Encode operation + */ +class RailFenceCypherEncode extends Operation { + + /** + * RailFenceCypherEncode constructor + */ + constructor() { + super(); + + this.name = "Rail Fence Cypher Encode"; + this.module = "Ciphers"; + this.description = "Encodes Strings using the Rail fence Cypher provided a key and an offset"; + this.infoURL = "https://en.wikipedia.org/wiki/Rail_fence_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "number", + value: 2 + }, + { + name: "Offset", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [key] = args; + // const [key, offset] = args; + + const plaintext = input; + + if (key < 2) { + return "Key has to be bigger than 2"; + } else if (key > plaintext.length) { + return "Key should be smaller than the plain text's length"; + } + + let cipher = ""; + + for (let block = 0; block < key; block++) { + for (let pos = block; pos < plaintext.length; pos += key) { + cipher += plaintext[pos]; + } + } + + return cipher; + } + + /** + * Highlight Rail Fence Cypher Encode + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Rail Fence Cypher Encode 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 RailFenceCypherEncode; From 6fad83f1a9e3af0e8364fe20ecdb2631588bdc08 Mon Sep 17 00:00:00 2001 From: Flavio Diez Date: Tue, 28 Jan 2020 12:56:26 +0100 Subject: [PATCH 5/5] Implemented offset and added tests --- ...erDecode.mjs => RailFenceCipherDecode.mjs} | 63 +++++-------- ...erEncode.mjs => RailFenceCipherEncode.mjs} | 57 ++++-------- tests/operations/tests/Ciphers.mjs | 89 +++++++++++++++++-- 3 files changed, 123 insertions(+), 86 deletions(-) rename src/core/operations/{RailFenceCypherDecode.mjs => RailFenceCipherDecode.mjs} (50%) rename src/core/operations/{RailFenceCypherEncode.mjs => RailFenceCipherEncode.mjs} (50%) diff --git a/src/core/operations/RailFenceCypherDecode.mjs b/src/core/operations/RailFenceCipherDecode.mjs similarity index 50% rename from src/core/operations/RailFenceCypherDecode.mjs rename to src/core/operations/RailFenceCipherDecode.mjs index 20a8a4f2..5280bb1a 100644 --- a/src/core/operations/RailFenceCypherDecode.mjs +++ b/src/core/operations/RailFenceCipherDecode.mjs @@ -7,19 +7,19 @@ import Operation from "../Operation.mjs"; /** - * Rail Fence Cypher Decode operation + * Rail Fence Cipher Decode operation */ -class RailFenceCypherDecode extends Operation { +class RailFenceCipherDecode extends Operation { /** - * RailFenceCypherDecode constructor + * RailFenceCipherDecode constructor */ constructor() { super(); - this.name = "Rail Fence Cypher Decode"; + this.name = "Rail Fence Cipher Decode"; this.module = "Ciphers"; - this.description = "Decodes Strings that were created using the Rail fence Cypher provided a key and an offset"; + this.description = "Decodes Strings that were created using the Rail fence Cipher provided a key and an offset"; this.infoURL = "https://en.wikipedia.org/wiki/Rail_fence_cipher"; this.inputType = "string"; this.outputType = "string"; @@ -43,8 +43,7 @@ class RailFenceCypherDecode extends Operation { * @returns {string} */ run(input, args) { - const [key] = args; - // const [key, offset] = args; + const [key, offset] = args; let cipher = input; @@ -54,51 +53,35 @@ class RailFenceCypherDecode extends Operation { return "Key should be smaller than the cipher's length"; } + if (offset < 0) { + return "Offset has to be a positive integer"; + } + + const cycle = (key - 1) * 2; + const rest = cipher.length % key; if (rest !== 0) { - cipher = cipher + (" ".repeat(key-rest)); + cipher = cipher + (" ".repeat(key - rest)); } - const blockLen = cipher.length / key; + const plaintext = new Array(cipher.length); - let plaintext = ""; + let j = 0; + let x, y; - for (let i = 0; i < blockLen; i++) { - for (let j = 0; j < key; j++) { - plaintext += cipher[i + (j * blockLen)]; + for (y = 0; y < key; y++) { + for (x = 0; x < cipher.length; x++) { + if ((y + x + offset) % cycle === 0 || (y - x - offset) % cycle === 0) { + plaintext[x] = cipher[j++]; + } } } - return plaintext; + return plaintext.join("").trim(); } - /** - * Highlight Rail Fence Cypher Decode - * - * @param {Object[]} pos - * @param {number} pos[].start - * @param {number} pos[].end - * @param {Object[]} args - * @returns {Object[]} pos - */ - highlight(pos, args) { - return pos; - } - - /** - * Highlight Rail Fence Cypher Decode 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 RailFenceCypherDecode; +export default RailFenceCipherDecode; diff --git a/src/core/operations/RailFenceCypherEncode.mjs b/src/core/operations/RailFenceCipherEncode.mjs similarity index 50% rename from src/core/operations/RailFenceCypherEncode.mjs rename to src/core/operations/RailFenceCipherEncode.mjs index 8da1830b..5d9d5eb1 100644 --- a/src/core/operations/RailFenceCypherEncode.mjs +++ b/src/core/operations/RailFenceCipherEncode.mjs @@ -7,19 +7,19 @@ import Operation from "../Operation.mjs"; /** - * Rail Fence Cypher Encode operation + * Rail Fence Cipher Encode operation */ -class RailFenceCypherEncode extends Operation { +class RailFenceCipherEncode extends Operation { /** - * RailFenceCypherEncode constructor + * RailFenceCipherEncode constructor */ constructor() { super(); - this.name = "Rail Fence Cypher Encode"; + this.name = "Rail Fence Cipher Encode"; this.module = "Ciphers"; - this.description = "Encodes Strings using the Rail fence Cypher provided a key and an offset"; + this.description = "Encodes Strings using the Rail fence Cipher provided a key and an offset"; this.infoURL = "https://en.wikipedia.org/wiki/Rail_fence_cipher"; this.inputType = "string"; this.outputType = "string"; @@ -43,54 +43,31 @@ class RailFenceCypherEncode extends Operation { * @returns {string} */ run(input, args) { - const [key] = args; - // const [key, offset] = args; + const [key, offset] = args; const plaintext = input; - if (key < 2) { return "Key has to be bigger than 2"; } else if (key > plaintext.length) { return "Key should be smaller than the plain text's length"; } - let cipher = ""; - - for (let block = 0; block < key; block++) { - for (let pos = block; pos < plaintext.length; pos += key) { - cipher += plaintext[pos]; - } + if (offset < 0) { + return "Offset has to be a positive integer"; } - return cipher; - } + const cycle = (key - 1) * 2; + const rows = new Array(key).fill(""); - /** - * Highlight Rail Fence Cypher Encode - * - * @param {Object[]} pos - * @param {number} pos[].start - * @param {number} pos[].end - * @param {Object[]} args - * @returns {Object[]} pos - */ - highlight(pos, args) { - return pos; - } + for (let pos = 0; pos < plaintext.length; pos++) { + const rowIdx = key - 1 - Math.abs(cycle / 2 - (pos + offset) % cycle); - /** - * Highlight Rail Fence Cypher Encode in reverse - * - * @param {Object[]} pos - * @param {number} pos[].start - * @param {number} pos[].end - * @param {Object[]} args - * @returns {Object[]} pos - */ - highlightReverse(pos, args) { - return pos; + rows[rowIdx] += plaintext[pos]; + } + + return rows.join("").trim(); } } -export default RailFenceCypherEncode; +export default RailFenceCipherEncode; diff --git a/tests/operations/tests/Ciphers.mjs b/tests/operations/tests/Ciphers.mjs index 0232a14d..a853db5a 100644 --- a/tests/operations/tests/Ciphers.mjs +++ b/tests/operations/tests/Ciphers.mjs @@ -420,36 +420,113 @@ TestRegister.addTests([ ], }, { - name: "Rail Fence Cypher Decode: normal", + name: "Rail Fence Cipher Decode: normal", input: "Cytgah sTEAto rtn rsligcdsrporpyi H r fWiigo ovn oe", expectedOutput: "Cryptography is THE Art of Writing or solving codes", recipeConfig: [ { - "op": "Rail Fence Cypher Decode", + "op": "Rail Fence Cipher Decode", "args": [2, 0] } ], }, { - name: "Rail Fence Cypher Decode: key has to be bigger than 2", + name: "Rail Fence Cipher Decode: key has to be bigger than 2", input: "Cytgah sTEAto rtn rsligcdsrporpyi H r fWiigo ovn oe", expectedOutput: "Key has to be bigger than 2", recipeConfig: [ { - "op": "Rail Fence Cypher Decode", + "op": "Rail Fence Cipher Decode", "args": [1, 0] } ], }, { - name: "Rail Fence Cypher Decode: key has to be smaller than input's length", + name: "Rail Fence Cipher Decode: key has to be smaller than input's length", input: "shortinput", expectedOutput: "Key should be smaller than the cipher's length", recipeConfig: [ { - "op": "Rail Fence Cypher Decode", + "op": "Rail Fence Cipher Decode", "args": [22, 0] } ], }, + { + name: "Rail Fence Cipher Decode: offset should be positive", + input: "shortinput", + expectedOutput: "Offset has to be a positive integer", + recipeConfig: [ + { + "op": "Rail Fence Cipher Decode", + "args": [2, -1] + } + ], + }, + { + name: "Rail Fence Cipher Decode: Normal with Offset non-null", + input: "51746026813793592840", + expectedOutput: "12345678901234567890", + recipeConfig: [ + { + "op": "Rail Fence Cipher Decode", + "args": [4, 2] + } + ], + }, + { + name: "Rail Fence Cipher Encode: normal", + input: "Cryptography is THE Art of Writing or solving codes", + expectedOutput: "Cytgah sTEAto rtn rsligcdsrporpyi H r fWiigo ovn oe", + recipeConfig: [ + { + "op": "Rail Fence Cipher Encode", + "args": [2, 0] + } + ], + }, + { + name: "Rail Fence Cipher Encode: key has to be bigger than 2", + input: "Cryptography is THE Art of Writing or solving codes", + expectedOutput: "Key has to be bigger than 2", + recipeConfig: [ + { + "op": "Rail Fence Cipher Encode", + "args": [1, 0] + } + ], + }, + { + name: "Rail Fence Cipher Encode: key has to be smaller than input's length", + input: "shortinput", + expectedOutput: "Key should be smaller than the plain text's length", + recipeConfig: [ + { + "op": "Rail Fence Cipher Encode", + "args": [22, 0] + } + ], + }, + { + name: "Rail Fence Cipher Encode: offset should be positive", + input: "shortinput", + expectedOutput: "Offset has to be a positive integer", + recipeConfig: [ + { + "op": "Rail Fence Cipher Encode", + "args": [2, -1] + } + ], + }, + { + name: "Rail Fence Cipher Encode: Normal with Offset non-null", + input: "12345678901234567890", + expectedOutput: "51746026813793592840", + recipeConfig: [ + { + "op": "Rail Fence Cipher Encode", + "args": [4, 2] + } + ], + }, ]);