From 355a6d6b76db8348d4f9dbd4f24d03cf478f743b Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 14 Feb 2020 14:21:32 +0000 Subject: [PATCH] Modifications made to CipherSaber2 --- src/core/config/Categories.json | 3 +- src/core/lib/CipherSaber2.mjs | 36 ++++++++ src/core/operations/CipherSaber2.mjs | 98 --------------------- src/core/operations/CipherSaber2Decrypt.mjs | 57 ++++++++++++ src/core/operations/CipherSaber2Encrypt.mjs | 61 +++++++++++++ tests/operations/index.mjs | 1 + tests/operations/tests/CipherSaber2.mjs | 45 ++++++++++ 7 files changed, 202 insertions(+), 99 deletions(-) create mode 100644 src/core/lib/CipherSaber2.mjs delete mode 100644 src/core/operations/CipherSaber2.mjs create mode 100644 src/core/operations/CipherSaber2Decrypt.mjs create mode 100644 src/core/operations/CipherSaber2Encrypt.mjs create mode 100644 tests/operations/tests/CipherSaber2.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index ad8ec0e7..e24cb047 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -96,7 +96,8 @@ "A1Z26 Cipher Encode", "A1Z26 Cipher Decode", "Atbash Cipher", - "CipherSaber2", + "CipherSaber2 Encrypt", + "CipherSaber2 Decrypt", "Substitute", "Derive PBKDF2 key", "Derive EVP key", diff --git a/src/core/lib/CipherSaber2.mjs b/src/core/lib/CipherSaber2.mjs new file mode 100644 index 00000000..cafeb76e --- /dev/null +++ b/src/core/lib/CipherSaber2.mjs @@ -0,0 +1,36 @@ +import Utils from "../Utils.mjs"; + +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ +export function encode(tempIVP, args, input) { + const ivp = new Uint8Array(Utils.strToByteArray(args[0]).concat(tempIVP)); + const state = new Array(256).fill(0); + let j = 0, i = 0; + const result = []; + + // Mixing states based off of IV. + for (let i = 0; i < 256; i++) + state[i] = i; + const ivpLength = ivp.length; + for (let r = 0; r < args[1]; r ++) { + for (let k = 0; k < 256; k++) { + j = (j + state[k] + ivp[k % ivpLength]) % 256; + [state[k], state[j]] = [state[j], state[k]]; + } + } + j = 0; + i = 0; + + // XOR cipher with key. + for (let x = 0; x < input.length; x++) { + i = (++i) % 256; + j = (j + state[i]) % 256; + [state[i], state[j]] = [state[j], state[i]]; + const n = (state[i] + state[j]) % 256; + result.push(state[n] ^ input[x]); + } + return result; +} diff --git a/src/core/operations/CipherSaber2.mjs b/src/core/operations/CipherSaber2.mjs deleted file mode 100644 index a03d1aed..00000000 --- a/src/core/operations/CipherSaber2.mjs +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @author n1073645 [n1073645@gmail.com] - * @copyright Crown Copyright 2020 - * @license Apache-2.0 - */ - -import Operation from "../Operation.mjs"; -import crypto from "crypto"; -import Utils from "../Utils.mjs"; - -/** - * CipherSaber2 operation - */ -class CipherSaber2 extends Operation { - - /** - * CipherSaber2 constructor - */ - constructor() { - super(); - - this.name = "CipherSaber2"; - this.module = "Crypto"; - this.description = "CipherSaber is a simple symmetric encryption protocol based on the RC4 stream cipher. It gives reasonably strong protection of message confidentiality, yet it's designed to be simple enough that even novice programmers can memorize the algorithm and implement it from scratch."; - this.infoURL = "https://wikipedia.org/wiki/CipherSaber"; - this.inputType = "ArrayBuffer"; - this.outputType = "ArrayBuffer"; - this.args = [ - { - name: "Key", - type: "string", - value: "" - }, - { - name: "Rounds", - type: "number", - value: 20 - }, - { - name: "Mode", - type: "option", - value: ["Encrypt", "Decrypt"] - } - ]; - } - - /** - * @param {ArrayBuffer} input - * @param {Object[]} args - * @returns {ArrayBuffer} - */ - run(input, args) { - input = new Uint8Array(input); - const ivp = new Uint8Array(args[0].length + 10); - ivp.set(new Uint8Array(Utils.strToByteArray(args[0])), 0); - const result = []; - let tempIVP; - - // Assign into initialisation vector based on cipher mode. - if (args[2] === "Encrypt") { - tempIVP = crypto.randomBytes(10); - for (let m = 0; m < 10; m++) - result.push(tempIVP[m]); - } else { - tempIVP = input.slice(0, 10); - input = input.slice(10); - } - ivp.set(tempIVP, args[0].length); - const state = new Array(256).fill(0); - let j = 0, i = 0; - - // Mixing states based off of IV. - for (let i = 0; i < 256; i++) - state[i] = i; - const ivpLength = ivp.length; - for (let r = 0; r < args[1]; r ++) { - for (let k = 0; k < 256; k++) { - j = (j + state[k] + ivp[k % ivpLength]) % 256; - [state[k], state[j]] = [state[j], state[k]]; - } - } - j = 0; - i = 0; - - // XOR cipher with key. - for (let x = 0; x < input.length; x++) { - i = (++i) % 256; - j = (j + state[i]) % 256; - [state[i], state[j]] = [state[j], state[i]]; - const n = (state[i] + state[j]) % 256; - result.push(state[n] ^ input[x]); - } - return new Uint8Array(result).buffer; - } - -} - -export default CipherSaber2; diff --git a/src/core/operations/CipherSaber2Decrypt.mjs b/src/core/operations/CipherSaber2Decrypt.mjs new file mode 100644 index 00000000..0784f905 --- /dev/null +++ b/src/core/operations/CipherSaber2Decrypt.mjs @@ -0,0 +1,57 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import { encode } from "../lib/CipherSaber2.mjs"; + +/** + * CipherSaber2 Decrypt operation + */ +class CipherSaber2Decrypt extends Operation { + + /** + * CipherSaber2Decrypt constructor + */ + constructor() { + super(); + + this.name = "CipherSaber2 Decrypt"; + this.module = "Crypto"; + this.description = "CipherSaber is a simple symmetric encryption protocol based on the RC4 stream cipher. It gives reasonably strong protection of message confidentiality, yet it's designed to be simple enough that even novice programmers can memorize the algorithm and implement it from scratch."; + this.infoURL = "https://wikipedia.org/wiki/CipherSaber"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "Key", + type: "string", + value: "" + }, + { + name: "Rounds", + type: "number", + value: 20 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + input = new Uint8Array(input); + const result = []; + + const tempIVP = input.slice(0, 10); + input = input.slice(10); + return new Uint8Array(result.concat(encode(tempIVP, args, input))).buffer; + } + +} + +export default CipherSaber2Decrypt; diff --git a/src/core/operations/CipherSaber2Encrypt.mjs b/src/core/operations/CipherSaber2Encrypt.mjs new file mode 100644 index 00000000..e2b4ce55 --- /dev/null +++ b/src/core/operations/CipherSaber2Encrypt.mjs @@ -0,0 +1,61 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import crypto from "crypto"; +import { encode } from "../lib/CipherSaber2.mjs"; + +/** + * CipherSaber2 operation + */ +class CipherSaber2 extends Operation { + + /** + * CipherSaber2 constructor + */ + constructor() { + super(); + + this.name = "CipherSaber2 Encrypt"; + this.module = "Crypto"; + this.description = "CipherSaber is a simple symmetric encryption protocol based on the RC4 stream cipher. It gives reasonably strong protection of message confidentiality, yet it's designed to be simple enough that even novice programmers can memorize the algorithm and implement it from scratch."; + this.infoURL = "https://wikipedia.org/wiki/CipherSaber"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "Key", + type: "string", + value: "" + }, + { + name: "Rounds", + type: "number", + value: 20 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + input = new Uint8Array(input); + const result = []; + + // Assign into initialisation vector based on cipher mode. + const tempIVP = crypto.randomBytes(10); + for (let m = 0; m < 10; m++) + result.push(tempIVP[m]); + + return new Uint8Array(result.concat(encode(tempIVP, args, input))).buffer; + } + +} + +export default CipherSaber2; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index bf440414..94fd48d3 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -96,6 +96,7 @@ import "./tests/DefangIP.mjs"; import "./tests/ParseUDP.mjs"; import "./tests/AvroToJSON.mjs"; import "./tests/Lorenz.mjs"; +import "./tests/CipherSaber2"; // Cannot test operations that use the File type yet diff --git a/tests/operations/tests/CipherSaber2.mjs b/tests/operations/tests/CipherSaber2.mjs new file mode 100644 index 00000000..df01a886 --- /dev/null +++ b/tests/operations/tests/CipherSaber2.mjs @@ -0,0 +1,45 @@ +/** + * Ciphersaber2 tests. + * + * @author n1073645 [n1073645@gmail.com] + * + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "CipherSaber2 Encrypt", + input: "Hello World", + expectedMatch: /.{21}/s, + recipeConfig: [ + { + op: "CipherSaber2 Encrypt", + args: ["test", 20], + }, + ], + }, + { + name: "CipherSaber2 Decrypt", + input: "\x5d\xd9\x7f\xeb\x77\x3c\x42\x9d\xfe\x9c\x3b\x21\x63\xbd\x53\x38\x18\x7c\x36\x37", + expectedOutput: "helloworld", + recipeConfig: [ + { + op: "CipherSaber2 Decrypt", + args: ["test", 20], + }, + ], + }, + { + name: "CipherSaber2 Encrypt", + input: "", + expectedMatch: /.{10}/s, + recipeConfig: [ + { + op: "CipherSaber2 Encrypt", + args: ["", 20], + }, + ], + }, +]);