cyberchef 11.2.0 → 11.3.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.
Files changed (134) hide show
  1. package/AGENTS.md +75 -0
  2. package/CHANGELOG.md +147 -1
  3. package/Dockerfile +2 -2
  4. package/Gruntfile.js +1 -0
  5. package/package.json +22 -21
  6. package/src/core/Dish.mjs +1 -5
  7. package/src/core/Ingredient.mjs +92 -0
  8. package/src/core/Operation.mjs +19 -0
  9. package/src/core/Recipe.mjs +4 -0
  10. package/src/core/Utils.mjs +48 -0
  11. package/src/core/config/Categories.json +22 -6
  12. package/src/core/config/OperationConfig.json +4771 -1226
  13. package/src/core/config/modules/Ciphers.mjs +20 -0
  14. package/src/core/config/modules/Crypto.mjs +10 -0
  15. package/src/core/config/modules/Default.mjs +8 -0
  16. package/src/core/config/modules/File.mjs +16 -0
  17. package/src/core/config/modules/OpModules.mjs +2 -0
  18. package/src/core/config/scripts/generateHTMLEntities.mjs +139 -0
  19. package/src/core/config/scripts/htmlEntityOverrides.mjs +86 -0
  20. package/src/core/lib/Arithmetic.mjs +21 -5
  21. package/src/core/lib/BigIntUtils.mjs +0 -1
  22. package/src/core/lib/COBS.mjs +86 -0
  23. package/src/core/lib/Decimal.mjs +5 -5
  24. package/src/core/lib/HTMLEntities.mjs +2068 -0
  25. package/src/core/lib/Present.mjs +422 -0
  26. package/src/core/lib/TEA.mjs +494 -0
  27. package/src/core/lib/TLVParser.mjs +16 -7
  28. package/src/core/lib/Twofish.mjs +608 -0
  29. package/src/core/operations/AsconDecrypt.mjs +112 -0
  30. package/src/core/operations/AsconEncrypt.mjs +108 -0
  31. package/src/core/operations/AsconHash.mjs +49 -0
  32. package/src/core/operations/AsconMAC.mjs +68 -0
  33. package/src/core/operations/AutomatedValidationTestOp.mjs +84 -0
  34. package/src/core/operations/AvroToJSON.mjs +1 -1
  35. package/src/core/operations/BLAKE3.mjs +5 -1
  36. package/src/core/operations/BcryptCompare.mjs +11 -5
  37. package/src/core/operations/BitShiftLeft.mjs +4 -1
  38. package/src/core/operations/Bzip2Compress.mjs +1 -1
  39. package/src/core/operations/DechunkHTTPResponse.mjs +4 -1
  40. package/src/core/operations/ExtendedGCD.mjs +101 -0
  41. package/src/core/operations/FromBase.mjs +2 -1
  42. package/src/core/operations/FromCOBS.mjs +38 -0
  43. package/src/core/operations/FromDecimal.mjs +6 -1
  44. package/src/core/operations/FromHTMLEntity.mjs +2 -1458
  45. package/src/core/operations/GenerateHOTP.mjs +21 -6
  46. package/src/core/operations/GenerateImage.mjs +22 -10
  47. package/src/core/operations/GeneratePrime.mjs +154 -0
  48. package/src/core/operations/GenerateTOTP.mjs +24 -7
  49. package/src/core/operations/Gzip.mjs +1 -3
  50. package/src/core/operations/Jsonata.mjs +12 -0
  51. package/src/core/operations/MIMEDecoding.mjs +1 -1
  52. package/src/core/operations/MOD.mjs +62 -0
  53. package/src/core/operations/ModularInverse.mjs +107 -0
  54. package/src/core/operations/PRESENTDecrypt.mjs +94 -0
  55. package/src/core/operations/PRESENTEncrypt.mjs +94 -0
  56. package/src/core/operations/ParseURI.mjs +18 -5
  57. package/src/core/operations/PseudoRandomNumberGenerator.mjs +2 -1
  58. package/src/core/operations/RandomPrime.mjs +154 -0
  59. package/src/core/operations/RenderPDF.mjs +100 -0
  60. package/src/core/operations/SM4Encrypt.mjs +1 -1
  61. package/src/core/operations/SetDifference.mjs +8 -1
  62. package/src/core/operations/SetIntersection.mjs +8 -1
  63. package/src/core/operations/ShowOnMap.mjs +14 -2
  64. package/src/core/operations/TEADecrypt.mjs +98 -0
  65. package/src/core/operations/TEAEncrypt.mjs +98 -0
  66. package/src/core/operations/ToBase.mjs +4 -4
  67. package/src/core/operations/ToBase32.mjs +20 -4
  68. package/src/core/operations/ToBinary.mjs +4 -1
  69. package/src/core/operations/ToCOBS.mjs +38 -0
  70. package/src/core/operations/ToHTMLEntity.mjs +7 -1430
  71. package/src/core/operations/TwofishDecrypt.mjs +94 -0
  72. package/src/core/operations/TwofishEncrypt.mjs +94 -0
  73. package/src/core/operations/URLEncode.mjs +22 -18
  74. package/src/core/operations/UnescapeUnicodeCharacters.mjs +2 -1
  75. package/src/core/operations/ViewBitPlane.mjs +9 -3
  76. package/src/core/operations/Wrap.mjs +5 -0
  77. package/src/core/operations/XORBruteForce.mjs +4 -1
  78. package/src/core/operations/XORChecksum.mjs +2 -2
  79. package/src/core/operations/XTEADecrypt.mjs +110 -0
  80. package/src/core/operations/XTEAEncrypt.mjs +110 -0
  81. package/src/core/operations/index.mjs +42 -0
  82. package/src/core/vendor/ascon.mjs +162 -0
  83. package/src/core/vendor/htmlEntities/entity.json +2233 -0
  84. package/src/core/vendor/htmlEntities/entity.txt +14 -0
  85. package/src/node/api.mjs +4 -1
  86. package/src/node/index.mjs +105 -0
  87. package/src/web/HTMLOperation.mjs +2 -1
  88. package/src/web/stylesheets/layout/_io.css +8 -0
  89. package/tests/browser/00_nightwatch.js +26 -0
  90. package/tests/browser/02_ops.js +20 -4
  91. package/tests/node/index.mjs +1 -0
  92. package/tests/node/tests/Dish.mjs +19 -0
  93. package/tests/node/tests/NodeDish.mjs +36 -0
  94. package/tests/node/tests/ToHTMLEntity.mjs +82 -0
  95. package/tests/node/tests/Utils.mjs +77 -0
  96. package/tests/node/tests/nodeApi.mjs +33 -1
  97. package/tests/node/tests/operations.mjs +26 -1
  98. package/tests/operations/index.mjs +17 -0
  99. package/tests/operations/tests/Arithmetic.mjs +33 -0
  100. package/tests/operations/tests/Ascon.mjs +501 -0
  101. package/tests/operations/tests/AutomatedValidation.mjs +154 -0
  102. package/tests/operations/tests/BLAKE3.mjs +39 -1
  103. package/tests/operations/tests/Base32.mjs +22 -0
  104. package/tests/operations/tests/COBS.mjs +476 -0
  105. package/tests/operations/tests/CharEnc.mjs +2 -2
  106. package/tests/operations/tests/DechunkHTTPResponse.mjs +66 -0
  107. package/tests/operations/tests/ExtendedGCD.mjs +78 -0
  108. package/tests/operations/tests/FromBase.mjs +66 -0
  109. package/tests/operations/tests/FromDecimal.mjs +55 -0
  110. package/tests/operations/tests/GenerateLoremIpsum.mjs +2 -2
  111. package/tests/operations/tests/Gzip.mjs +60 -0
  112. package/tests/operations/tests/HTMLEntity.mjs +126 -0
  113. package/tests/operations/tests/Hash.mjs +44 -0
  114. package/tests/operations/tests/Hexdump.mjs +1 -1
  115. package/tests/operations/tests/Image.mjs +26 -0
  116. package/tests/operations/tests/Jsonata.mjs +23 -0
  117. package/tests/operations/tests/MIMEDecoding.mjs +33 -0
  118. package/tests/operations/tests/MOD.mjs +208 -0
  119. package/tests/operations/tests/Median.mjs +33 -0
  120. package/tests/operations/tests/ModularInverse.mjs +78 -0
  121. package/tests/operations/tests/OTP.mjs +167 -2
  122. package/tests/operations/tests/PRESENT.mjs +465 -0
  123. package/tests/operations/tests/ParseTLV.mjs +41 -0
  124. package/tests/operations/tests/RenderPDF.mjs +55 -0
  125. package/tests/operations/tests/SM2.mjs +1 -1
  126. package/tests/operations/tests/SetDifference.mjs +22 -0
  127. package/tests/operations/tests/SetIntersection.mjs +23 -1
  128. package/tests/operations/tests/ShowOnMap.mjs +61 -0
  129. package/tests/operations/tests/TEA.mjs +566 -0
  130. package/tests/operations/tests/Twofish.mjs +486 -0
  131. package/tests/operations/tests/URLEncodeDecode.mjs +26 -0
  132. package/tests/operations/tests/UnescapeUnicodeCharacters.mjs +88 -0
  133. package/tests/operations/tests/Wrap.mjs +44 -0
  134. package/webpack.config.js +3 -3
