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;