Added Bifid Cipher Encode & Decode

Bifid Cipher + Tests
This commit is contained in:
Matt C 2017-06-21 22:28:17 +01:00
parent a417a6469c
commit 91c6f682e7
5 changed files with 248 additions and 6 deletions

View file

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

View file

@ -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: "Alphabet Key",
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: "Alphabet Key",
type: "string",
value: ""
}
]
},
"Affine Cipher Encode": { "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.", 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, run: Cipher.runAffineEnc,

View file

@ -407,7 +407,7 @@ const Cipher = {
/** /**
* Vigenère Encode operation. * Vigenère Encode operation.
* *
* @author Matt C [matt@artemisbot.pw] * @author Matt C [matt@artemisbot.uk]
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
@ -454,7 +454,7 @@ const Cipher = {
/** /**
* Vigenère Decode operation. * Vigenère Decode operation.
* *
* @author Matt C [matt@artemisbot.pw] * @author Matt C [matt@artemisbot.uk]
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
@ -508,7 +508,7 @@ const Cipher = {
/** /**
* Affine Cipher Encode operation. * Affine Cipher Encode operation.
* *
* @author Matt C [matt@artemisbot.pw] * @author Matt C [matt@artemisbot.uk]
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @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 {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
@ -584,7 +584,7 @@ const Cipher = {
/** /**
* Atbash Cipher Encode operation. * Atbash Cipher Encode operation.
* *
* @author Matt C [matt@artemisbot.pw] * @author Matt C [matt@artemisbot.uk]
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
@ -593,6 +593,137 @@ const Cipher = {
return Cipher.runAffineEnc(input, [25, 25]); return Cipher.runAffineEnc(input, [25, 25]);
}, },
/**
* Generates a polybius square for the given keyword
*
* @author Matt C [matt@artemisbot.uk]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
genPolybiusSquare: function (keyword) {
const alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
let polybius = [],
polString = "";
keyword.split("").unique().forEach(letter => {
polString += letter;
});
polString = `${polString}${alpha}`.split("").unique().join("");
for (let i = 0; i < 5; i++) {
polybius[i] = polString.substr(i*5, 5).split("");
}
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 keyword = args[0].toUpperCase().replace("J", "I"),
alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
let output = "",
xCo = [],
yCo = [],
structure = [],
count = 0,
trans;
if (keyword.split("").unique().length > 25) return "The alphabet keyword must be less than 25 characters.";
if (!/^[a-zA-Z]+$/.test(keyword) && keyword.split("").unique().length > 0) return "The key must consist only of letters";
const polybius = Cipher.genPolybiusSquare(keyword);
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);
}
});
trans = `${yCo.join("")}${xCo.join("")}`;
structure.forEach(pos => {
if (typeof pos === "boolean") {
let coords = trans.substr(2*count, 2).split("");
if (pos) {
output += polybius[coords[0]][coords[1]];
} else {
output += 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 keyword = args[0].toUpperCase().replace("J", "I"),
alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
let output = "",
structure = [],
count = 0,
trans = "";
if (keyword.split("").unique().length > 25) return "The alphabet keyword must be less than 25 characters.";
if (!/^[a-zA-Z]+$/.test(keyword) && keyword.split("").unique().length > 0) return "The key must consist only of letters";
const polybius = Cipher.genPolybiusSquare(keyword);
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]];
if (pos) {
output += polybius[coords[0]][coords[1]];
} else {
output += polybius[coords[0]][coords[1]].toLocaleLowerCase();
}
count++;
} else {
output += pos;
}
});
return output;
},
/** /**
* @constant * @constant

View file

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

View file

@ -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"]
}
],
},
]);