@@ -0,0 +1,465 @@
1
+ /**
2
+ * PRESENT cipher tests.
3
+ *
4
+ * Test vectors from the original PRESENT paper:
5
+ * "PRESENT: An Ultra-Lightweight Block Cipher"
6
+ * https://link.springer.com/chapter/10.1007/978-3-540-74735-2_31
7
+ * https://www.iacr.org/archive/ches2007/47270450/47270450.pdf
8
+ *
9
+ * Note: PKCS5 padding adds an extra block when input is exactly block-aligned.
10
+ * Round-trip tests verify correct encryption/decryption behavior.
11
+ *
12
+ * @author Medjedtxm
13
+ * @copyright Crown Copyright 2026
14
+ * @license Apache-2.0
15
+ */
16
+
17
+ import TestRegister from "../../lib/TestRegister.mjs";
18
+
19
+ TestRegister.addTests([
20
+ // ============================================================
21
+ // OFFICIAL TEST VECTORS from the original PRESENT paper:
22
+ // "PRESENT: An Ultra-Lightweight Block Cipher" (Bogdanov et al., CHES 2007)
23
+ // https://link.springer.com/chapter/10.1007/978-3-540-74735-2_31
24
+ // Table 3: Test Vectors
25
+ // ============================================================
26
+ {
27
+ name: "PRESENT Official Vector 1: 80-bit zero key, zero plaintext",
28
+ input: "0000000000000000",
29
+ expectedOutput: "5579c1387b228445",
30
+ recipeConfig: [
31
+ {
32
+ op: "PRESENT Encrypt",
33
+ args: [
34
+ { string: "00000000000000000000", option: "Hex" },
35
+ { string: "", option: "Hex" },
36
+ "ECB", "Hex", "Hex", "NO"
37
+ ]
38
+ }
39
+ ]
40
+ },
41
+ {
42
+ name: "PRESENT Official Vector 2: 80-bit all-ones key, zero plaintext",
43
+ input: "0000000000000000",
44
+ expectedOutput: "e72c46c0f5945049",
45
+ recipeConfig: [
46
+ {
47
+ op: "PRESENT Encrypt",
48
+ args: [
49
+ { string: "ffffffffffffffffffff", option: "Hex" },
50
+ { string: "", option: "Hex" },
51
+ "ECB", "Hex", "Hex", "NO"
52
+ ]
53
+ }
54
+ ]
55
+ },
56
+ {
57
+ name: "PRESENT Official Vector 3: 80-bit zero key, all-ones plaintext",
58
+ input: "ffffffffffffffff",
59
+ expectedOutput: "a112ffc72f68417b",
60
+ recipeConfig: [
61
+ {
62
+ op: "PRESENT Encrypt",
63
+ args: [
64
+ { string: "00000000000000000000", option: "Hex" },
65
+ { string: "", option: "Hex" },
66
+ "ECB", "Hex", "Hex", "NO"
67
+ ]
68
+ }
69
+ ]
70
+ },
71
+ {
72
+ name: "PRESENT Official Vector 4: 80-bit all-ones key, all-ones plaintext",
73
+ input: "ffffffffffffffff",
74
+ expectedOutput: "3333dcd3213210d2",
75
+ recipeConfig: [
76
+ {
77
+ op: "PRESENT Encrypt",
78
+ args: [
79
+ { string: "ffffffffffffffffffff", option: "Hex" },
80
+ { string: "", option: "Hex" },
81
+ "ECB", "Hex", "Hex", "NO"
82
+ ]
83
+ }
84
+ ]
85
+ },
86
+ {
87
+ name: "PRESENT Official Vector 5: 128-bit zero key, zero plaintext",
88
+ input: "0000000000000000",
89
+ expectedOutput: "96db702a2e6900af",
90
+ recipeConfig: [
91
+ {
92
+ op: "PRESENT Encrypt",
93
+ args: [
94
+ { string: "00000000000000000000000000000000", option: "Hex" },
95
+ { string: "", option: "Hex" },
96
+ "ECB", "Hex", "Hex", "NO"
97
+ ]
98
+ }
99
+ ]
100
+ },
101
+ {
102
+ name: "PRESENT Official Vector 6: 128-bit key (SageMath reference)",
103
+ input: "0123456789abcdef",
104
+ expectedOutput: "0e9d28685e671dd6",
105
+ recipeConfig: [
106
+ {
107
+ op: "PRESENT Encrypt",
108
+ args: [
109
+ { string: "0123456789abcdef0123456789abcdef", option: "Hex" },
110
+ { string: "", option: "Hex" },
111
+ "ECB", "Hex", "Hex", "NO"
112
+ ]
113
+ }
114
+ ]
115
+ },
116
+ // Decrypt verification of official vectors
117
+ {
118
+ name: "PRESENT Official Vector 1 Decrypt: 80-bit zero key",
119
+ input: "5579c1387b228445",
120
+ expectedOutput: "0000000000000000",
121
+ recipeConfig: [
122
+ {
123
+ op: "PRESENT Decrypt",
124
+ args: [
125
+ { string: "00000000000000000000", option: "Hex" },
126
+ { string: "", option: "Hex" },
127
+ "ECB", "Hex", "Hex", "NO"
128
+ ]
129
+ }
130
+ ]
131
+ },
132
+ {
133
+ name: "PRESENT Official Vector 4 Decrypt: 80-bit all-ones key",
134
+ input: "3333dcd3213210d2",
135
+ expectedOutput: "ffffffffffffffff",
136
+ recipeConfig: [
137
+ {
138
+ op: "PRESENT Decrypt",
139
+ args: [
140
+ { string: "ffffffffffffffffffff", option: "Hex" },
141
+ { string: "", option: "Hex" },
142
+ "ECB", "Hex", "Hex", "NO"
143
+ ]
144
+ }
145
+ ]
146
+ },
147
+ {
148
+ name: "PRESENT Official Vector 5 Decrypt: 128-bit zero key",
149
+ input: "96db702a2e6900af",
150
+ expectedOutput: "0000000000000000",
151
+ recipeConfig: [
152
+ {
153
+ op: "PRESENT Decrypt",
154
+ args: [
155
+ { string: "00000000000000000000000000000000", option: "Hex" },
156
+ { string: "", option: "Hex" },
157
+ "ECB", "Hex", "Hex", "NO"
158
+ ]
159
+ }
160
+ ]
161
+ },
162
+ {
163
+ name: "PRESENT Official Vector 6 Decrypt: 128-bit key (SageMath reference)",
164
+ input: "0e9d28685e671dd6",
165
+ expectedOutput: "0123456789abcdef",
166
+ recipeConfig: [
167
+ {
168
+ op: "PRESENT Decrypt",
169
+ args: [
170
+ { string: "0123456789abcdef0123456789abcdef", option: "Hex" },
171
+ { string: "", option: "Hex" },
172
+ "ECB", "Hex", "Hex", "NO"
173
+ ]
174
+ }
175
+ ]
176
+ },
177
+ // ============================================================
178
+ // Round-trip tests - These verify encryption and decryption work correctly
179
+ // ============================================================
180
+ {
181
+ name: "PRESENT Round-trip: ECB 80-bit key, short message",
182
+ input: "Hello!!!",
183
+ expectedOutput: "Hello!!!",
184
+ recipeConfig: [
185
+ {
186
+ op: "PRESENT Encrypt",
187
+ args: [
188
+ { string: "00112233445566778899", option: "Hex" },
189
+ { string: "", option: "Hex" },
190
+ "ECB", "Raw", "Hex", "PKCS5"
191
+ ]
192
+ },
193
+ {
194
+ op: "PRESENT Decrypt",
195
+ args: [
196
+ { string: "00112233445566778899", option: "Hex" },
197
+ { string: "", option: "Hex" },
198
+ "ECB", "Hex", "Raw", "PKCS5"
199
+ ]
200
+ }
201
+ ]
202
+ },
203
+ {
204
+ name: "PRESENT Round-trip: CBC 80-bit key, long message",
205
+ input: "The quick brown fox jumps over the lazy dog",
206
+ expectedOutput: "The quick brown fox jumps over the lazy dog",
207
+ recipeConfig: [
208
+ {
209
+ op: "PRESENT Encrypt",
210
+ args: [
211
+ { string: "aabbccddeeff00112233", option: "Hex" },
212
+ { string: "0011223344556677", option: "Hex" },
213
+ "CBC", "Raw", "Hex", "PKCS5"
214
+ ]
215
+ },
216
+ {
217
+ op: "PRESENT Decrypt",
218
+ args: [
219
+ { string: "aabbccddeeff00112233", option: "Hex" },
220
+ { string: "0011223344556677", option: "Hex" },
221
+ "CBC", "Hex", "Raw", "PKCS5"
222
+ ]
223
+ }
224
+ ]
225
+ },
226
+ {
227
+ name: "PRESENT Round-trip: ECB 128-bit key",
228
+ input: "Testing PRESENT cipher with 128-bit key",
229
+ expectedOutput: "Testing PRESENT cipher with 128-bit key",
230
+ recipeConfig: [
231
+ {
232
+ op: "PRESENT Encrypt",
233
+ args: [
234
+ { string: "00112233445566778899aabbccddeeff", option: "Hex" },
235
+ { string: "", option: "Hex" },
236
+ "ECB", "Raw", "Hex", "PKCS5"
237
+ ]
238
+ },
239
+ {
240
+ op: "PRESENT Decrypt",
241
+ args: [
242
+ { string: "00112233445566778899aabbccddeeff", option: "Hex" },
243
+ { string: "", option: "Hex" },
244
+ "ECB", "Hex", "Raw", "PKCS5"
245
+ ]
246
+ }
247
+ ]
248
+ },
249
+ {
250
+ name: "PRESENT Round-trip: CBC 128-bit key",
251
+ input: "PRESENT is an ultra-lightweight block cipher!",
252
+ expectedOutput: "PRESENT is an ultra-lightweight block cipher!",
253
+ recipeConfig: [
254
+ {
255
+ op: "PRESENT Encrypt",
256
+ args: [
257
+ { string: "ffeeddccbbaa99887766554433221100", option: "Hex" },
258
+ { string: "8877665544332211", option: "Hex" },
259
+ "CBC", "Raw", "Hex", "PKCS5"
260
+ ]
261
+ },
262
+ {
263
+ op: "PRESENT Decrypt",
264
+ args: [
265
+ { string: "ffeeddccbbaa99887766554433221100", option: "Hex" },
266
+ { string: "8877665544332211", option: "Hex" },
267
+ "CBC", "Hex", "Raw", "PKCS5"
268
+ ]
269
+ }
270
+ ]
271
+ },
272
+ {
273
+ name: "PRESENT Round-trip: UTF8 key (10 bytes)",
274
+ input: "Secret message",
275
+ expectedOutput: "Secret message",
276
+ recipeConfig: [
277
+ {
278
+ op: "PRESENT Encrypt",
279
+ args: [
280
+ { string: "mypassword", option: "UTF8" },
281
+ { string: "initvect", option: "UTF8" },
282
+ "CBC", "Raw", "Hex", "PKCS5"
283
+ ]
284
+ },
285
+ {
286
+ op: "PRESENT Decrypt",
287
+ args: [
288
+ { string: "mypassword", option: "UTF8" },
289
+ { string: "initvect", option: "UTF8" },
290
+ "CBC", "Hex", "Raw", "PKCS5"
291
+ ]
292
+ }
293
+ ]
294
+ },
295
+
296
+ // Encryption consistency tests - verify same input always produces same output
297
+ {
298
+ name: "PRESENT Encrypt: 80-bit zero key consistency",
299
+ input: "TestData",
300
+ expectedOutput: "b78cfea5ffcd89f265585a6ce7312131",
301
+ recipeConfig: [
302
+ {
303
+ op: "PRESENT Encrypt",
304
+ args: [
305
+ { string: "00000000000000000000", option: "Hex" },
306
+ { string: "", option: "Hex" },
307
+ "ECB", "Raw", "Hex", "PKCS5"
308
+ ]
309
+ }
310
+ ]
311
+ },
312
+ {
313
+ name: "PRESENT Encrypt: 128-bit zero key consistency",
314
+ input: "TestData",
315
+ expectedOutput: "e127a24e38de2c36407e794ef5dffefd",
316
+ recipeConfig: [
317
+ {
318
+ op: "PRESENT Encrypt",
319
+ args: [
320
+ { string: "00000000000000000000000000000000", option: "Hex" },
321
+ { string: "", option: "Hex" },
322
+ "ECB", "Raw", "Hex", "PKCS5"
323
+ ]
324
+ }
325
+ ]
326
+ },
327
+ {
328
+ name: "PRESENT Round-trip: Various lengths 1 byte",
329
+ input: "A",
330
+ expectedOutput: "A",
331
+ recipeConfig: [
332
+ {
333
+ op: "PRESENT Encrypt",
334
+ args: [
335
+ { string: "00112233445566778899", option: "Hex" },
336
+ { string: "", option: "Hex" },
337
+ "ECB", "Raw", "Hex", "PKCS5"
338
+ ]
339
+ },
340
+ {
341
+ op: "PRESENT Decrypt",
342
+ args: [
343
+ { string: "00112233445566778899", option: "Hex" },
344
+ { string: "", option: "Hex" },
345
+ "ECB", "Hex", "Raw", "PKCS5"
346
+ ]
347
+ }
348
+ ]
349
+ },
350
+ {
351
+ name: "PRESENT Round-trip: Various lengths 7 bytes",
352
+ input: "1234567",
353
+ expectedOutput: "1234567",
354
+ recipeConfig: [
355
+ {
356
+ op: "PRESENT Encrypt",
357
+ args: [
358
+ { string: "00112233445566778899", option: "Hex" },
359
+ { string: "", option: "Hex" },
360
+ "ECB", "Raw", "Hex", "PKCS5"
361
+ ]
362
+ },
363
+ {
364
+ op: "PRESENT Decrypt",
365
+ args: [
366
+ { string: "00112233445566778899", option: "Hex" },
367
+ { string: "", option: "Hex" },
368
+ "ECB", "Hex", "Raw", "PKCS5"
369
+ ]
370
+ }
371
+ ]
372
+ },
373
+ {
374
+ name: "PRESENT Round-trip: Various lengths 8 bytes (exact block)",
375
+ input: "12345678",
376
+ expectedOutput: "12345678",
377
+ recipeConfig: [
378
+ {
379
+ op: "PRESENT Encrypt",
380
+ args: [
381
+ { string: "00112233445566778899", option: "Hex" },
382
+ { string: "", option: "Hex" },
383
+ "ECB", "Raw", "Hex", "PKCS5"
384
+ ]
385
+ },
386
+ {
387
+ op: "PRESENT Decrypt",
388
+ args: [
389
+ { string: "00112233445566778899", option: "Hex" },
390
+ { string: "", option: "Hex" },
391
+ "ECB", "Hex", "Raw", "PKCS5"
392
+ ]
393
+ }
394
+ ]
395
+ },
396
+ {
397
+ name: "PRESENT Round-trip: Various lengths 9 bytes",
398
+ input: "123456789",
399
+ expectedOutput: "123456789",
400
+ recipeConfig: [
401
+ {
402
+ op: "PRESENT Encrypt",
403
+ args: [
404
+ { string: "00112233445566778899", option: "Hex" },
405
+ { string: "", option: "Hex" },
406
+ "ECB", "Raw", "Hex", "PKCS5"
407
+ ]
408
+ },
409
+ {
410
+ op: "PRESENT Decrypt",
411
+ args: [
412
+ { string: "00112233445566778899", option: "Hex" },
413
+ { string: "", option: "Hex" },
414
+ "ECB", "Hex", "Raw", "PKCS5"
415
+ ]
416
+ }
417
+ ]
418
+ },
419
+ {
420
+ name: "PRESENT Round-trip: Various lengths 16 bytes (two blocks)",
421
+ input: "1234567890ABCDEF",
422
+ expectedOutput: "1234567890ABCDEF",
423
+ recipeConfig: [
424
+ {
425
+ op: "PRESENT Encrypt",
426
+ args: [
427
+ { string: "00112233445566778899", option: "Hex" },
428
+ { string: "", option: "Hex" },
429
+ "ECB", "Raw", "Hex", "PKCS5"
430
+ ]
431
+ },
432
+ {
433
+ op: "PRESENT Decrypt",
434
+ args: [
435
+ { string: "00112233445566778899", option: "Hex" },
436
+ { string: "", option: "Hex" },
437
+ "ECB", "Hex", "Raw", "PKCS5"
438
+ ]
439
+ }
440
+ ]
441
+ },
442
+ {
443
+ name: "PRESENT Round-trip: Binary data",
444
+ input: "\x00\x01\x02\x03\x04\x05\x06\x07",
445
+ expectedOutput: "\x00\x01\x02\x03\x04\x05\x06\x07",
446
+ recipeConfig: [
447
+ {
448
+ op: "PRESENT Encrypt",
449
+ args: [
450
+ { string: "ffeeddccbbaa99887766", option: "Hex" },
451
+ { string: "0011223344556677", option: "Hex" },
452
+ "CBC", "Raw", "Hex", "PKCS5"
453
+ ]
454
+ },
455
+ {
456
+ op: "PRESENT Decrypt",
457
+ args: [
458
+ { string: "ffeeddccbbaa99887766", option: "Hex" },
459
+ { string: "0011223344556677", option: "Hex" },
460
+ "CBC", "Hex", "Raw", "PKCS5"
461
+ ]
462
+ }
463
+ ]
464
+ }
465
+ ]);
@@ -52,5 +52,46 @@ TestRegister.addTests([
52
52
  "args": [1, 4, true] // length value is patently wrong, should be ignored by BER.
53
53
  }
54
54
  ]
