cyberchef 9.36.1 → 9.37.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,7 +22,7 @@ class AESDecrypt extends Operation {
22
22
 
23
23
  this.name = "AES Decrypt";
24
24
  this.module = "Ciphers";
25
- 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.";
25
+ 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 as a default.<br><br><b>GCM Tag:</b> This field is ignored unless 'GCM' mode is used.";
26
26
  this.infoURL = "https://wikipedia.org/wiki/Advanced_Encryption_Standard";
27
27
  this.inputType = "string";
28
28
  this.outputType = "string";
@@ -66,6 +66,14 @@ class AESDecrypt extends Operation {
66
66
  {
67
67
  name: "ECB",
68
68
  off: [5, 6]
69
+ },
70
+ {
71
+ name: "CBC/NoPadding",
72
+ off: [5, 6]
73
+ },
74
+ {
75
+ name: "ECB/NoPadding",
76
+ off: [5, 6]
69
77
  }
70
78
  ]
71
79
  },
@@ -104,7 +112,8 @@ class AESDecrypt extends Operation {
104
112
  run(input, args) {
105
113
  const key = Utils.convertToByteString(args[0].string, args[0].option),
106
114
  iv = Utils.convertToByteString(args[1].string, args[1].option),
107
- mode = args[2],
115
+ mode = args[2].substring(0, 3),
116
+ noPadding = args[2].endsWith("NoPadding"),
108
117
  inputType = args[3],
109
118
  outputType = args[4],
110
119
  gcmTag = Utils.convertToByteString(args[5].string, args[5].option),
@@ -122,6 +131,14 @@ The following algorithms will be used based on the size of the key:
122
131
  input = Utils.convertToByteString(input, inputType);
123
132
 
124
133
  const decipher = forge.cipher.createDecipher("AES-" + mode, key);
134
+
135
+ /* Allow for a "no padding" mode */
136
+ if (noPadding) {
137
+ decipher.mode.unpad = function(output, options) {
138
+ return true;
139
+ };
140
+ }
141
+
125
142
  decipher.start({
126
143
  iv: iv.length === 0 ? "" : iv,
127
144
  tag: mode === "GCM" ? gcmTag : undefined,
@@ -22,7 +22,7 @@ class DESDecrypt extends Operation {
22
22
 
23
23
  this.name = "DES Decrypt";
24
24
  this.module = "Ciphers";
25
- this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
25
+ this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
26
26
  this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
27
27
  this.inputType = "string";
28
28
  this.outputType = "string";
@@ -42,7 +42,7 @@ class DESDecrypt extends Operation {
42
42
  {
43
43
  "name": "Mode",
44
44
  "type": "option",
45
- "value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
45
+ "value": ["CBC", "CFB", "OFB", "CTR", "ECB", "CBC/NoPadding", "ECB/NoPadding"]
46
46
  },
47
47
  {
48
48
  "name": "Input",
@@ -65,7 +65,9 @@ class DESDecrypt extends Operation {
65
65
  run(input, args) {
66
66
  const key = Utils.convertToByteString(args[0].string, args[0].option),
67
67
  iv = Utils.convertToByteArray(args[1].string, args[1].option),
68
- [,, mode, inputType, outputType] = args;
68
+ mode = args[2].substring(0, 3),
69
+ noPadding = args[2].endsWith("NoPadding"),
70
+ [,,, inputType, outputType] = args;
69
71
 
70
72
  if (key.length !== 8) {
71
73
  throw new OperationError(`Invalid key length: ${key.length} bytes
@@ -83,6 +85,14 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
83
85
  input = Utils.convertToByteString(input, inputType);
84
86
 
85
87
  const decipher = forge.cipher.createDecipher("DES-" + mode, key);
88
+
89
+ /* Allow for a "no padding" mode */
90
+ if (noPadding) {
91
+ decipher.mode.unpad = function(output, options) {
92
+ return true;
93
+ };
94
+ }
95
+
86
96
  decipher.start({iv: iv});
87
97
  decipher.update(forge.util.createBuffer(input));
88
98
  const result = decipher.finish();
@@ -43,9 +43,9 @@ class RC4Drop extends Operation {
43
43
  "value": ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Hex", "Base64"]
44
44
  },
45
45
  {
46
- "name": "Number of bytes to drop",
46
+ "name": "Number of dwords to drop",
47
47
  "type": "number",
48
- "value": 768
48
+ "value": 192
49
49
  }
50
50
  ];
51
51
  }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @author swesven
3
+ * @copyright 2021
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import Utils from "../Utils.mjs";
9
+ import OperationError from "../errors/OperationError.mjs";
10
+ import { toHex } from "../lib/Hex.mjs";
11
+ import { decryptSM4 } from "../lib/SM4.mjs";
12
+
13
+ /**
14
+ * SM4 Decrypt operation
15
+ */
16
+ class SM4Decrypt extends Operation {
17
+
18
+ /**
19
+ * SM4Encrypt constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "SM4 Decrypt";
25
+ this.module = "Ciphers";
26
+ this.description = "SM4 is a 128-bit block cipher, currently established as a national standard (GB/T 32907-2016) of China.";
27
+ this.infoURL = "https://wikipedia.org/wiki/SM4_(cipher)";
28
+ this.inputType = "string";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ },
37
+ {
38
+ "name": "IV",
39
+ "type": "toggleString",
40
+ "value": "",
41
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
42
+ },
43
+ {
44
+ "name": "Mode",
45
+ "type": "option",
46
+ "value": ["CBC", "CFB", "OFB", "CTR", "ECB", "CBC/NoPadding", "ECB/NoPadding"]
47
+ },
48
+ {
49
+ "name": "Input",
50
+ "type": "option",
51
+ "value": ["Raw", "Hex"]
52
+ },
53
+ {
54
+ "name": "Output",
55
+ "type": "option",
56
+ "value": ["Hex", "Raw"]
57
+ }
58
+ ];
59
+ }
60
+
61
+ /**
62
+ * @param {string} input
63
+ * @param {Object[]} args
64
+ * @returns {string}
65
+ */
66
+ run(input, args) {
67
+ const key = Utils.convertToByteArray(args[0].string, args[0].option),
68
+ iv = Utils.convertToByteArray(args[1].string, args[1].option),
69
+ [,, mode, inputType, outputType] = args;
70
+
71
+ if (key.length !== 16)
72
+ throw new OperationError(`Invalid key length: ${key.length} bytes
73
+
74
+ SM4 uses a key length of 16 bytes (128 bits).`);
75
+ if (iv.length !== 16 && !mode.startsWith("ECB"))
76
+ throw new OperationError(`Invalid IV length: ${iv.length} bytes
77
+
78
+ SM4 uses an IV length of 16 bytes (128 bits).
79
+ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
80
+
81
+ input = Utils.convertToByteArray(input, inputType);
82
+ const output = decryptSM4(input, key, iv, mode.substring(0, 3), mode.endsWith("NoPadding"));
83
+ return outputType === "Hex" ? toHex(output) : Utils.byteArrayToUtf8(output);
84
+ }
85
+
86
+ }
87
+
88
+ export default SM4Decrypt;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @author swesven
3
+ * @copyright 2021
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import Utils from "../Utils.mjs";
9
+ import OperationError from "../errors/OperationError.mjs";
10
+ import { toHex } from "../lib/Hex.mjs";
11
+ import { encryptSM4 } from "../lib/SM4.mjs";
12
+
13
+ /**
14
+ * SM4 Encrypt operation
15
+ */
16
+ class SM4Encrypt extends Operation {
17
+
18
+ /**
19
+ * SM4Encrypt constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "SM4 Encrypt";
25
+ this.module = "Ciphers";
26
+ this.description = "SM4 is a 128-bit block cipher, currently established as a national standard (GB/T 32907-2016) of China. Multiple block cipher modes are supported. When using CBC or ECB mode, the PKCS#7 padding scheme is used.";
27
+ this.infoURL = "https://wikipedia.org/wiki/SM4_(cipher)";
28
+ this.inputType = "string";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ },
37
+ {
38
+ "name": "IV",
39
+ "type": "toggleString",
40
+ "value": "",
41
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
42
+ },
43
+ {
44
+ "name": "Mode",
45
+ "type": "option",
46
+ "value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
47
+ },
48
+ {
49
+ "name": "Input",
50
+ "type": "option",
51
+ "value": ["Raw", "Hex"]
52
+ },
53
+ {
54
+ "name": "Output",
55
+ "type": "option",
56
+ "value": ["Hex", "Raw"]
57
+ }
58
+ ];
59
+ }
60
+
61
+ /**
62
+ * @param {string} input
63
+ * @param {Object[]} args
64
+ * @returns {string}
65
+ */
66
+ run(input, args) {
67
+ const key = Utils.convertToByteArray(args[0].string, args[0].option),
68
+ iv = Utils.convertToByteArray(args[1].string, args[1].option),
69
+ [,, mode, inputType, outputType] = args;
70
+
71
+ if (key.length !== 16)
72
+ throw new OperationError(`Invalid key length: ${key.length} bytes
73
+
74
+ SM4 uses a key length of 16 bytes (128 bits).`);
75
+ if (iv.length !== 16 && !mode.startsWith("ECB"))
76
+ throw new OperationError(`Invalid IV length: ${iv.length} bytes
77
+
78
+ SM4 uses an IV length of 16 bytes (128 bits).
79
+ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
80
+
81
+ input = Utils.convertToByteArray(input, inputType);
82
+ const output = encryptSM4(input, key, iv, mode.substring(0, 3), mode.endsWith("NoPadding"));
83
+ return outputType === "Hex" ? toHex(output) : Utils.byteArrayToUtf8(output);
84
+ }
85
+
86
+ }
87
+
88
+ export default SM4Encrypt;
@@ -43,9 +43,9 @@ class ToBase45 extends Operation {
43
43
  * @returns {string}
44
44
  */
45
45
  run(input, args) {
46
+ if (!input) return "";
46
47
  input = new Uint8Array(input);
47
48
  const alphabet = Utils.expandAlphRange(args[0]);
48
- if (!input) return "";
49
49
 
50
50
  const res = [];
51
51
 
@@ -22,7 +22,7 @@ class TripleDESDecrypt extends Operation {
22
22
 
23
23
  this.name = "Triple DES Decrypt";
24
24
  this.module = "Ciphers";
25
- this.description = "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
25
+ this.description = "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
26
26
  this.infoURL = "https://wikipedia.org/wiki/Triple_DES";
27
27
  this.inputType = "string";
28
28
  this.outputType = "string";
@@ -42,7 +42,7 @@ class TripleDESDecrypt extends Operation {
42
42
  {
43
43
  "name": "Mode",
44
44
  "type": "option",
45
- "value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
45
+ "value": ["CBC", "CFB", "OFB", "CTR", "ECB", "CBC/NoPadding", "ECB/NoPadding"]
46
46
  },
47
47
  {
48
48
  "name": "Input",
@@ -65,7 +65,8 @@ class TripleDESDecrypt extends Operation {
65
65
  run(input, args) {
66
66
  const key = Utils.convertToByteString(args[0].string, args[0].option),
67
67
  iv = Utils.convertToByteArray(args[1].string, args[1].option),
68
- mode = args[2],
68
+ mode = args[2].substring(0, 3),
69
+ noPadding = args[2].endsWith("NoPadding"),
69
70
  inputType = args[3],
70
71
  outputType = args[4];
71
72
 
@@ -85,6 +86,14 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
85
86
  input = Utils.convertToByteString(input, inputType);
86
87
 
87
88
  const decipher = forge.cipher.createDecipher("3DES-" + mode, key);
89
+
90
+ /* Allow for a "no padding" mode */
91
+ if (noPadding) {
92
+ decipher.mode.unpad = function(output, options) {
93
+ return true;
94
+ };
95
+ }
96
+
88
97
  decipher.start({iv: iv});
89
98
  decipher.update(forge.util.createBuffer(input));
90
99
  const result = decipher.finish();
@@ -277,6 +277,8 @@ import SHA2 from "./SHA2.mjs";
277
277
  import SHA3 from "./SHA3.mjs";
278
278
  import SIGABA from "./SIGABA.mjs";
279
279
  import SM3 from "./SM3.mjs";
280
+ import SM4Decrypt from "./SM4Decrypt.mjs";
281
+ import SM4Encrypt from "./SM4Encrypt.mjs";
280
282
  import SQLBeautify from "./SQLBeautify.mjs";
281
283
  import SQLMinify from "./SQLMinify.mjs";
282
284
  import SSDEEP from "./SSDEEP.mjs";
@@ -647,6 +649,8 @@ export {
647
649
  SHA3,
648
650
  SIGABA,
649
651
  SM3,
652
+ SM4Decrypt,
653
+ SM4Encrypt,
650
654
  SQLBeautify,
651
655
  SQLMinify,
652
656
  SSDEEP,
@@ -278,6 +278,8 @@ import {
278
278
  SHA3 as core_SHA3,
279
279
  SIGABA as core_SIGABA,
280
280
  SM3 as core_SM3,
281
+ SM4Decrypt as core_SM4Decrypt,
282
+ SM4Encrypt as core_SM4Encrypt,
281
283
  SQLBeautify as core_SQLBeautify,
282
284
  SQLMinify as core_SQLMinify,
283
285
  SSDEEP as core_SSDEEP,
@@ -648,6 +650,8 @@ function generateChef() {
648
650
  "SHA3": _wrap(core_SHA3),
649
651
  "SIGABA": _wrap(core_SIGABA),
650
652
  "SM3": _wrap(core_SM3),
653
+ "SM4Decrypt": _wrap(core_SM4Decrypt),
654
+ "SM4Encrypt": _wrap(core_SM4Encrypt),
651
655
  "SQLBeautify": _wrap(core_SQLBeautify),
652
656
  "SQLMinify": _wrap(core_SQLMinify),
653
657
  "SSDEEP": _wrap(core_SSDEEP),
@@ -1035,6 +1039,8 @@ const SHA2 = chef.SHA2;
1035
1039
  const SHA3 = chef.SHA3;
1036
1040
  const SIGABA = chef.SIGABA;
1037
1041
  const SM3 = chef.SM3;
1042
+ const SM4Decrypt = chef.SM4Decrypt;
1043
+ const SM4Encrypt = chef.SM4Encrypt;
1038
1044
  const SQLBeautify = chef.SQLBeautify;
1039
1045
  const SQLMinify = chef.SQLMinify;
1040
1046
  const SSDEEP = chef.SSDEEP;
@@ -1407,6 +1413,8 @@ const operations = [
1407
1413
  SHA3,
1408
1414
  SIGABA,
1409
1415
  SM3,
1416
+ SM4Decrypt,
1417
+ SM4Encrypt,
1410
1418
  SQLBeautify,
1411
1419
  SQLMinify,
1412
1420
  SSDEEP,
@@ -1783,6 +1791,8 @@ export {
1783
1791
  SHA3,
1784
1792
  SIGABA,
1785
1793
  SM3,
1794
+ SM4Decrypt,
1795
+ SM4Encrypt,
1786
1796
  SQLBeautify,
1787
1797
  SQLMinify,
1788
1798
  SSDEEP,
@@ -16,7 +16,8 @@ module.exports = {
16
16
  .click("#auto-bake-label");
17
17
  },
18
18
 
19
- "Sanity check operations": browser => {
19
+ "Sanity check operations": async browser => {
20
+ const Images = await import("../samples/Images.mjs");
20
21
  testOp(browser, "A1Z26 Cipher Decode", "20 5 19 20 15 21 20 16 21 20", "testoutput");
21
22
  testOp(browser, "A1Z26 Cipher Encode", "test input", "20 5 19 20 9 14 16 21 20");
22
23
  testOp(browser, "ADD", "test input", "Ê»ÉÊv¿ÄÆËÊ", [{ "option": "Hex", "string": "56" }]);
@@ -24,7 +25,7 @@ module.exports = {
24
25
  testOp(browser, "AES Encrypt", "test input", "e42eb8fbfb7a98fff061cd2c1a794d92", [{"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex"]);
25
26
  testOp(browser, "AND", "test input", "4$04 $044", [{ "option": "Hex", "string": "34" }]);
26
27
  testOp(browser, "Add line numbers", "test input", "1 test input");
27
- // testOp(browser, "Add Text To Image", "test input", "test_output");
28
+ testOp(browser, ["From Hex", "Add Text To Image", "To Base64"], Images.PNG_HEX, Images.PNG_CHEF_B64, [[], ["Chef", "Center", "Middle", 0, 0, 16], []]);
28
29
  testOp(browser, "Adler-32 Checksum", "test input", "16160411");
29
30
  testOp(browser, "Affine Cipher Decode", "test input", "rcqr glnsr", [1, 2]);
30
31
  testOp(browser, "Affine Cipher Encode", "test input", "njln rbfpn", [2, 1]);
@@ -44,12 +45,12 @@ module.exports = {
44
45
  // testOp(browser, "Bifid Cipher Encode", "test input", "test_output");
45
46
  // testOp(browser, "Bit shift left", "test input", "test_output");
46
47
  // testOp(browser, "Bit shift right", "test input", "test_output");
47
- // testOp(browser, "Blowfish Decrypt", "test input", "test_output");
48
- // testOp(browser, "Blowfish Encrypt", "test input", "test_output");
49
- // testOp(browser, "Blur Image", "test input", "test_output");
48
+ testOp(browser, "Blowfish Decrypt", "10884e15427dd84ec35204e9c8e921ae", "test_output", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Hex", "Raw"]);
49
+ testOp(browser, "Blowfish Encrypt", "test input", "f0fadbd1d90d774f714248cf26b96410", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Raw", "Hex"]);
50
+ testOp(browser, ["From Hex", "Blur Image", "To Base64"], Images.PNG_HEX, Images.PNG_BLUR_B64);
50
51
  // testOp(browser, "Bombe", "test input", "test_output");
51
- // testOp(browser, "Bzip2 Compress", "test input", "test_output");
52
- // testOp(browser, "Bzip2 Decompress", "test input", "test_output");
52
+ testOp(browser, ["Bzip2 Compress", "To Hex"], "test input", "42 5a 68 39 31 41 59 26 53 59 cf 96 82 1d 00 00 03 91 80 40 00 02 21 4e 00 20 00 21 90 c2 10 c0 88 33 92 8e df 17 72 45 38 50 90 cf 96 82 1d");
53
+ testOp(browser, ["From Hex", "Bzip2 Decompress"], "425a68393141592653597b0884b7000003038000008200ce00200021a647a4218013709517c5dc914e14241ec2212dc0", "test_output", [[], [true]]);
53
54
  // testOp(browser, "CRC-16 Checksum", "test input", "test_output");
54
55
  // testOp(browser, "CRC-32 Checksum", "test input", "test_output");
55
56
  // testOp(browser, "CRC-8 Checksum", "test input", "test_output");
@@ -69,10 +70,10 @@ module.exports = {
69
70
  // testOp(browser, "Comment", "test input", "test_output");
70
71
  // testOp(browser, "Compare CTPH hashes", "test input", "test_output");
71
72
  // testOp(browser, "Compare SSDEEP hashes", "test input", "test_output");
72
- // testOp(browser, "Conditional Jump", "test input", "test_output");
73
+ // /testOp(browser, "Conditional Jump", "test input", "test_output");
73
74
  // testOp(browser, "Contain Image", "test input", "test_output");
74
75
  // testOp(browser, "Convert area", "test input", "test_output");
75
- // testOp(browser, "Convert co-ordinate format", "test input", "test_output");
76
+ // /testOp(browser, "Convert co-ordinate format", "test input", "test_output");
76
77
  // testOp(browser, "Convert data units", "test input", "test_output");
77
78
  // testOp(browser, "Convert distance", "test input", "test_output");
78
79
  // testOp(browser, "Convert Image Format", "test input", "test_output");
@@ -197,10 +198,12 @@ module.exports = {
197
198
  // testOp(browser, "MD4", "test input", "test_output");
198
199
  // testOp(browser, "MD5", "test input", "test_output");
199
200
  // testOp(browser, "MD6", "test input", "test_output");
200
- // testOp(browser, "Magic", "test input", "test_output");
201
+ testOpHtml(browser, "Magic", "dGVzdF9vdXRwdXQ=", "tr:nth-of-type(1) th:nth-of-type(2)", "Result snippet");
202
+ testOpHtml(browser, "Magic", "dGVzdF9vdXRwdXQ=", "tr:nth-of-type(2) td:nth-of-type(2)", "test_output");
203
+ testOpHtml(browser, "Magic", "dGVzdF9vdXRwdXQ=", "tr:nth-of-type(2) td:nth-of-type(1)", /Base64/);
201
204
  // testOp(browser, "Mean", "test input", "test_output");
202
- // testOp(browser, "Median", "test input", "test_output");
203
- // testOp(browser, "Merge", "test input", "test_output");
205
+ // testOp(browser, "Median", "test input", "test_output");`
206
+ // testOp(browser, "Merge", "test input", "test_output");`
204
207
  // testOp(browser, "Microsoft Script Decoder", "test input", "test_output");
205
208
  // testOp(browser, "Multiple Bombe", "test input", "test_output");
206
209
  // testOp(browser, "Multiply", "test input", "test_output");
@@ -372,23 +375,36 @@ module.exports = {
372
375
  }
373
376
  };
374
377
 
375
- /**
376
- * Clears the current recipe and tests a new operation.
378
+ /** @function
379
+ * Clears the current recipe and bakes a new operation.
377
380
  *
378
- * @param {string} opName
379
- * @param {Browser} browser
381
+ * @param {Browser} browser - Nightwatch client
382
+ * @param {string|Array<string>} opName - name of operation to be tested, array for multiple ops
383
+ * @param {string} input - input text for test
384
+ * @param {Array<string>|Array<Array<string>>} args - aarguments, nested if multiple ops
380
385
  */
381
- function testOp(browser, opName, input, output, args=[]) {
386
+ function bakeOp(browser, opName, input, args=[]) {
387
+ let recipeConfig;
382
388
 
383
- const recipeConfig = JSON.stringify([{
384
- "op": opName,
385
- "args": args
386
- }]);
389
+ if (typeof(opName) === "string") {
390
+ recipeConfig = JSON.stringify([{
391
+ "op": opName,
392
+ "args": args
393
+ }]);
394
+ } else if (opName instanceof Array) {
395
+ recipeConfig = JSON.stringify(
396
+ opName.map((op, i) => {
397
+ return {
398
+ op: op,
399
+ args: args.length ? args[i] : []
400
+ };
401
+ })
402
+ );
403
+ } else {
404
+ throw new Error("Invalid operation type. Must be string or array of strings. Received: " + typeof(opName));
405
+ }
387
406
 
388
407
  browser
389
- .perform(function() {
390
- console.log(opName);
391
- })
392
408
  .useCss()
393
409
  .click("#clr-recipe")
394
410
  .click("#clr-io")
@@ -396,6 +412,9 @@ function testOp(browser, opName, input, output, args=[]) {
396
412
  .expect.element("#input-text").to.have.property("value").that.equals("");
397
413
 
398
414
  browser
415
+ .perform(function() {
416
+ console.log(`Current test: ${opName}`);
417
+ })
399
418
  .urlHash("recipe=" + recipeConfig)
400
419
  .setValue("#input-text", input)
401
420
  .waitForElementPresent("#rec-list li.operation")
@@ -408,6 +427,20 @@ function testOp(browser, opName, input, output, args=[]) {
408
427
  .pause(100)
409
428
  .waitForElementPresent("#stale-indicator.hidden", 5000)
410
429
  .waitForElementNotVisible("#output-loader", 5000);
430
+ }
431
+
432
+ /** @function
433
+ * Clears the current recipe and tests a new operation.
434
+ *
435
+ * @param {Browser} browser - Nightwatch client
436
+ * @param {string|Array<string>} opName - name of operation to be tested, array for multiple ops
437
+ * @param {string} input - input text
438
+ * @param {string} output - expected output
439
+ * @param {Array<string>|Array<Array<string>>} args - arguments, nested if multiple ops
440
+ */
441
+ function testOp(browser, opName, input, output, args=[]) {
442
+
443
+ bakeOp(browser, opName, input, args);
411
444
 
412
445
  if (typeof output === "string") {
413
446
  browser.expect.element("#output-text").to.have.property("value").that.equals(output);
@@ -415,3 +448,23 @@ function testOp(browser, opName, input, output, args=[]) {
415
448
  browser.expect.element("#output-text").to.have.property("value").that.matches(output);
416
449
  }
417
450
  }
451
+
452
+ /** @function
453
+ * Clears the current recipe and tests a new operation.
454
+ *
455
+ * @param {Browser} browser - Nightwatch client
456
+ * @param {string|Array<string>} opName - name of operation to be tested array for multiple ops
457
+ * @param {string} input - input text
458
+ * @param {string} cssSelector - CSS selector for HTML output
459
+ * @param {string} output - expected output
460
+ * @param {Array<string>|Array<Array<string>>} args - arguments, nested if multiple ops
461
+ */
462
+ function testOpHtml(browser, opName, input, cssSelector, output, args=[]) {
463
+ bakeOp(browser, opName, input, args);
464
+
465
+ if (typeof output === "string") {
466
+ browser.expect.element("#output-html " + cssSelector).text.that.equals(output);
467
+ } else if (output instanceof RegExp) {
468
+ browser.expect.element("#output-html " + cssSelector).text.that.matches(output);
469
+ }
470
+ }
@@ -119,7 +119,7 @@ TestRegister.addApiTests([
119
119
  assert.strictEqual(result[0].module, "Ciphers");
120
120
  assert.strictEqual(result[0].inputType, "string");
121
121
  assert.strictEqual(result[0].outputType, "string");
122
- assert.strictEqual(result[0].description, "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.");
122
+ assert.strictEqual(result[0].description, "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.");
123
123
  assert.strictEqual(result[0].args.length, 5);
124
124
  }),
125
125
 
@@ -816,7 +816,7 @@ pCGTErs=
816
816
  it("RC4 Drop", () => {
817
817
  assert.strictEqual(
818
818
  chef.RC4Drop("Go Out On a Limb", {passphrase: {string: "Under Your Nose", option: "UTF8"}, inputFormat: "UTF8", outputFormat: "Hex"}).toString(),
819
- "8fa5f2751d34476a0c857439f43816cf");
819
+ "b85cb1c4ed6bed8f260ab92829bba942");
820
820
  }),
821
821
 
822
822
  it("Regular Expression", () => {
@@ -75,6 +75,7 @@ import "./tests/SeqUtils.mjs";
75
75
  import "./tests/SetDifference.mjs";
76
76
  import "./tests/SetIntersection.mjs";
77
77
  import "./tests/SetUnion.mjs";
78
+ import "./tests/SM4.mjs";
78
79
  import "./tests/StrUtils.mjs";
79
80
  import "./tests/SymmetricDifference.mjs";
80
81
  import "./tests/TextEncodingBruteForce.mjs";
@@ -9,7 +9,7 @@
9
9
  * @license Apache-2.0
10
10
  */
11
11
  import TestRegister from "../../lib/TestRegister.mjs";
12
- import { GIF_ANIMATED_HEX, PNG_HEX, JPG_B64, EXIF_JPG_HEX, NO_EXIF_JPG_HEX } from "../samples/Images.mjs";
12
+ import { GIF_ANIMATED_HEX, PNG_HEX, JPG_B64, EXIF_JPG_HEX, NO_EXIF_JPG_HEX } from "../../samples/Images.mjs";
13
13
 
14
14
  TestRegister.addTests([
15
15
  {
@@ -7,7 +7,7 @@
7
7
  * @license Apache-2.0
8
8
  */
9
9
  import TestRegister from "../../lib/TestRegister.mjs";
10
- import { JPG_RAW } from "../samples/Images.mjs";
10
+ import { JPG_RAW } from "../../samples/Images.mjs";
11
11
 
12
12
  TestRegister.addTests([
13
13
  {
@@ -6,7 +6,7 @@
6
6
  * @license Apache-2.0
7
7
  */
8
8
  import TestRegister from "../../lib/TestRegister.mjs";
9
- import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../samples/Ciphers.mjs";
9
+ import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../../samples/Ciphers.mjs";
10
10
 
11
11
  // RSA-1024
12
12
  const ALICE_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK-----
@@ -6,7 +6,7 @@
6
6
  * @license Apache-2.0
7
7
  */
8
8
  import TestRegister from "../../lib/TestRegister.mjs";
9
- import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../samples/Ciphers.mjs";
9
+ import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../../samples/Ciphers.mjs";
10
10
 
11
11
  const PEM_PRIV_2048 = `-----BEGIN RSA PRIVATE KEY-----
12
12
  MIIEpAIBAAKCAQEAwfaUOpUEutKyU3wkCv6kYunz4MqxzSuTSckRz1IxwZtwIiqq