Browse Source

ESM: Ported AES operations

n1474335 7 years ago
parent
commit
a7d763287e
3 changed files with 212 additions and 0 deletions
  1. 105 0
      src/core/operations/AESDecrypt.mjs
  2. 103 0
      src/core/operations/AESEncrypt.mjs
  3. 4 0
      webpack.config.js

+ 105 - 0
src/core/operations/AESDecrypt.mjs

@@ -0,0 +1,105 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import forge from "node-forge/dist/forge.min.js";
+
+/**
+ * AES Decrypt operation
+ */
+class AESDecrypt extends Operation {
+
+    /**
+     * AESDecrypt constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "AES Decrypt";
+        this.module = "Ciphers";
+        this.description = "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul><br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.<br><br><b>GCM Tag:</b> This field is ignored unless 'GCM' mode is used.";
+        this.inputType = "string";
+        this.outputType = "string";
+        this.args = [
+            {
+                "name": "Key",
+                "type": "toggleString",
+                "value": "",
+                "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
+            },
+            {
+                "name": "IV",
+                "type": "toggleString",
+                "value": "",
+                "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
+            },
+            {
+                "name": "Mode",
+                "type": "option",
+                "value": ["CBC", "CFB", "OFB", "CTR", "GCM", "ECB"]
+            },
+            {
+                "name": "Input",
+                "type": "option",
+                "value": ["Hex", "Raw"]
+            },
+            {
+                "name": "Output",
+                "type": "option",
+                "value": ["Raw", "Hex"]
+            },
+            {
+                "name": "GCM Tag",
+                "type": "toggleString",
+                "value": "",
+                "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        const key = Utils.convertToByteArray(args[0].string, args[0].option),
+            iv = Utils.convertToByteArray(args[1].string, args[1].option),
+            mode = args[2],
+            inputType = args[3],
+            outputType = args[4],
+            gcmTag = Utils.convertToByteString(args[5].string, args[5].option);
+
+        if ([16, 24, 32].indexOf(key.length) < 0) {
+            return `Invalid key length: ${key.length} bytes
+
+The following algorithms will be used based on the size of the key:
+  16 bytes = AES-128
+  24 bytes = AES-192
+  32 bytes = AES-256`;
+        }
+
+        input = Utils.convertToByteString(input, inputType);
+
+        const decipher = forge.cipher.createDecipher("AES-" + mode, key);
+        decipher.start({
+            iv: iv,
+            tag: gcmTag
+        });
+        decipher.update(forge.util.createBuffer(input));
+        const result = decipher.finish();
+
+        if (result) {
+            return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes();
+        } else {
+            return "Unable to decrypt input with these parameters.";
+        }
+    }
+
+}
+
+export default AESDecrypt;

+ 103 - 0
src/core/operations/AESEncrypt.mjs

@@ -0,0 +1,103 @@
+/**
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2016
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import Utils from "../Utils";
+import forge from "node-forge/dist/forge.min.js";
+
+/**
+ * AES Encrypt operation
+ */
+class AESEncrypt extends Operation {
+
+    /**
+     * AESEncrypt constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "AES Encrypt";
+        this.module = "Ciphers";
+        this.description = "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
+        this.inputType = "string";
+        this.outputType = "string";
+        this.args = [
+            {
+                "name": "Key",
+                "type": "toggleString",
+                "value": "",
+                "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
+            },
+            {
+                "name": "IV",
+                "type": "toggleString",
+                "value": "",
+                "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
+            },
+            {
+                "name": "Mode",
+                "type": "option",
+                "value": ["CBC", "CFB", "OFB", "CTR", "GCM", "ECB"]
+            },
+            {
+                "name": "Input",
+                "type": "option",
+                "value": ["Raw", "Hex"]
+            },
+            {
+                "name": "Output",
+                "type": "option",
+                "value": ["Hex", "Raw"]
+            }
+        ];
+    }
+
+    /**
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    run(input, args) {
+        const key = Utils.convertToByteArray(args[0].string, args[0].option),
+            iv = Utils.convertToByteArray(args[1].string, args[1].option),
+            mode = args[2],
+            inputType = args[3],
+            outputType = args[4];
+
+        if ([16, 24, 32].indexOf(key.length) < 0) {
+            return `Invalid key length: ${key.length} bytes
+
+The following algorithms will be used based on the size of the key:
+  16 bytes = AES-128
+  24 bytes = AES-192
+  32 bytes = AES-256`;
+        }
+
+        input = Utils.convertToByteString(input, inputType);
+
+        const cipher = forge.cipher.createCipher("AES-" + mode, key);
+        cipher.start({iv: iv});
+        cipher.update(forge.util.createBuffer(input));
+        cipher.finish();
+
+        if (outputType === "Hex") {
+            if (mode === "GCM") {
+                return cipher.output.toHex() + "\n\n" +
+                    "Tag: " + cipher.mode.tag.toHex();
+            }
+            return cipher.output.toHex();
+        } else {
+            if (mode === "GCM") {
+                return cipher.output.getBytes() + "\n\n" +
+                    "Tag: " + cipher.mode.tag.getBytes();
+            }
+            return cipher.output.getBytes();
+        }
+    }
+
+}
+
+export default AESEncrypt;

+ 4 - 0
webpack.config.js

@@ -69,6 +69,10 @@ module.exports = {
                 exclude: /node_modules\/(?!jsesc)/,
                 loader: "babel-loader?compact=false"
             },
+            {
+                test: /forge.min.js$/,
+                loader: "imports-loader?jQuery=>null"
+            },
             {
                 test: /\.css$/,
                 use: ExtractTextPlugin.extract({