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 +17 -0
- package/package.json +2 -1
- package/src/core/config/Categories.json +7 -1
- package/src/core/config/OperationConfig.json +164 -0
- package/src/core/config/modules/Compression.mjs +4 -0
- package/src/core/config/modules/Crypto.mjs +4 -0
- package/src/core/config/modules/Default.mjs +4 -0
- package/src/core/lib/LS47.mjs +244 -0
- package/src/core/lib/LZString.mjs +21 -0
- package/src/core/operations/LS47Decrypt.mjs +57 -0
- package/src/core/operations/LS47Encrypt.mjs +62 -0
- package/src/core/operations/LZStringCompress.mjs +55 -0
- package/src/core/operations/LZStringDecompress.mjs +56 -0
- package/src/core/operations/ROT13BruteForce.mjs +102 -0
- package/src/core/operations/ROT47BruteForce.mjs +82 -0
- package/src/core/operations/index.mjs +12 -0
- package/src/node/index.mjs +30 -0
- package/tests/operations/index.mjs +2 -0
- package/tests/operations/tests/LS47.mjs +45 -0
- package/tests/operations/tests/LZString.mjs +33 -0
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.
|
|
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,
|
package/src/node/index.mjs
CHANGED
|
@@ -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
|
+
]);
|