cyberchef 9.41.0 → 9.44.0

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.
package/CHANGELOG.md CHANGED
@@ -13,6 +13,15 @@ All major and minor version changes will be documented in this file. Details of
13
13
 
14
14
  ## Details
15
15
 
16
+ ### [9.43.0] - 2022-07-08
17
+ - Added 'ROT13 Brute Force' and 'ROT47 Brute Force' operations [@mikecat] | [#1264]
18
+
19
+ ### [9.42.0] - 2022-07-08
20
+ - Added 'LS47 Encrypt' and 'LS47 Decrypt' operations [@n1073645] | [#951]
21
+
22
+ ### [9.41.0] - 2022-07-08
23
+ - Added 'Caesar Box Cipher' operation [@n1073645] | [#1066]
24
+
16
25
  ### [9.40.0] - 2022-07-08
17
26
  - Added 'P-list Viewer' operation [@n1073645] | [#906]
18
27
 
@@ -297,6 +306,9 @@ All major and minor version changes will be documented in this file. Details of
297
306
 
298
307
 
299
308
 
309
+ [9.43.0]: https://github.com/gchq/CyberChef/releases/tag/v9.43.0
310
+ [9.42.0]: https://github.com/gchq/CyberChef/releases/tag/v9.42.0
311
+ [9.41.0]: https://github.com/gchq/CyberChef/releases/tag/v9.41.0
300
312
  [9.40.0]: https://github.com/gchq/CyberChef/releases/tag/v9.40.0
301
313
  [9.39.0]: https://github.com/gchq/CyberChef/releases/tag/v9.39.0
302
314
  [9.38.0]: https://github.com/gchq/CyberChef/releases/tag/v9.38.0
@@ -422,6 +434,7 @@ All major and minor version changes will be documented in this file. Details of
422
434
  [@t-8ch]: https://github.com/t-8ch
423
435
  [@hettysymes]: https://github.com/hettysymes
424
436
  [@swesven]: https://github.com/swesven
437
+ [@mikecat]: https://github.com/mikecat
425
438
 
426
439
  [8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
427
440
  [9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
@@ -500,6 +513,7 @@ All major and minor version changes will be documented in this file. Details of
500
513
  [#917]: https://github.com/gchq/CyberChef/pull/917
501
514
  [#934]: https://github.com/gchq/CyberChef/pull/934
502
515
  [#948]: https://github.com/gchq/CyberChef/pull/948
516
+ [#951]: https://github.com/gchq/CyberChef/pull/951
503
517
  [#952]: https://github.com/gchq/CyberChef/pull/952
504
518
  [#965]: https://github.com/gchq/CyberChef/pull/965
505
519
  [#966]: https://github.com/gchq/CyberChef/pull/966
@@ -511,6 +525,7 @@ All major and minor version changes will be documented in this file. Details of
511
525
  [#1045]: https://github.com/gchq/CyberChef/pull/1045
512
526
  [#1049]: https://github.com/gchq/CyberChef/pull/1049
513
527
  [#1065]: https://github.com/gchq/CyberChef/pull/1065
528
+ [#1066]: https://github.com/gchq/CyberChef/pull/1066
514
529
  [#1083]: https://github.com/gchq/CyberChef/pull/1083
515
530
  [#1189]: https://github.com/gchq/CyberChef/pull/1189
516
531
  [#1242]: https://github.com/gchq/CyberChef/pull/1242
@@ -518,3 +533,5 @@ All major and minor version changes will be documented in this file. Details of
518
533
  [#1313]: https://github.com/gchq/CyberChef/pull/1313
519
534
  [#1326]: https://github.com/gchq/CyberChef/pull/1326
520
535
  [#1364]: https://github.com/gchq/CyberChef/pull/1364
536
+ [#1264]: https://github.com/gchq/CyberChef/pull/1264
537
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberchef",
3
- "version": "9.41.0",
3
+ "version": "9.44.0",
4
4
  "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
5
5
  "author": "n1474335 <n1474335@gmail.com>",
6
6
  "homepage": "https://gchq.github.io/CyberChef",
@@ -133,6 +133,7 @@
133
133
  "lodash": "^4.17.21",
134
134
  "loglevel": "^1.8.0",
135
135
  "loglevel-message-prefix": "^3.0.0",
136
+ "lz-string": "^1.4.4",
136
137
  "markdown-it": "^13.0.1",
137
138
  "moment": "^2.29.3",
138
139
  "moment-timezone": "^0.5.34",
@@ -79,6 +79,8 @@
79
79
  "DES Decrypt",
80
80
  "Triple DES Encrypt",
81
81
  "Triple DES Decrypt",
82
+ "LS47 Encrypt",
83
+ "LS47 Decrypt",
82
84
  "RC2 Encrypt",
83
85
  "RC2 Decrypt",
84
86
  "RC4",
@@ -86,7 +88,9 @@
86
88
  "SM4 Encrypt",
87
89
  "SM4 Decrypt",
88
90
  "ROT13",
91
+ "ROT13 Brute Force",
89
92
  "ROT47",
93
+ "ROT47 Brute Force",
90
94
  "XOR",
91
95
  "XOR Brute Force",
92
96
  "Vigenère Encode",
@@ -321,7 +325,9 @@
321
325
  "Bzip2 Decompress",
322
326
  "Bzip2 Compress",
323
327
  "Tar",
324
- "Untar"
328
+ "Untar",
329
+ "LZString Compress",
330
+ "LZString Decompress"
325
331
  ]
326
332
  },
327
333
  {
@@ -7934,6 +7934,93 @@
7934
7934
  }
7935
7935
  ]
7936
7936
  },
7937
+ "LS47 Decrypt": {
7938
+ "module": "Crypto",
7939
+ "description": "This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky. We use 7x7 characters instead of original (barely fitting) 6x6, to be able to encrypt some structured information. We also describe a simple key-expansion algorithm, because remembering passwords is popular. Similar security considerations as with ElsieFour hold.<br>The LS47 alphabet consists of following characters: <code>_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()</code><br>An LS47 key is a permutation of the alphabet that is then represented in a 7x7 grid used for the encryption or decryption.",
7940
+ "infoURL": "https://github.com/exaexa/ls47",
7941
+ "inputType": "string",
7942
+ "outputType": "string",
7943
+ "flowControl": false,
7944
+ "manualBake": false,
7945
+ "args": [
7946
+ {
7947
+ "name": "Password",
7948
+ "type": "string",
7949
+ "value": ""
7950
+ },
7951
+ {
7952
+ "name": "Padding",
7953
+ "type": "number",
7954
+ "value": 10
7955
+ }
7956
+ ]
7957
+ },
7958
+ "LS47 Encrypt": {
7959
+ "module": "Crypto",
7960
+ "description": "This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky. We use 7x7 characters instead of original (barely fitting) 6x6, to be able to encrypt some structured information. We also describe a simple key-expansion algorithm, because remembering passwords is popular. Similar security considerations as with ElsieFour hold.<br>The LS47 alphabet consists of following characters: <code>_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()</code><br>A LS47 key is a permutation of the alphabet that is then represented in a 7x7 grid used for the encryption or decryption.",
7961
+ "infoURL": "https://github.com/exaexa/ls47",
7962
+ "inputType": "string",
7963
+ "outputType": "string",
7964
+ "flowControl": false,
7965
+ "manualBake": false,
7966
+ "args": [
7967
+ {
7968
+ "name": "Password",
7969
+ "type": "string",
7970
+ "value": ""
7971
+ },
7972
+ {
7973
+ "name": "Padding",
7974
+ "type": "number",
7975
+ "value": 10
7976
+ },
7977
+ {
7978
+ "name": "Signature",
7979
+ "type": "string",
7980
+ "value": ""
7981
+ }
7982
+ ]
7983
+ },
7984
+ "LZString Compress": {
7985
+ "module": "Compression",
7986
+ "description": "Compress the input with lz-string.",
7987
+ "infoURL": "https://pieroxy.net/blog/pages/lz-string/index.html",
7988
+ "inputType": "string",
7989
+ "outputType": "string",
7990
+ "flowControl": false,
7991
+ "manualBake": false,
7992
+ "args": [
7993
+ {
7994
+ "name": "Compression Format",
7995
+ "type": "option",
7996
+ "value": [
7997
+ "default",
7998
+ "UTF16",
7999
+ "Base64"
8000
+ ]
8001
+ }
8002
+ ]
8003
+ },
8004
+ "LZString Decompress": {
8005
+ "module": "Compression",
8006
+ "description": "Decompresses data that was compressed with lz-string.",
8007
+ "infoURL": "https://pieroxy.net/blog/pages/lz-string/index.html",
8008
+ "inputType": "string",
8009
+ "outputType": "string",
8010
+ "flowControl": false,
8011
+ "manualBake": false,
8012
+ "args": [
8013
+ {
8014
+ "name": "Compression Format",
8015
+ "type": "option",
8016
+ "value": [
8017
+ "default",
8018
+ "UTF16",
8019
+ "Base64"
8020
+ ]
8021
+ }
8022
+ ]
8023
+ },
7937
8024
  "Label": {
7938
8025
  "module": "Default",
7939
8026
  "description": "Provides a location for conditional and fixed jumps to redirect execution to.",
@@ -10131,6 +10218,52 @@
10131
10218
  }
10132
10219
  ]
10133
10220
  },
10221
+ "ROT13 Brute Force": {
10222
+ "module": "Default",
10223
+ "description": "Try all meaningful amounts for ROT13.<br><br>Optionally you can enter your known plaintext (crib) to filter the result.",
10224
+ "infoURL": "https://wikipedia.org/wiki/ROT13",
10225
+ "inputType": "byteArray",
10226
+ "outputType": "string",
10227
+ "flowControl": false,
10228
+ "manualBake": false,
10229
+ "args": [
10230
+ {
10231
+ "name": "Rotate lower case chars",
10232
+ "type": "boolean",
10233
+ "value": true
10234
+ },
10235
+ {
10236
+ "name": "Rotate upper case chars",
10237
+ "type": "boolean",
10238
+ "value": true
10239
+ },
10240
+ {
10241
+ "name": "Rotate numbers",
10242
+ "type": "boolean",
10243
+ "value": false
10244
+ },
10245
+ {
10246
+ "name": "Sample length",
10247
+ "type": "number",
10248
+ "value": 100
10249
+ },
10250
+ {
10251
+ "name": "Sample offset",
10252
+ "type": "number",
10253
+ "value": 0
10254
+ },
10255
+ {
10256
+ "name": "Print amount",
10257
+ "type": "boolean",
10258
+ "value": true
10259
+ },
10260
+ {
10261
+ "name": "Crib (known plaintext string)",
10262
+ "type": "string",
10263
+ "value": ""
10264
+ }
10265
+ ]
10266
+ },
10134
10267
  "ROT47": {
10135
10268
  "module": "Default",
10136
10269
  "description": "A slightly more complex variation of a caesar cipher, which includes ASCII characters from 33 '!' to 126 '~'. Default rotation: 47.",
@@ -10147,6 +10280,37 @@
10147
10280
  }
10148
10281
  ]
10149
10282
  },
10283
+ "ROT47 Brute Force": {
10284
+ "module": "Default",
10285
+ "description": "Try all meaningful amounts for ROT47.<br><br>Optionally you can enter your known plaintext (crib) to filter the result.",
10286
+ "infoURL": "https://wikipedia.org/wiki/ROT13#Variants",
10287
+ "inputType": "byteArray",
10288
+ "outputType": "string",
10289
+ "flowControl": false,
10290
+ "manualBake": false,
10291
+ "args": [
10292
+ {
10293
+ "name": "Sample length",
10294
+ "type": "number",
10295
+ "value": 100
10296
+ },
10297
+ {
10298
+ "name": "Sample offset",
10299
+ "type": "number",
10300
+ "value": 0
10301
+ },
10302
+ {
10303
+ "name": "Print amount",
10304
+ "type": "boolean",
10305
+ "value": true
10306
+ },
10307
+ {
10308
+ "name": "Crib (known plaintext string)",
10309
+ "type": "string",
10310
+ "value": ""
10311
+ }
10312
+ ]
10313
+ },
10150
10314
  "RSA Decrypt": {
10151
10315
  "module": "Ciphers",
10152
10316
  "description": "Decrypt an RSA encrypted message with a PEM encoded private key.",
@@ -9,6 +9,8 @@ import Bzip2Compress from "../../operations/Bzip2Compress.mjs";
9
9
  import Bzip2Decompress from "../../operations/Bzip2Decompress.mjs";
10
10
  import Gunzip from "../../operations/Gunzip.mjs";
11
11
  import Gzip from "../../operations/Gzip.mjs";
12
+ import LZStringCompress from "../../operations/LZStringCompress.mjs";
13
+ import LZStringDecompress from "../../operations/LZStringDecompress.mjs";
12
14
  import RawDeflate from "../../operations/RawDeflate.mjs";
13
15
  import RawInflate from "../../operations/RawInflate.mjs";
14
16
  import Tar from "../../operations/Tar.mjs";
@@ -25,6 +27,8 @@ OpModules.Compression = {
25
27
  "Bzip2 Decompress": Bzip2Decompress,
26
28
  "Gunzip": Gunzip,
27
29
  "Gzip": Gzip,
30
+ "LZString Compress": LZStringCompress,
31
+ "LZString Decompress": LZStringDecompress,
28
32
  "Raw Deflate": RawDeflate,
29
33
  "Raw Inflate": RawInflate,
30
34
  "Tar": Tar,
@@ -34,6 +34,8 @@ import JWTDecode from "../../operations/JWTDecode.mjs";
34
34
  import JWTSign from "../../operations/JWTSign.mjs";
35
35
  import JWTVerify from "../../operations/JWTVerify.mjs";
36
36
  import Keccak from "../../operations/Keccak.mjs";
37
+ import LS47Decrypt from "../../operations/LS47Decrypt.mjs";
38
+ import LS47Encrypt from "../../operations/LS47Encrypt.mjs";
37
39
  import MD2 from "../../operations/MD2.mjs";
38
40
  import MD4 from "../../operations/MD4.mjs";
39
41
  import MD5 from "../../operations/MD5.mjs";
@@ -83,6 +85,8 @@ OpModules.Crypto = {
83
85
  "JWT Sign": JWTSign,
84
86
  "JWT Verify": JWTVerify,
85
87
  "Keccak": Keccak,
88
+ "LS47 Decrypt": LS47Decrypt,
89
+ "LS47 Encrypt": LS47Encrypt,
86
90
  "MD2": MD2,
87
91
  "MD4": MD4,
88
92
  "MD5": MD5,
@@ -107,7 +107,9 @@ import ParseUNIXFilePermissions from "../../operations/ParseUNIXFilePermissions.
107
107
  import PlayMedia from "../../operations/PlayMedia.mjs";
108
108
  import PowerSet from "../../operations/PowerSet.mjs";
109
109
  import ROT13 from "../../operations/ROT13.mjs";
110
+ import ROT13BruteForce from "../../operations/ROT13BruteForce.mjs";
110
111
  import ROT47 from "../../operations/ROT47.mjs";
112
+ import ROT47BruteForce from "../../operations/ROT47BruteForce.mjs";
111
113
  import RemoveDiacritics from "../../operations/RemoveDiacritics.mjs";
112
114
  import RemoveLineNumbers from "../../operations/RemoveLineNumbers.mjs";
113
115
  import RemoveNullBytes from "../../operations/RemoveNullBytes.mjs";
@@ -277,7 +279,9 @@ OpModules.Default = {
277
279
  "Play Media": PlayMedia,
278
280
  "Power Set": PowerSet,
279
281
  "ROT13": ROT13,
282
+ "ROT13 Brute Force": ROT13BruteForce,
280
283
  "ROT47": ROT47,
284
+ "ROT47 Brute Force": ROT47BruteForce,
281
285
  "Remove Diacritics": RemoveDiacritics,
282
286
  "Remove line numbers": RemoveLineNumbers,
283
287
  "Remove null bytes": RemoveNullBytes,
@@ -0,0 +1,244 @@
1
+ /**
2
+ * @author n1073645 [n1073645@gmail.com]
3
+ * @copyright Crown Copyright 2020
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import OperationError from "../errors/OperationError.mjs";
8
+
9
+ const letters = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()";
10
+ const tiles = [];
11
+
12
+ /**
13
+ * Initialises the tiles with values and positions.
14
+ */
15
+ export function initTiles() {
16
+ for (let i = 0; i < 49; i++)
17
+ tiles.push([letters.charAt(i), [Math.floor(i/7), i % 7]]);
18
+ }
19
+
20
+ /**
21
+ * Rotates the key "down".
22
+ *
23
+ * @param {string} key
24
+ * @param {number} col
25
+ * @param {number} n
26
+ * @returns {string}
27
+ */
28
+ function rotateDown(key, col, n) {
29
+ const lines = [];
30
+ for (let i = 0; i < 7; i++)
31
+ lines.push(key.slice(i*7, (i + 1) * 7));
32
+ const lefts = [];
33
+ let mids = [];
34
+ const rights = [];
35
+ lines.forEach((element) => {
36
+ lefts.push(element.slice(0, col));
37
+ mids.push(element.charAt(col));
38
+ rights.push(element.slice(col+1));
39
+ });
40
+ n = (7 - n % 7) % 7;
41
+ mids = mids.slice(n).concat(mids.slice(0, n));
42
+ let result = "";
43
+ for (let i = 0; i < 7; i++)
44
+ result += lefts[i] + mids[i] + rights[i];
45
+ return result;
46
+ }
47
+
48
+ /**
49
+ * Rotates the key "right".
50
+ *
51
+ * @param {string} key
52
+ * @param {number} row
53
+ * @param {number} n
54
+ * @returns {string}
55
+ */
56
+ function rotateRight(key, row, n) {
57
+ const mid = key.slice(row * 7, (row + 1) * 7);
58
+ n = (7 - n % 7) % 7;
59
+ return key.slice(0, 7 * row) + mid.slice(n) + mid.slice(0, n) + key.slice(7 * (row + 1));
60
+ }
61
+
62
+ /**
63
+ * Finds the position of a letter in the tiles.
64
+ *
65
+ * @param {string} letter
66
+ * @returns {string}
67
+ */
68
+ function findIx(letter) {
69
+ for (let i = 0; i < tiles.length; i++)
70
+ if (tiles[i][0] === letter)
71
+ return tiles[i][1];
72
+ throw new OperationError("Letter " + letter + " is not included in LS47");
73
+ }
74
+
75
+ /**
76
+ * Derives key from the input password.
77
+ *
78
+ * @param {string} password
79
+ * @returns {string}
80
+ */
81
+ export function deriveKey(password) {
82
+ let i = 0;
83
+ let k = letters;
84
+ for (const c of password) {
85
+ const [row, col] = findIx(c);
86
+ k = rotateDown(rotateRight(k, i, col), i, row);
87
+ i = (i + 1) % 7;
88
+ }
89
+ return k;
90
+ }
91
+
92
+ /**
93
+ * Checks the key is a valid key.
94
+ *
95
+ * @param {string} key
96
+ */
97
+ function checkKey(key) {
98
+ if (key.length !== letters.length)
99
+ throw new OperationError("Wrong key size");
100
+ const counts = new Array();
101
+ for (let i = 0; i < letters.length; i++)
102
+ counts[letters.charAt(i)] = 0;
103
+ for (const elem of letters) {
104
+ if (letters.indexOf(elem) === -1)
105
+ throw new OperationError("Letter " + elem + " not in LS47");
106
+ counts[elem]++;
107
+ if (counts[elem] > 1)
108
+ throw new OperationError("Letter duplicated in the key");
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Finds the position of a letter in they key.
114
+ *
115
+ * @param {letter} key
116
+ * @param {string} letter
117
+ * @returns {object}
118
+ */
119
+ function findPos (key, letter) {
120
+ const index = key.indexOf(letter);
121
+ if (index >= 0 && index < 49)
122
+ return [Math.floor(index/7), index%7];
123
+ throw new OperationError("Letter " + letter + " is not in the key");
124
+ }
125
+
126
+ /**
127
+ * Returns the character at the position on the tiles.
128
+ *
129
+ * @param {string} key
130
+ * @param {object} coord
131
+ * @returns {string}
132
+ */
133
+ function findAtPos(key, coord) {
134
+ return key.charAt(coord[1] + (coord[0] * 7));
135
+ }
136
+
137
+ /**
138
+ * Returns new position by adding two positions.
139
+ *
140
+ * @param {object} a
141
+ * @param {object} b
142
+ * @returns {object}
143
+ */
144
+ function addPos(a, b) {
145
+ return [(a[0] + b[0]) % 7, (a[1] + b[1]) % 7];
146
+ }
147
+
148
+ /**
149
+ * Returns new position by subtracting two positions.
150
+ * Note: We have to manually do the remainder division, since JS does not
151
+ * operate correctly on negative numbers (e.g. -3 % 4 = -3 when it should be 1).
152
+ *
153
+ * @param {object} a
154
+ * @param {object} b
155
+ * @returns {object}
156
+ */
157
+ function subPos(a, b) {
158
+ const asub = a[0] - b[0];
159
+ const bsub = a[1] - b[1];
160
+ return [asub - (Math.floor(asub/7) * 7), bsub - (Math.floor(bsub/7) * 7)];
161
+ }
162
+
163
+ /**
164
+ * Encrypts the plaintext string.
165
+ *
166
+ * @param {string} key
167
+ * @param {string} plaintext
168
+ * @returns {string}
169
+ */
170
+ function encrypt(key, plaintext) {
171
+ checkKey(key);
172
+ let mp = [0, 0];
173
+ let ciphertext = "";
174
+ for (const p of plaintext) {
175
+ const pp = findPos(key, p);
176
+ const mix = findIx(findAtPos(key, mp));
177
+ let cp = addPos(pp, mix);
178
+ const c = findAtPos(key, cp);
179
+ ciphertext += c;
180
+ key = rotateRight(key, pp[0], 1);
181
+ cp = findPos(key, c);
182
+ key = rotateDown(key, cp[1], 1);
183
+ mp = addPos(mp, findIx(c));
184
+ }
185
+ return ciphertext;
186
+ }
187
+
188
+ /**
189
+ * Decrypts the ciphertext string.
190
+ *
191
+ * @param {string} key
192
+ * @param {string} ciphertext
193
+ * @returns {string}
194
+ */
195
+ function decrypt(key, ciphertext) {
196
+ checkKey(key);
197
+ let mp = [0, 0];
198
+ let plaintext = "";
199
+ for (const c of ciphertext) {
200
+ let cp = findPos(key, c);
201
+ const mix = findIx(findAtPos(key, mp));
202
+ const pp = subPos(cp, mix);
203
+ const p = findAtPos(key, pp);
204
+ plaintext += p;
205
+ key = rotateRight(key, pp[0], 1);
206
+ cp = findPos(key, c);
207
+ key = rotateDown(key, cp[1], 1);
208
+ mp = addPos(mp, findIx(c));
209
+ }
210
+ return plaintext;
211
+ }
212
+
213
+ /**
214
+ * Adds padding to the input.
215
+ *
216
+ * @param {string} key
217
+ * @param {string} plaintext
218
+ * @param {string} signature
219
+ * @param {number} paddingSize
220
+ * @returns {string}
221
+ */
222
+ export function encryptPad(key, plaintext, signature, paddingSize) {
223
+ initTiles();
224
+ checkKey(key);
225
+ let padding = "";
226
+ for (let i = 0; i < paddingSize; i++) {
227
+ padding += letters.charAt(Math.floor(Math.random() * letters.length));
228
+ }
229
+ return encrypt(key, padding+plaintext+"---"+signature);
230
+ }
231
+
232
+ /**
233
+ * Removes padding from the ouput.
234
+ *
235
+ * @param {string} key
236
+ * @param {string} ciphertext
237
+ * @param {number} paddingSize
238
+ * @returns {string}
239
+ */
240
+ export function decryptPad(key, ciphertext, paddingSize) {
241
+ initTiles();
242
+ checkKey(key);
243
+ return decrypt(key, ciphertext).slice(paddingSize);
244
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * lz-string exports.
3
+ *
4
+ * @author crespyl [peter@crespyl.net]
5
+ * @copyright Peter Jacobs 2021
6
+ * @license Apache-2.0
7
+ */
8
+
9
+ import LZString from "lz-string";
10
+
11
+ export const COMPRESSION_OUTPUT_FORMATS = ["default", "UTF16", "Base64"];
12
+ export const COMPRESSION_FUNCTIONS = {
13
+ "default": LZString.compress,
14
+ "UTF16": LZString.compressToUTF16,
15
+ "Base64": LZString.compressToBase64,
16
+ };
17
+ export const DECOMPRESSION_FUNCTIONS = {
18
+ "default": LZString.decompress,
19
+ "UTF16": LZString.decompressFromUTF16,
20
+ "Base64": LZString.decompressFromBase64,
21
+ };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @author n1073645 [n1073645@gmail.com]
3
+ * @copyright Crown Copyright 2020
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import * as LS47 from "../lib/LS47.mjs";
9
+
10
+ /**
11
+ * LS47 Decrypt operation
12
+ */
13
+ class LS47Decrypt extends Operation {
14
+
15
+ /**
16
+ * LS47Decrypt constructor
17
+ */
18
+ constructor() {
19
+ super();
20
+
21
+ this.name = "LS47 Decrypt";
22
+ this.module = "Crypto";
23
+ this.description = "This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky. We use 7x7 characters instead of original (barely fitting) 6x6, to be able to encrypt some structured information. We also describe a simple key-expansion algorithm, because remembering passwords is popular. Similar security considerations as with ElsieFour hold.<br>The LS47 alphabet consists of following characters: <code>_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()</code><br>An LS47 key is a permutation of the alphabet that is then represented in a 7x7 grid used for the encryption or decryption.";
24
+ this.infoURL = "https://github.com/exaexa/ls47";
25
+ this.inputType = "string";
26
+ this.outputType = "string";
27
+ this.args = [
28
+ {
29
+ name: "Password",
30
+ type: "string",
31
+ value: ""
32
+ },
33
+ {
34
+ name: "Padding",
35
+ type: "number",
36
+ value: 10
37
+ }
38
+ ];
39
+ }
40
+
41
+ /**
42
+ * @param {string} input
43
+ * @param {Object[]} args
44
+ * @returns {string}
45
+ */
46
+ run(input, args) {
47
+ this.paddingSize = parseInt(args[1], 10);
48
+
49
+ LS47.initTiles();
50
+
51
+ const key = LS47.deriveKey(args[0]);
52
+ return LS47.decryptPad(key, input, this.paddingSize);
53
+ }
54
+
55
+ }
56
+
57
+ export default LS47Decrypt;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @author n1073645 [n1073645@gmail.com]
3
+ * @copyright Crown Copyright 2020
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import * as LS47 from "../lib/LS47.mjs";
9
+
10
+ /**
11
+ * LS47 Encrypt operation
12
+ */
13
+ class LS47Encrypt extends Operation {
14
+
15
+ /**
16
+ * LS47Encrypt constructor
17
+ */
18
+ constructor() {
19
+ super();
20
+
21
+ this.name = "LS47 Encrypt";
22
+ this.module = "Crypto";
23
+ this.description = "This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky. We use 7x7 characters instead of original (barely fitting) 6x6, to be able to encrypt some structured information. We also describe a simple key-expansion algorithm, because remembering passwords is popular. Similar security considerations as with ElsieFour hold.<br>The LS47 alphabet consists of following characters: <code>_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()</code><br>A LS47 key is a permutation of the alphabet that is then represented in a 7x7 grid used for the encryption or decryption.";
24
+ this.infoURL = "https://github.com/exaexa/ls47";
25
+ this.inputType = "string";
26
+ this.outputType = "string";
27
+ this.args = [
28
+ {
29
+ name: "Password",
30
+ type: "string",
31
+ value: ""
32
+ },
33
+ {
34
+ name: "Padding",
35
+ type: "number",
36
+ value: 10
37
+ },
38
+ {
39
+ name: "Signature",
40
+ type: "string",
41
+ value: ""
42
+ }
43
+ ];
44
+ }
45
+
46
+ /**
47
+ * @param {string} input
48
+ * @param {Object[]} args
49
+ * @returns {string}
50
+ */
51
+ run(input, args) {
52
+ this.paddingSize = parseInt(args[1], 10);
53
+
54
+ LS47.initTiles();
55
+
56
+ const key = LS47.deriveKey(args[0]);
57
+ return LS47.encryptPad(key, input, args[2], this.paddingSize);
58
+ }
59
+
60
+ }
61
+
62
+ export default LS47Encrypt;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @author crespyl [peter@crespyl.net]
3
+ * @copyright Peter Jacobs 2021
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+
10
+ import {COMPRESSION_OUTPUT_FORMATS, COMPRESSION_FUNCTIONS} from "../lib/LZString.mjs";
11
+
12
+ /**
13
+ * LZString Compress operation
14
+ */
15
+ class LZStringCompress extends Operation {
16
+
17
+ /**
18
+ * LZStringCompress constructor
19
+ */
20
+ constructor() {
21
+ super();
22
+
23
+ this.name = "LZString Compress";
24
+ this.module = "Compression";
25
+ this.description = "Compress the input with lz-string.";
26
+ this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html";
27
+ this.inputType = "string";
28
+ this.outputType = "string";
29
+ this.args = [
30
+ {
31
+ name: "Compression Format",
32
+ type: "option",
33
+ defaultIndex: 0,
34
+ value: COMPRESSION_OUTPUT_FORMATS
35
+ }
36
+ ];
37
+ }
38
+
39
+ /**
40
+ * @param {string} input
41
+ * @param {Object[]} args
42
+ * @returns {string}
43
+ */
44
+ run(input, args) {
45
+ const compress = COMPRESSION_FUNCTIONS[args[0]];
46
+ if (compress) {
47
+ return compress(input);
48
+ } else {
49
+ throw new OperationError("Unable to find compression function");
50
+ }
51
+ }
52
+
53
+ }
54
+
55
+ export default LZStringCompress;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @author crespyl [peter@crespyl.net]
3
+ * @copyright Peter Jacobs 2021
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+
10
+ import {COMPRESSION_OUTPUT_FORMATS, DECOMPRESSION_FUNCTIONS} from "../lib/LZString.mjs";
11
+
12
+ /**
13
+ * LZString Decompress operation
14
+ */
15
+ class LZStringDecompress extends Operation {
16
+
17
+ /**
18
+ * LZStringDecompress constructor
19
+ */
20
+ constructor() {
21
+ super();
22
+
23
+ this.name = "LZString Decompress";
24
+ this.module = "Compression";
25
+ this.description = "Decompresses data that was compressed with lz-string.";
26
+ this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html";
27
+ this.inputType = "string";
28
+ this.outputType = "string";
29
+ this.args = [
30
+ {
31
+ name: "Compression Format",
32
+ type: "option",
33
+ defaultIndex: 0,
34
+ value: COMPRESSION_OUTPUT_FORMATS
35
+ }
36
+ ];
37
+ }
38
+
39
+ /**
40
+ * @param {string} input
41
+ * @param {Object[]} args
42
+ * @returns {string}
43
+ */
44
+ run(input, args) {
45
+ const decompress = DECOMPRESSION_FUNCTIONS[args[0]];
46
+ if (decompress) {
47
+ return decompress(input);
48
+ } else {
49
+ throw new OperationError("Unable to find decompression function");
50
+ }
51
+ }
52
+
53
+
54
+ }
55
+
56
+ export default LZStringDecompress;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @author MikeCAT
3
+ * @license Apache-2.0
4
+ */
5
+
6
+ import Operation from "../Operation.mjs";
7
+ import Utils from "../Utils.mjs";
8
+
9
+ /**
10
+ * ROT13 Brute Force operation.
11
+ */
12
+ class ROT13BruteForce extends Operation {
13
+
14
+ /**
15
+ * ROT13BruteForce constructor
16
+ */
17
+ constructor() {
18
+ super();
19
+
20
+ this.name = "ROT13 Brute Force";
21
+ this.module = "Default";
22
+ this.description = "Try all meaningful amounts for ROT13.<br><br>Optionally you can enter your known plaintext (crib) to filter the result.";
23
+ this.infoURL = "https://wikipedia.org/wiki/ROT13";
24
+ this.inputType = "byteArray";
25
+ this.outputType = "string";
26
+ this.args = [
27
+ {
28
+ name: "Rotate lower case chars",
29
+ type: "boolean",
30
+ value: true
31
+ },
32
+ {
33
+ name: "Rotate upper case chars",
34
+ type: "boolean",
35
+ value: true
36
+ },
37
+ {
38
+ name: "Rotate numbers",
39
+ type: "boolean",
40
+ value: false
41
+ },
42
+ {
43
+ name: "Sample length",
44
+ type: "number",
45
+ value: 100
46
+ },
47
+ {
48
+ name: "Sample offset",
49
+ type: "number",
50
+ value: 0
51
+ },
52
+ {
53
+ name: "Print amount",
54
+ type: "boolean",
55
+ value: true
56
+ },
57
+ {
58
+ name: "Crib (known plaintext string)",
59
+ type: "string",
60
+ value: ""
61
+ }
62
+ ];
63
+ }
64
+
65
+ /**
66
+ * @param {byteArray} input
67
+ * @param {Object[]} args
68
+ * @returns {string}
69
+ */
70
+ run(input, args) {
71
+ const [rotateLower, rotateUpper, rotateNum, sampleLength, sampleOffset, printAmount, crib] = args;
72
+ const sample = input.slice(sampleOffset, sampleOffset + sampleLength);
73
+ const cribLower = crib.toLowerCase();
74
+ const lowerStart = "a".charCodeAt(0), upperStart = "A".charCodeAt(0), numStart = "0".charCodeAt(0);
75
+ const result = [];
76
+ for (let amount = 1; amount < 26; amount++) {
77
+ const rotated = sample.slice();
78
+ for (let i = 0; i < rotated.length; i++) {
79
+ if (rotateLower && lowerStart <= rotated[i] && rotated[i] < lowerStart + 26) {
80
+ rotated[i] = (rotated[i] - lowerStart + amount) % 26 + lowerStart;
81
+ } else if (rotateUpper && upperStart <= rotated[i] && rotated[i] < upperStart + 26) {
82
+ rotated[i] = (rotated[i] - upperStart + amount) % 26 + upperStart;
83
+ } else if (rotateNum && numStart <= rotated[i] && rotated[i] < numStart + 10) {
84
+ rotated[i] = (rotated[i] - numStart + amount) % 10 + numStart;
85
+ }
86
+ }
87
+ const rotatedString = Utils.byteArrayToUtf8(rotated);
88
+ if (rotatedString.toLowerCase().indexOf(cribLower) >= 0) {
89
+ const rotatedStringPrintable = Utils.printable(rotatedString, false);
90
+ if (printAmount) {
91
+ const amountStr = "Amount = " + (" " + amount).slice(-2) + ": ";
92
+ result.push(amountStr + rotatedStringPrintable);
93
+ } else {
94
+ result.push(rotatedStringPrintable);
95
+ }
96
+ }
97
+ }
98
+ return result.join("\n");
99
+ }
100
+ }
101
+
102
+ export default ROT13BruteForce;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @author MikeCAT
3
+ * @license Apache-2.0
4
+ */
5
+
6
+ import Operation from "../Operation.mjs";
7
+ import Utils from "../Utils.mjs";
8
+
9
+ /**
10
+ * ROT47 Brute Force operation.
11
+ */
12
+ class ROT47BruteForce extends Operation {
13
+
14
+ /**
15
+ * ROT47BruteForce constructor
16
+ */
17
+ constructor() {
18
+ super();
19
+
20
+ this.name = "ROT47 Brute Force";
21
+ this.module = "Default";
22
+ this.description = "Try all meaningful amounts for ROT47.<br><br>Optionally you can enter your known plaintext (crib) to filter the result.";
23
+ this.infoURL = "https://wikipedia.org/wiki/ROT13#Variants";
24
+ this.inputType = "byteArray";
25
+ this.outputType = "string";
26
+ this.args = [
27
+ {
28
+ name: "Sample length",
29
+ type: "number",
30
+ value: 100
31
+ },
32
+ {
33
+ name: "Sample offset",
34
+ type: "number",
35
+ value: 0
36
+ },
37
+ {
38
+ name: "Print amount",
39
+ type: "boolean",
40
+ value: true
41
+ },
42
+ {
43
+ name: "Crib (known plaintext string)",
44
+ type: "string",
45
+ value: ""
46
+ }
47
+ ];
48
+ }
49
+
50
+ /**
51
+ * @param {byteArray} input
52
+ * @param {Object[]} args
53
+ * @returns {string}
54
+ */
55
+ run(input, args) {
56
+ const [sampleLength, sampleOffset, printAmount, crib] = args;
57
+ const sample = input.slice(sampleOffset, sampleOffset + sampleLength);
58
+ const cribLower = crib.toLowerCase();
59
+ const result = [];
60
+ for (let amount = 1; amount < 94; amount++) {
61
+ const rotated = sample.slice();
62
+ for (let i = 0; i < rotated.length; i++) {
63
+ if (33 <= rotated[i] && rotated[i] <= 126) {
64
+ rotated[i] = (rotated[i] - 33 + amount) % 94 + 33;
65
+ }
66
+ }
67
+ const rotatedString = Utils.byteArrayToUtf8(rotated);
68
+ if (rotatedString.toLowerCase().indexOf(cribLower) >= 0) {
69
+ const rotatedStringPrintable = Utils.printable(rotatedString, false);
70
+ if (printAmount) {
71
+ const amountStr = "Amount = " + (" " + amount).slice(-2) + ": ";
72
+ result.push(amountStr + rotatedStringPrintable);
73
+ } else {
74
+ result.push(rotatedStringPrintable);
75
+ }
76
+ }
77
+ }
78
+ return result.join("\n");
79
+ }
80
+ }
81
+
82
+ export default ROT47BruteForce;
@@ -192,6 +192,10 @@ import JavaScriptMinify from "./JavaScriptMinify.mjs";
192
192
  import JavaScriptParser from "./JavaScriptParser.mjs";
193
193
  import Jump from "./Jump.mjs";
194
194
  import Keccak from "./Keccak.mjs";
195
+ import LS47Decrypt from "./LS47Decrypt.mjs";
196
+ import LS47Encrypt from "./LS47Encrypt.mjs";
197
+ import LZStringCompress from "./LZStringCompress.mjs";
198
+ import LZStringDecompress from "./LZStringDecompress.mjs";
195
199
  import Label from "./Label.mjs";
196
200
  import Lorenz from "./Lorenz.mjs";
197
201
  import LuhnChecksum from "./LuhnChecksum.mjs";
@@ -250,7 +254,9 @@ import RC4 from "./RC4.mjs";
250
254
  import RC4Drop from "./RC4Drop.mjs";
251
255
  import RIPEMD from "./RIPEMD.mjs";
252
256
  import ROT13 from "./ROT13.mjs";
257
+ import ROT13BruteForce from "./ROT13BruteForce.mjs";
253
258
  import ROT47 from "./ROT47.mjs";
259
+ import ROT47BruteForce from "./ROT47BruteForce.mjs";
254
260
  import RSADecrypt from "./RSADecrypt.mjs";
255
261
  import RSAEncrypt from "./RSAEncrypt.mjs";
256
262
  import RSASign from "./RSASign.mjs";
@@ -568,6 +574,10 @@ export {
568
574
  JavaScriptParser,
569
575
  Jump,
570
576
  Keccak,
577
+ LS47Decrypt,
578
+ LS47Encrypt,
579
+ LZStringCompress,
580
+ LZStringDecompress,
571
581
  Label,
572
582
  Lorenz,
573
583
  LuhnChecksum,
@@ -626,7 +636,9 @@ export {
626
636
  RC4Drop,
627
637
  RIPEMD,
628
638
  ROT13,
639
+ ROT13BruteForce,
629
640
  ROT47,
641
+ ROT47BruteForce,
630
642
  RSADecrypt,
631
643
  RSAEncrypt,
632
644
  RSASign,
@@ -195,6 +195,10 @@ import {
195
195
  JWTSign as core_JWTSign,
196
196
  JWTVerify as core_JWTVerify,
197
197
  Keccak as core_Keccak,
198
+ LS47Decrypt as core_LS47Decrypt,
199
+ LS47Encrypt as core_LS47Encrypt,
200
+ LZStringCompress as core_LZStringCompress,
201
+ LZStringDecompress as core_LZStringDecompress,
198
202
  Lorenz as core_Lorenz,
199
203
  LuhnChecksum as core_LuhnChecksum,
200
204
  MD2 as core_MD2,
@@ -251,7 +255,9 @@ import {
251
255
  RC4Drop as core_RC4Drop,
252
256
  RIPEMD as core_RIPEMD,
253
257
  ROT13 as core_ROT13,
258
+ ROT13BruteForce as core_ROT13BruteForce,
254
259
  ROT47 as core_ROT47,
260
+ ROT47BruteForce as core_ROT47BruteForce,
255
261
  RSADecrypt as core_RSADecrypt,
256
262
  RSAEncrypt as core_RSAEncrypt,
257
263
  RSASign as core_RSASign,
@@ -571,6 +577,10 @@ function generateChef() {
571
577
  "JWTSign": _wrap(core_JWTSign),
572
578
  "JWTVerify": _wrap(core_JWTVerify),
573
579
  "keccak": _wrap(core_Keccak),
580
+ "LS47Decrypt": _wrap(core_LS47Decrypt),
581
+ "LS47Encrypt": _wrap(core_LS47Encrypt),
582
+ "LZStringCompress": _wrap(core_LZStringCompress),
583
+ "LZStringDecompress": _wrap(core_LZStringDecompress),
574
584
  "lorenz": _wrap(core_Lorenz),
575
585
  "luhnChecksum": _wrap(core_LuhnChecksum),
576
586
  "MD2": _wrap(core_MD2),
@@ -627,7 +637,9 @@ function generateChef() {
627
637
  "RC4Drop": _wrap(core_RC4Drop),
628
638
  "RIPEMD": _wrap(core_RIPEMD),
629
639
  "ROT13": _wrap(core_ROT13),
640
+ "ROT13BruteForce": _wrap(core_ROT13BruteForce),
630
641
  "ROT47": _wrap(core_ROT47),
642
+ "ROT47BruteForce": _wrap(core_ROT47BruteForce),
631
643
  "RSADecrypt": _wrap(core_RSADecrypt),
632
644
  "RSAEncrypt": _wrap(core_RSAEncrypt),
633
645
  "RSASign": _wrap(core_RSASign),
@@ -962,6 +974,10 @@ const javaScriptMinify = chef.javaScriptMinify;
962
974
  const javaScriptParser = chef.javaScriptParser;
963
975
  const jump = chef.jump;
964
976
  const keccak = chef.keccak;
977
+ const LS47Decrypt = chef.LS47Decrypt;
978
+ const LS47Encrypt = chef.LS47Encrypt;
979
+ const LZStringCompress = chef.LZStringCompress;
980
+ const LZStringDecompress = chef.LZStringDecompress;
965
981
  const label = chef.label;
966
982
  const lorenz = chef.lorenz;
967
983
  const luhnChecksum = chef.luhnChecksum;
@@ -1020,7 +1036,9 @@ const RC4 = chef.RC4;
1020
1036
  const RC4Drop = chef.RC4Drop;
1021
1037
  const RIPEMD = chef.RIPEMD;
1022
1038
  const ROT13 = chef.ROT13;
1039
+ const ROT13BruteForce = chef.ROT13BruteForce;
1023
1040
  const ROT47 = chef.ROT47;
1041
+ const ROT47BruteForce = chef.ROT47BruteForce;
1024
1042
  const RSADecrypt = chef.RSADecrypt;
1025
1043
  const RSAEncrypt = chef.RSAEncrypt;
1026
1044
  const RSASign = chef.RSASign;
@@ -1340,6 +1358,10 @@ const operations = [
1340
1358
  javaScriptParser,
1341
1359
  jump,
1342
1360
  keccak,
1361
+ LS47Decrypt,
1362
+ LS47Encrypt,
1363
+ LZStringCompress,
1364
+ LZStringDecompress,
1343
1365
  label,
1344
1366
  lorenz,
1345
1367
  luhnChecksum,
@@ -1398,7 +1420,9 @@ const operations = [
1398
1420
  RC4Drop,
1399
1421
  RIPEMD,
1400
1422
  ROT13,
1423
+ ROT13BruteForce,
1401
1424
  ROT47,
1425
+ ROT47BruteForce,
1402
1426
  RSADecrypt,
1403
1427
  RSAEncrypt,
1404
1428
  RSASign,
@@ -1722,6 +1746,10 @@ export {
1722
1746
  javaScriptParser,
1723
1747
  jump,
1724
1748
  keccak,
1749
+ LS47Decrypt,
1750
+ LS47Encrypt,
1751
+ LZStringCompress,
1752
+ LZStringDecompress,
1725
1753
  label,
1726
1754
  lorenz,
1727
1755
  luhnChecksum,
@@ -1780,7 +1808,9 @@ export {
1780
1808
  RC4Drop,
1781
1809
  RIPEMD,
1782
1810
  ROT13,
1811
+ ROT13BruteForce,
1783
1812
  ROT47,
1813
+ ROT47BruteForce,
1784
1814
  RSADecrypt,
1785
1815
  RSAEncrypt,
1786
1816
  RSASign,
@@ -117,6 +117,8 @@ import "./tests/SIGABA.mjs";
117
117
  import "./tests/ELFInfo.mjs";
118
118
  import "./tests/Subsection.mjs";
119
119
  import "./tests/CaesarBoxCipher.mjs";
120
+ import "./tests/LS47.mjs";
121
+ import "./tests/LZString.mjs";
120
122
 
121
123
 
122
124
  // Cannot test operations that use the File type yet
@@ -0,0 +1,45 @@
1
+ /**
2
+ * LS47 tests.
3
+ *
4
+ * @author n1073645 [n1073645@gmail.com]
5
+ *
6
+ * @copyright Crown Copyright 2020
7
+ * @license Apache-2.0
8
+ */
9
+ import TestRegister from "../../lib/TestRegister.mjs";
10
+
11
+ TestRegister.addTests([
12
+ {
13
+ name: "LS47 Encrypt",
14
+ input: "thequickbrownfoxjumped",
15
+ expectedOutput: "(,t74ci78cp/8trx*yesu:alp1wqy",
16
+ recipeConfig: [
17
+ {
18
+ op: "LS47 Encrypt",
19
+ args: ["helloworld", 0, "test"],
20
+ },
21
+ ],
22
+ },
23
+ {
24
+ name: "LS47 Decrypt",
25
+ input: "(,t74ci78cp/8trx*yesu:alp1wqy",
26
+ expectedOutput: "thequickbrownfoxjumped---test",
27
+ recipeConfig: [
28
+ {
29
+ op: "LS47 Decrypt",
30
+ args: ["helloworld", 0],
31
+ },
32
+ ],
33
+ },
34
+ {
35
+ name: "LS47 Encrypt",
36
+ input: "thequickbrownfoxjumped",
37
+ expectedOutput: "Letter H is not included in LS47",
38
+ recipeConfig: [
39
+ {
40
+ op: "LS47 Encrypt",
41
+ args: ["Helloworld", 0, "test"],
42
+ },
43
+ ],
44
+ }
45
+ ]);
@@ -0,0 +1,33 @@
1
+ /**
2
+ * LZString tests.
3
+ *
4
+ * @author crespyl [peter@crespyl.net]
5
+ * @copyright Peter Jacobs 2021
6
+ * @license Apache-2.0
7
+ */
8
+ import TestRegister from "../../lib/TestRegister.mjs";
9
+
10
+ TestRegister.addTests([
11
+ {
12
+ name: "LZString Compress To Base64",
13
+ input: "hello world",
14
+ expectedOutput: "BYUwNmD2AEDukCcwBMg=",
15
+ recipeConfig: [
16
+ {
17
+ "op": "LZString Compress",
18
+ "args": ["Base64"]
19
+ }
20
+ ],
21
+ },
22
+ {
23
+ name: "LZString Decompress From Base64",
24
+ input: "BYUwNmD2AEDukCcwBMg=",
25
+ expectedOutput: "hello world",
26
+ recipeConfig: [
27
+ {
28
+ "op": "LZString Decompress",
29
+ "args": ["Base64"]
30
+ }
31
+ ],
32
+ }
33
+ ]);