55
+ },
56
+ {
57
+ name: "Parse TLV: BER long-form length (two-byte length encoding)",
58
+ input: "\x01\x82\x01\x00" + "A".repeat(256) + "\x02\x03\x41\x42\x43",
59
+ expectedOutput: JSON.stringify([
60
+ {"key": [1], "length": 256, "value": Array(256).fill(65)},
61
+ {"key": [2], "length": 3, "value": [65, 66, 67]}
62
+ ], null, 4),
63
+ recipeConfig: [
64
+ {
65
+ "op": "Parse TLV",
66
+ "args": [1, 1, true]
67
+ }
68
+ ]
69
+ },
70
+ {
71
+ name: "Parse TLV: BER long-form length (one-byte length encoding)",
72
+ input: "\x01\x81\x80" + "B".repeat(128),
73
+ expectedOutput: JSON.stringify([
74
+ {"key": [1], "length": 128, "value": Array(128).fill(66)}
75
+ ], null, 4),
76
+ recipeConfig: [
77
+ {
78
+ "op": "Parse TLV",
79
+ "args": [1, 1, true]
80
+ }
81
+ ]
82
+ },
83
+ {
84
+ name: "Parse TLV: BER multiple entries with mixed short and long-form lengths",
85
+ input: "\x01\x05\x48\x65\x6c\x6c\x6f\x02\x81\x05\x57\x6f\x72\x6c\x64",
86
+ expectedOutput: JSON.stringify([
87
+ {"key": [1], "length": 5, "value": [72, 101, 108, 108, 111]},
88
+ {"key": [2], "length": 5, "value": [87, 111, 114, 108, 100]}
89
+ ], null, 4),
90
+ recipeConfig: [
91
+ {
92
+ "op": "Parse TLV",
93
+ "args": [1, 1, true]
94
+ }
95
+ ]
55
96
  }
