From a06303c2fd203b77def862d2cfa3a9bb1059caac Mon Sep 17 00:00:00 2001 From: n1073645 Date: Mon, 27 Jan 2020 14:33:05 +0000 Subject: [PATCH 1/4] CipherSaber2 added --- src/core/config/Categories.json | 1 + src/core/operations/CipherSaber2.mjs | 98 ++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/core/operations/CipherSaber2.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 53ca796d..ad8ec0e7 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -96,6 +96,7 @@ "A1Z26 Cipher Encode", "A1Z26 Cipher Decode", "Atbash Cipher", + "CipherSaber2", "Substitute", "Derive PBKDF2 key", "Derive EVP key", diff --git a/src/core/operations/CipherSaber2.mjs b/src/core/operations/CipherSaber2.mjs new file mode 100644 index 00000000..27945186 --- /dev/null +++ b/src/core/operations/CipherSaber2.mjs @@ -0,0 +1,98 @@ +/** + * @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 = ""; + this.infoURL = ""; + 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; From 6090842372a9d5966d76f6b7db5a69e7b7548a00 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 14 Feb 2020 09:15:50 +0000 Subject: [PATCH 2/4] Modifications made to ciphersaber --- src/core/operations/CipherSaber2.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/operations/CipherSaber2.mjs b/src/core/operations/CipherSaber2.mjs index 27945186..a03d1aed 100644 --- a/src/core/operations/CipherSaber2.mjs +++ b/src/core/operations/CipherSaber2.mjs @@ -21,8 +21,8 @@ class CipherSaber2 extends Operation { this.name = "CipherSaber2"; this.module = "Crypto"; - this.description = ""; - this.infoURL = ""; + 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 = [ From 355a6d6b76db8348d4f9dbd4f24d03cf478f743b Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 14 Feb 2020 14:21:32 +0000 Subject: [PATCH 3/4] 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], + }, + ], + }, +]); From 64b979e25e3ca95fabc010ef6a19c5b6bcd9664e Mon Sep 17 00:00:00 2001 From: n1474335 Date: Thu, 5 Mar 2020 16:39:52 +0000 Subject: [PATCH 4/4] CipherSaber2 ops now accept a variety of key types --- src/core/lib/CipherSaber2.mjs | 8 +++----- src/core/operations/CipherSaber2Decrypt.mjs | 12 ++++++++---- src/core/operations/CipherSaber2Encrypt.mjs | 20 ++++++++++++-------- tests/operations/tests/CipherSaber2.mjs | 6 +++--- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/core/lib/CipherSaber2.mjs b/src/core/lib/CipherSaber2.mjs index cafeb76e..bf3954e9 100644 --- a/src/core/lib/CipherSaber2.mjs +++ b/src/core/lib/CipherSaber2.mjs @@ -1,12 +1,10 @@ -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)); +export function encode(tempIVP, key, rounds, input) { + const ivp = new Uint8Array(key.concat(tempIVP)); const state = new Array(256).fill(0); let j = 0, i = 0; const result = []; @@ -15,7 +13,7 @@ export function encode(tempIVP, args, input) { for (let i = 0; i < 256; i++) state[i] = i; const ivpLength = ivp.length; - for (let r = 0; r < args[1]; r ++) { + for (let r = 0; r < rounds; r ++) { for (let k = 0; k < 256; k++) { j = (j + state[k] + ivp[k % ivpLength]) % 256; [state[k], state[j]] = [state[j], state[k]]; diff --git a/src/core/operations/CipherSaber2Decrypt.mjs b/src/core/operations/CipherSaber2Decrypt.mjs index 0784f905..53d61468 100644 --- a/src/core/operations/CipherSaber2Decrypt.mjs +++ b/src/core/operations/CipherSaber2Decrypt.mjs @@ -6,6 +6,7 @@ import Operation from "../Operation.mjs"; import { encode } from "../lib/CipherSaber2.mjs"; +import Utils from "../Utils.mjs"; /** * CipherSaber2 Decrypt operation @@ -27,8 +28,9 @@ class CipherSaber2Decrypt extends Operation { this.args = [ { name: "Key", - type: "string", - value: "" + type: "toggleString", + value: "", + toggleValues: ["Hex", "UTF8", "Latin1", "Base64"] }, { name: "Rounds", @@ -45,11 +47,13 @@ class CipherSaber2Decrypt extends Operation { */ run(input, args) { input = new Uint8Array(input); - const result = []; + const result = [], + key = Utils.convertToByteArray(args[0].string, args[0].option), + rounds = args[1]; const tempIVP = input.slice(0, 10); input = input.slice(10); - return new Uint8Array(result.concat(encode(tempIVP, args, input))).buffer; + return new Uint8Array(result.concat(encode(tempIVP, key, rounds, input))).buffer; } } diff --git a/src/core/operations/CipherSaber2Encrypt.mjs b/src/core/operations/CipherSaber2Encrypt.mjs index e2b4ce55..dd86bd52 100644 --- a/src/core/operations/CipherSaber2Encrypt.mjs +++ b/src/core/operations/CipherSaber2Encrypt.mjs @@ -7,14 +7,15 @@ import Operation from "../Operation.mjs"; import crypto from "crypto"; import { encode } from "../lib/CipherSaber2.mjs"; +import Utils from "../Utils.mjs"; /** - * CipherSaber2 operation + * CipherSaber2 Encrypt operation */ -class CipherSaber2 extends Operation { +class CipherSaber2Encrypt extends Operation { /** - * CipherSaber2 constructor + * CipherSaber2Encrypt constructor */ constructor() { super(); @@ -28,8 +29,9 @@ class CipherSaber2 extends Operation { this.args = [ { name: "Key", - type: "string", - value: "" + type: "toggleString", + value: "", + toggleValues: ["Hex", "UTF8", "Latin1", "Base64"] }, { name: "Rounds", @@ -46,16 +48,18 @@ class CipherSaber2 extends Operation { */ run(input, args) { input = new Uint8Array(input); - const result = []; + const result = [], + key = Utils.convertToByteArray(args[0].string, args[0].option), + rounds = args[1]; // 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; + return new Uint8Array(result.concat(encode(tempIVP, key, rounds, input))).buffer; } } -export default CipherSaber2; +export default CipherSaber2Encrypt; diff --git a/tests/operations/tests/CipherSaber2.mjs b/tests/operations/tests/CipherSaber2.mjs index df01a886..dd675d45 100644 --- a/tests/operations/tests/CipherSaber2.mjs +++ b/tests/operations/tests/CipherSaber2.mjs @@ -16,7 +16,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "CipherSaber2 Encrypt", - args: ["test", 20], + args: [{ "option": "Latin1", "string": "test" }, 20], }, ], }, @@ -27,7 +27,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "CipherSaber2 Decrypt", - args: ["test", 20], + args: [{ "option": "Latin1", "string": "test" }, 20], }, ], }, @@ -38,7 +38,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "CipherSaber2 Encrypt", - args: ["", 20], + args: [{ "option": "Latin1", "string": "" }, 20], }, ], },