Sfoglia il codice sorgente

Implemented the Rail Fence Cipher with both encoding and decoding

Flavio Diez 5 anni fa
parent
commit
1509b2b96c

+ 2 - 0
src/core/config/Categories.json

@@ -95,6 +95,8 @@
             "Affine Cipher Decode",
             "A1Z26 Cipher Encode",
             "A1Z26 Cipher Decode",
+            "Rail Fence Cipher Encode",
+            "Rail Fence Cipher Decode",
             "Atbash Cipher",
             "Substitute",
             "Derive PBKDF2 key",

+ 87 - 0
src/core/operations/RailFenceCipherDecode.mjs

@@ -0,0 +1,87 @@
+/**
+ * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com]
+ * @copyright Crown Copyright 2020
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation.mjs";
+
+/**
+ * Rail Fence Cipher Decode operation
+ */
+class RailFenceCipherDecode extends Operation {
+
+    /**
+     * RailFenceCipherDecode constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Rail Fence Cipher Decode";
+        this.module = "Ciphers";
+        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";
+        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, offset] = args;
+
+        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";
+        }
+
+        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));
+        }
+
+        const plaintext = new Array(cipher.length);
+
+        let j = 0;
+        let x, y;
+
+        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.join("").trim();
+    }
+
+}
+
+
+export default RailFenceCipherDecode;

+ 73 - 0
src/core/operations/RailFenceCipherEncode.mjs

@@ -0,0 +1,73 @@
+/**
+ * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com]
+ * @copyright Crown Copyright 2020
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation.mjs";
+
+/**
+ * Rail Fence Cipher Encode operation
+ */
+class RailFenceCipherEncode extends Operation {
+
+    /**
+     * RailFenceCipherEncode constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Rail Fence Cipher Encode";
+        this.module = "Ciphers";
+        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";
+        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, 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";
+        }
+
+        if (offset < 0) {
+            return "Offset has to be a positive integer";
+        }
+
+        const cycle = (key - 1) * 2;
+        const rows = new Array(key).fill("");
+
+        for (let pos = 0; pos < plaintext.length; pos++) {
+            const rowIdx = key - 1 - Math.abs(cycle / 2 - (pos + offset) % cycle);
+
+            rows[rowIdx] += plaintext[pos];
+        }
+
+        return rows.join("").trim();
+    }
+
+}
+
+export default RailFenceCipherEncode;

+ 110 - 0
tests/operations/tests/Ciphers.mjs

@@ -418,4 +418,114 @@ TestRegister.addTests([
             }
         ],
     },
+    {
+        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 Cipher Decode",
+                "args": [2, 0]
+            }
+        ],
+    },
+    {
+        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 Cipher Decode",
+                "args": [1, 0]
+            }
+        ],
+    },
+    {
+        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 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]
+            }
+        ],
+    },
 ]);