56
97
  ]);
@@ -0,0 +1,55 @@
1
+ /**
2
+ * RenderPDF tests.
3
+ *
4
+ * @copyright Crown Copyright 2026
5
+ * @license Apache-2.0
6
+ */
7
+ import TestRegister from "../../lib/TestRegister.mjs";
8
+
9
+
10
+ const oversizedPdfLikeInput = "%PDF-1.0\n" + "A".repeat(5000);
11
+
12
+
13
+ TestRegister.addTests([
14
+ {
15
+ name: "RenderPDF",
16
+ input: "Not a PDF",
17
+ expectedOutput: "Input does not appear to be a PDF file.",
18
+ recipeConfig: [
19
+ {
20
+ op: "Render PDF",
21
+ args: ["Raw"]
22
+ },
23
+ ],
24
+ },
25
+ {
26
+ name: "RenderPDF",
27
+ input: "",
28
+ expectedMatch: /^<iframe src="data:application\/pdf;base64,JVBERi0xLjAKCjEgMCBvYmogPDwg/,
29
+ recipeConfig: [
30
+ {
31
+ "op": "Generate QR Code",
32
+ "args": ["PDF", 1, 1, "Low"]
33
+ },
34
+ {
35
+ "op": "Render PDF",
36
+ "args": ["Raw"]
37
+ }
38
+ ],
39
+ },
40
+ {
41
+ name: "RenderPDF followed by Generate QR Code error returns plain text",
42
+ input: oversizedPdfLikeInput,
43
+ expectedOutput: "Error generating QR code. (Error: Too much data)",
44
+ recipeConfig: [
45
+ {
46
+ "op": "Render PDF",
47
+ "args": ["Raw"]
48
+ },
49
+ {
50
+ "op": "Generate QR Code",
51
+ "args": ["PNG", 1, 0, "High"]
52
+ }
53
+ ],
54
+ },
55
+ ]);
@@ -113,7 +113,7 @@ TestRegister.addTests([
113
113
  },
114
114
  {
115
115
  "op": "SM2 Decrypt",
116
- "args": [PRIVATE_K, "C1C2C2", CURVE]
116
+ "args": [PRIVATE_K, "C1C2C3", CURVE]
117
117
  }
118
118
  ]
