Browse Source

Merge branch 'artemisbot-features/bifid'

n1474335 8 years ago
parent
commit
51798553e1

+ 3 - 3
src/core/Utils.js

@@ -1050,7 +1050,7 @@ const Utils = {
     /**
      * Actual modulo function, since % is actually the remainder function in JS.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {number} x
      * @param {number} y
      * @returns {number}
@@ -1063,7 +1063,7 @@ const Utils = {
     /**
      * Finds the greatest common divisor of two numbers.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {number} x
      * @param {number} y
      * @returns {number}
@@ -1079,7 +1079,7 @@ const Utils = {
     /**
      * Finds the modular inverse of two values.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {number} x
      * @param {number} y
      * @returns {number}

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

@@ -89,6 +89,8 @@ const Categories = [
             "Vigenère Decode",
             "To Morse Code",
             "From Morse Code",
+            "Bifid Cipher Encode",
+            "Bifid Cipher Decode",
             "Affine Cipher Encode",
             "Affine Cipher Decode",
             "Atbash Cipher",

+ 30 - 0
src/core/config/OperationConfig.js

@@ -1512,6 +1512,36 @@ const OperationConfig = {
             }
         ]
     },
+    "Bifid Cipher Encode": {
+        description: "The Bifid cipher is a cipher which uses a Polybius square in conjunction with transposition, which can be fairly difficult to decipher without knowing the alphabet keyword.",
+        run: Cipher.runBifidEnc,
+        highlight: true,
+        highlightReverse: true,
+        inputType: "string",
+        outputType: "string",
+        args: [
+            {
+                name: "Keyword",
+                type: "string",
+                value: ""
+            }
+        ]
+    },
+    "Bifid Cipher Decode": {
+        description: "The Bifid cipher is a cipher which uses a Polybius square in conjunction with transposition, which can be fairly difficult to decipher without knowing the alphabet keyword.",
+        run: Cipher.runBifidDec,
+        highlight: true,
+        highlightReverse: true,
+        inputType: "string",
+        outputType: "string",
+        args: [
+            {
+                name: "Keyword",
+                type: "string",
+                value: ""
+            }
+        ]
+    },
     "Affine Cipher Encode": {
         description: "The Affine cipher is a type of monoalphabetic substitution cipher, wherein each letter in an alphabet is mapped to its numeric equivalent, encrypted using simple mathematical function, <code>(ax + b) % 26</code>, and converted back to a letter.",
         run: Cipher.runAffineEnc,

+ 2 - 2
src/core/operations/ByteRepr.js

@@ -58,7 +58,7 @@ const ByteRepr = {
     /**
      * To Octal operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {byteArray} input
      * @param {Object[]} args
      * @returns {string}
@@ -72,7 +72,7 @@ const ByteRepr = {
     /**
      * From Octal operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {string} input
      * @param {Object[]} args
      * @returns {byteArray}

+ 159 - 6
src/core/operations/Cipher.js

@@ -407,7 +407,7 @@ const Cipher = {
     /**
      * Vigenère Encode operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
@@ -454,7 +454,7 @@ const Cipher = {
     /**
      * Vigenère Decode operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
@@ -508,7 +508,7 @@ const Cipher = {
     /**
      * Affine Cipher Encode operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
@@ -540,9 +540,9 @@ const Cipher = {
 
 
     /**
-     * Affine Cipher Encode operation.
+     * Affine Cipher Decode operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
@@ -584,7 +584,7 @@ const Cipher = {
     /**
      * Atbash Cipher Encode operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
@@ -594,6 +594,159 @@ const Cipher = {
     },
 
 
+    /**
+     * Generates a polybius square for the given keyword
+     *
+     * @private
+     * @author Matt C [matt@artemisbot.uk]
+     * @param {string} keyword - Must be upper case
+     * @returns {string}
+     */
+    _genPolybiusSquare: function (keyword) {
+        const alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
+        const polArray = `${keyword}${alpha}`.split("").unique();
+        let polybius = [];
+
+        for (let i = 0; i < 5; i++) {
+            polybius[i] = polArray.slice(i*5, i*5 + 5);
+        }
+
+        return polybius;
+    },
+
+    /**
+     * Bifid Cipher Encode operation
+     *
+     * @author Matt C [matt@artemisbot.uk]
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    runBifidEnc: function (input, args) {
+        const keywordStr = args[0].toUpperCase().replace("J", "I"),
+            keyword = keywordStr.split("").unique(),
+            alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
+
+        let output = "",
+            xCo = [],
+            yCo = [],
+            structure = [],
+            count = 0;
+
+        if (keyword.length > 25)
+            return "The alphabet keyword must be less than 25 characters.";
+
+        if (!/^[a-zA-Z]+$/.test(keywordStr) && keyword.length > 0)
+            return "The key must consist only of letters";
+
+        const polybius = Cipher._genPolybiusSquare(keywordStr);
+
+        input.replace("J", "I").split("").forEach(letter => {
+            let alpInd = alpha.split("").indexOf(letter.toLocaleUpperCase()) >= 0,
+                polInd;
+
+            if (alpInd) {
+                for (let i = 0; i < 5; i++) {
+                    polInd = polybius[i].indexOf(letter.toLocaleUpperCase());
+                    if (polInd >= 0) {
+                        xCo.push(polInd);
+                        yCo.push(i);
+                    }
+                }
+
+                if (alpha.split("").indexOf(letter) >= 0) {
+                    structure.push(true);
+                } else if (alpInd) {
+                    structure.push(false);
+                }
+            } else {
+                structure.push(letter);
+            }
+        });
+
+        const trans = `${yCo.join("")}${xCo.join("")}`;
+
+        structure.forEach(pos => {
+            if (typeof pos === "boolean") {
+                let coords = trans.substr(2*count, 2).split("");
+
+                output += pos ?
+                    polybius[coords[0]][coords[1]] :
+                    polybius[coords[0]][coords[1]].toLocaleLowerCase();
+                count++;
+            } else {
+                output += pos;
+            }
+        });
+
+        return output;
+    },
+
+    /**
+     * Bifid Cipher Decode operation
+     *
+     * @author Matt C [matt@artemisbot.uk]
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    runBifidDec: function (input, args) {
+        const keywordStr = args[0].toUpperCase().replace("J", "I"),
+            keyword = keywordStr.split("").unique(),
+            alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
+
+        let output = "",
+            structure = [],
+            count = 0,
+            trans = "";
+
+        if (keyword.length > 25)
+            return "The alphabet keyword must be less than 25 characters.";
+
+        if (!/^[a-zA-Z]+$/.test(keywordStr) && keyword.length > 0)
+            return "The key must consist only of letters";
+
+        const polybius = Cipher._genPolybiusSquare(keywordStr);
+
+        input.replace("J", "I").split("").forEach((letter) => {
+            let alpInd = alpha.split("").indexOf(letter.toLocaleUpperCase()) >= 0,
+                polInd;
+
+            if (alpInd) {
+                for (let i = 0; i < 5; i++) {
+                    polInd = polybius[i].indexOf(letter.toLocaleUpperCase());
+                    if (polInd >= 0) {
+                        trans += `${i}${polInd}`;
+                    }
+                }
+
+                if (alpha.split("").indexOf(letter) >= 0) {
+                    structure.push(true);
+                } else if (alpInd) {
+                    structure.push(false);
+                }
+            } else {
+                structure.push(letter);
+            }
+        });
+
+        structure.forEach(pos => {
+            if (typeof pos === "boolean") {
+                let coords = [trans[count], trans[count+trans.length/2]];
+
+                output += pos ?
+                    polybius[coords[0]][coords[1]] :
+                    polybius[coords[0]][coords[1]].toLocaleLowerCase();
+                count++;
+            } else {
+                output += pos;
+            }
+        });
+
+        return output;
+    },
+
+
     /**
      * @constant
      * @default

+ 1 - 1
src/core/operations/Rotate.js

@@ -135,7 +135,7 @@ const Rotate = {
     /**
      * ROT47 operation.
      *
-     * @author Matt C [matt@artemisbot.pw]
+     * @author Matt C [matt@artemisbot.uk]
      * @param {byteArray} input
      * @param {Object[]} args
      * @returns {byteArray}

+ 1 - 0
test/index.js

@@ -14,6 +14,7 @@ import TestRegister from "./TestRegister.js";
 import "./tests/operations/Base58.js";
 import "./tests/operations/ByteRepr.js";
 import "./tests/operations/CharEnc.js";
+import "./tests/operations/Cipher.js";
 import "./tests/operations/Code.js";
 import "./tests/operations/Compress.js";
 import "./tests/operations/DateTime.js";

+ 1 - 1
test/tests/operations/ByteRepr.js

@@ -1,7 +1,7 @@
 /**
  * ByteRepr tests.
  *
- * @author Matt C [matt@artemisbot.pw]
+ * @author Matt C [matt@artemisbot.uk]
  * @copyright Crown Copyright 2017
  * @license Apache-2.0
  */

+ 78 - 0
test/tests/operations/Cipher.js

@@ -0,0 +1,78 @@
+/**
+ * Cipher tests.
+ *
+ * @author Matt C [matt@artemisbot.uk]
+ *
+ * @copyright Crown Copyright 2017
+ * @license Apache-2.0
+ */
+import TestRegister from "../../TestRegister.js";
+
+TestRegister.addTests([
+    {
+        name: "Bifid Cipher Encode: no input",
+        input: "",
+        expectedOutput: "",
+        recipeConfig: [
+            {
+                "op": "Bifid Cipher Encode",
+                "args": ["nothing"]
+            }
+        ],
+    },
+    {
+        name: "Bifid Cipher Encode: no key",
+        input: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
+        expectedOutput: "Vq daqcliho rmltofvlnc qbdhlcr nt qdq Fbm-Rdkkm vuoottnoi aitp al axf tdtmvt owppkaodtx.",
+        recipeConfig: [
+            {
+                "op": "Bifid Cipher Encode",
+                "args": [""]
+            }
+        ],
+    },
+    {
+        name: "Bifid Cipher Encode: normal",
+        input: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
+        expectedOutput: "Wc snpsigdd cpfrrcxnfi hikdnnp dm crc Fcb-Pdeug vueageacc vtyl sa zxm crebzp lyoeuaiwpv.",
+        recipeConfig: [
+            {
+                "op": "Bifid Cipher Encode",
+                "args": ["Schrodinger"]
+            }
+        ],
+    },
+    {
+        name: "Bifid Cipher Decode: no input",
+        input: "",
+        expectedOutput: "",
+        recipeConfig: [
+            {
+                "op": "Bifid Cipher Decode",
+                "args": ["nothing"]
+            }
+        ],
+    },
+    {
+        name: "Bifid Cipher Decode: no key",
+        input: "Vq daqcliho rmltofvlnc qbdhlcr nt qdq Fbm-Rdkkm vuoottnoi aitp al axf tdtmvt owppkaodtx.",
+        expectedOutput: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
+        recipeConfig: [
+            {
+                "op": "Bifid Cipher Decode",
+                "args": [""]
+            }
+        ],
+    },
+    {
+        name: "Bifid Cipher Decode: normal",
+        input: "Wc snpsigdd cpfrrcxnfi hikdnnp dm crc Fcb-Pdeug vueageacc vtyl sa zxm crebzp lyoeuaiwpv.",
+        expectedOutput: "We recreate conditions similar to the Van-Allen radiation belt in our secure facilities.",
+        recipeConfig: [
+            {
+                "op": "Bifid Cipher Decode",
+                "args": ["Schrodinger"]
+            }
+        ],
+    },
+]);