119
119
  },
@@ -53,4 +53,26 @@ TestRegister.addTests([
53
53
  },
54
54
  ],
55
55
  },
56
+ {
57
+ name: "Set Difference: duplicates in first set are removed",
58
+ input: "red,red,blue\n\nblue",
59
+ expectedOutput: "red",
60
+ recipeConfig: [
61
+ {
62
+ op: "Set Difference",
63
+ args: ["\n\n", ","],
64
+ },
65
+ ],
66
+ },
67
+ {
68
+ name: "Set Difference: duplicates in both sets",
69
+ input: "1 1 2 2 3\n\n2 2 3 3",
70
+ expectedOutput: "1",
71
+ recipeConfig: [
72
+ {
73
+ op: "Set Difference",
74
+ args: ["\n\n", " "],
75
+ },
76
+ ],
77
+ },
56
78
  ]);
@@ -52,5 +52,27 @@ TestRegister.addTests([
52
52
  args: ["z", "-"],
53
53
  },
54
54
  ],
55
- }
55
+ },
56
+ {
57
+ name: "Set Intersection: duplicates in first set are removed",
58
+ input: "red,red,blue\n\nred,blue",
59
+ expectedOutput: "red,blue",
60
+ recipeConfig: [
61
+ {
62
+ op: "Set Intersection",
63
+ args: ["\n\n", ","],
64
+ },
65
+ ],
66
+ },
67
+ {
68
+ name: "Set Intersection: duplicates in both sets",
69
+ input: "1 1 2 2 3\n\n2 2 3 3 4",
70
+ expectedOutput: "2 3",
71
+ recipeConfig: [
72
+ {
73
+ op: "Set Intersection",
74
+ args: ["\n\n", " "],
75
+ },
76
+ ],
77
+ },
56
78
  ]);
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Show on map tests
3
+ *
4
+ * @author Leon Zandman [leon@wirwar.com]
5
+ *
6
+ * @copyright Crown Copyright 2026
7
+ * @license Apache-2.0
8
+ */
9
+ import TestRegister from "../../lib/TestRegister.mjs";
10
+
11
+ TestRegister.addTests([
12
+ {
13
+ name: "Show on map: valid coordinate pair",
14
+ input: "51.5007, -0.1246",
15
+ // The presented output is the Leaflet map HTML; just check the coordinates made it through.
16
+ expectedMatch: /51\.5007,-0\.1246/,
17
+ recipeConfig: [
18
+ {
19
+ op: "Show on map",
20
+ args: [13, "Auto", "Auto"]
21
+ },
22
+ ],
23
+ },
24
+ {
25
+ // Regression test: a comma-separated input with the delimiter set to "\n" used to be
26
+ // mis-detected as a single Degrees Decimal Minutes value (1° 24' = 1.4°), producing a single
27
+ // coordinate. That single value was then passed to Leaflet's setView([1.4], ...), throwing
28
+ // an uncaught "Cannot read properties of null (reading 'lat')" TypeError in the browser.
29
+ name: "Show on map: single value is rejected with a helpful error",
30
+ input: "1, 24",
31
+ expectedOutput: "Could not show coordinates '1.4' on the map. Expected a latitude and longitude pair - check that the input format and delimiter are correct.",
32
+ recipeConfig: [
33
+ {
34
+ op: "Show on map",
35
+ args: [13, "Auto", "\\n"]
36
+ },
37
+ ],
38
+ },
39
+ {
40
+ name: "Show on map: empty input format is rejected",
41
+ input: "1, 24",
42
+ expectedOutput: "Input Format cannot be empty.",
43
+ recipeConfig: [
44
+ {
45
+ op: "Show on map",
46
+ args: [13, "", "Auto"]
47
+ },
48
+ ],
49
+ },
50
+ {
51
+ name: "Show on map: empty input delimiter is rejected",
52
+ input: "1, 24",
53
+ expectedOutput: "Input Delimiter cannot be empty.",
54
+ recipeConfig: [
55
+ {
56
+ op: "Show on map",
57
+ args: [13, "Auto", ""]
58
+ },
59
+ ],
60
+ },
61
+ ]);