cyberchef 11.1.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 (148) hide show
  1. package/AGENTS.md +75 -0
  2. package/CHANGELOG.md +173 -2
  3. package/Dockerfile +2 -2
  4. package/Gruntfile.js +1 -0
  5. package/README.md +7 -6
  6. package/SECURITY.md +3 -1
  7. package/package.json +22 -21
  8. package/src/core/Chef.mjs +2 -0
  9. package/src/core/Dish.mjs +1 -5
  10. package/src/core/Ingredient.mjs +92 -0
  11. package/src/core/Operation.mjs +19 -0
  12. package/src/core/Recipe.mjs +4 -0
  13. package/src/core/Utils.mjs +48 -0
  14. package/src/core/config/Categories.json +22 -6
  15. package/src/core/config/OperationConfig.json +4774 -1228
  16. package/src/core/config/modules/Ciphers.mjs +20 -0
  17. package/src/core/config/modules/Crypto.mjs +10 -0
  18. package/src/core/config/modules/Default.mjs +8 -0
  19. package/src/core/config/modules/File.mjs +16 -0
  20. package/src/core/config/modules/OpModules.mjs +2 -0
  21. package/src/core/config/scripts/generateHTMLEntities.mjs +139 -0
  22. package/src/core/config/scripts/htmlEntityOverrides.mjs +86 -0
  23. package/src/core/dishTypes/DishType.mjs +1 -1
  24. package/src/core/errors/ExcludedOperationError.mjs +1 -1
  25. package/src/core/lib/Arithmetic.mjs +21 -5
  26. package/src/core/lib/BigIntUtils.mjs +0 -1
  27. package/src/core/lib/COBS.mjs +86 -0
  28. package/src/core/lib/Charts.mjs +3 -3
  29. package/src/core/lib/Decimal.mjs +5 -5
  30. package/src/core/lib/HTMLEntities.mjs +2068 -0
  31. package/src/core/lib/Present.mjs +422 -0
  32. package/src/core/lib/Protocol.mjs +8 -6
  33. package/src/core/lib/TEA.mjs +494 -0
  34. package/src/core/lib/TLVParser.mjs +16 -7
  35. package/src/core/lib/Twofish.mjs +608 -0
  36. package/src/core/operations/AsconDecrypt.mjs +112 -0
  37. package/src/core/operations/AsconEncrypt.mjs +108 -0
  38. package/src/core/operations/AsconHash.mjs +49 -0
  39. package/src/core/operations/AsconMAC.mjs +68 -0
  40. package/src/core/operations/AutomatedValidationTestOp.mjs +84 -0
  41. package/src/core/operations/AvroToJSON.mjs +1 -1
  42. package/src/core/operations/BLAKE3.mjs +5 -1
  43. package/src/core/operations/BcryptCompare.mjs +11 -5
  44. package/src/core/operations/BitShiftLeft.mjs +4 -1
  45. package/src/core/operations/Bzip2Compress.mjs +1 -1
  46. package/src/core/operations/DechunkHTTPResponse.mjs +4 -1
  47. package/src/core/operations/ExtendedGCD.mjs +101 -0
  48. package/src/core/operations/FromBase.mjs +2 -1
  49. package/src/core/operations/FromCOBS.mjs +38 -0
  50. package/src/core/operations/FromDecimal.mjs +6 -1
  51. package/src/core/operations/FromHTMLEntity.mjs +2 -1458
  52. package/src/core/operations/GenerateDeBruijnSequence.mjs +8 -0
  53. package/src/core/operations/GenerateHOTP.mjs +21 -6
  54. package/src/core/operations/GenerateImage.mjs +22 -10
  55. package/src/core/operations/GeneratePrime.mjs +154 -0
  56. package/src/core/operations/GenerateTOTP.mjs +24 -7
  57. package/src/core/operations/Gzip.mjs +1 -3
  58. package/src/core/operations/Jsonata.mjs +12 -0
  59. package/src/core/operations/MIMEDecoding.mjs +1 -1
  60. package/src/core/operations/MOD.mjs +62 -0
  61. package/src/core/operations/ModularInverse.mjs +107 -0
  62. package/src/core/operations/PRESENTDecrypt.mjs +94 -0
  63. package/src/core/operations/PRESENTEncrypt.mjs +94 -0
  64. package/src/core/operations/ParityBit.mjs +1 -1
  65. package/src/core/operations/ParseIPv4Header.mjs +1 -1
  66. package/src/core/operations/ParseURI.mjs +18 -5
  67. package/src/core/operations/PseudoRandomNumberGenerator.mjs +2 -1
  68. package/src/core/operations/RandomPrime.mjs +154 -0
  69. package/src/core/operations/RenderPDF.mjs +100 -0
  70. package/src/core/operations/SHA2.mjs +1 -1
  71. package/src/core/operations/SM4Encrypt.mjs +1 -1
  72. package/src/core/operations/SetDifference.mjs +8 -1
  73. package/src/core/operations/SetIntersection.mjs +8 -1
  74. package/src/core/operations/ShowOnMap.mjs +14 -2
  75. package/src/core/operations/TEADecrypt.mjs +98 -0
  76. package/src/core/operations/TEAEncrypt.mjs +98 -0
  77. package/src/core/operations/ToBase.mjs +4 -4
  78. package/src/core/operations/ToBase32.mjs +20 -4
  79. package/src/core/operations/ToBinary.mjs +4 -1
  80. package/src/core/operations/ToCOBS.mjs +38 -0
  81. package/src/core/operations/ToHTMLEntity.mjs +7 -1430
  82. package/src/core/operations/ToHexdump.mjs +7 -1
  83. package/src/core/operations/TwofishDecrypt.mjs +94 -0
  84. package/src/core/operations/TwofishEncrypt.mjs +94 -0
  85. package/src/core/operations/URLEncode.mjs +22 -18
  86. package/src/core/operations/UnescapeUnicodeCharacters.mjs +2 -1
  87. package/src/core/operations/ViewBitPlane.mjs +9 -3
  88. package/src/core/operations/Wrap.mjs +5 -0
  89. package/src/core/operations/XORBruteForce.mjs +4 -1
  90. package/src/core/operations/XORChecksum.mjs +10 -3
  91. package/src/core/operations/XTEADecrypt.mjs +110 -0
  92. package/src/core/operations/XTEAEncrypt.mjs +110 -0
  93. package/src/core/operations/index.mjs +42 -0
  94. package/src/core/vendor/ascon.mjs +162 -0
  95. package/src/core/vendor/htmlEntities/entity.json +2233 -0
  96. package/src/core/vendor/htmlEntities/entity.txt +14 -0
  97. package/src/node/api.mjs +4 -1
  98. package/src/node/index.mjs +105 -0
  99. package/src/web/HTMLOperation.mjs +2 -1
  100. package/src/web/stylesheets/layout/_io.css +8 -0
  101. package/tests/browser/00_nightwatch.js +26 -0
  102. package/tests/browser/02_ops.js +20 -4
  103. package/tests/node/index.mjs +2 -0
  104. package/tests/node/tests/Dish.mjs +19 -0
  105. package/tests/node/tests/NodeDish.mjs +36 -0
  106. package/tests/node/tests/ToHTMLEntity.mjs +82 -0
  107. package/tests/node/tests/Utils.mjs +77 -0
  108. package/tests/node/tests/lib/ChartsProtocolPrototypePollution.mjs +90 -0
  109. package/tests/node/tests/nodeApi.mjs +33 -1
  110. package/tests/node/tests/operations.mjs +26 -1
  111. package/tests/operations/index.mjs +17 -0
  112. package/tests/operations/tests/Arithmetic.mjs +33 -0
  113. package/tests/operations/tests/Ascon.mjs +501 -0
  114. package/tests/operations/tests/AutomatedValidation.mjs +154 -0
  115. package/tests/operations/tests/BLAKE3.mjs +39 -1
  116. package/tests/operations/tests/Base32.mjs +22 -0
  117. package/tests/operations/tests/COBS.mjs +476 -0
  118. package/tests/operations/tests/CharEnc.mjs +2 -2
  119. package/tests/operations/tests/DechunkHTTPResponse.mjs +66 -0
  120. package/tests/operations/tests/ExtendedGCD.mjs +78 -0
  121. package/tests/operations/tests/FromBase.mjs +66 -0
  122. package/tests/operations/tests/FromDecimal.mjs +55 -0
  123. package/tests/operations/tests/GenerateLoremIpsum.mjs +2 -2
  124. package/tests/operations/tests/Gzip.mjs +60 -0
  125. package/tests/operations/tests/HTMLEntity.mjs +126 -0
  126. package/tests/operations/tests/Hash.mjs +44 -0
  127. package/tests/operations/tests/Hexdump.mjs +11 -0
  128. package/tests/operations/tests/Image.mjs +26 -0
  129. package/tests/operations/tests/Jsonata.mjs +23 -0
  130. package/tests/operations/tests/MIMEDecoding.mjs +33 -0
  131. package/tests/operations/tests/MOD.mjs +208 -0
  132. package/tests/operations/tests/Median.mjs +33 -0
  133. package/tests/operations/tests/ModularInverse.mjs +78 -0
  134. package/tests/operations/tests/OTP.mjs +167 -2
  135. package/tests/operations/tests/PRESENT.mjs +465 -0
  136. package/tests/operations/tests/ParseIPv4Header.mjs +11 -0
  137. package/tests/operations/tests/ParseTLV.mjs +41 -0
  138. package/tests/operations/tests/RenderPDF.mjs +55 -0
  139. package/tests/operations/tests/SM2.mjs +1 -1
  140. package/tests/operations/tests/SetDifference.mjs +22 -0
  141. package/tests/operations/tests/SetIntersection.mjs +23 -1
  142. package/tests/operations/tests/ShowOnMap.mjs +61 -0
  143. package/tests/operations/tests/TEA.mjs +566 -0
  144. package/tests/operations/tests/Twofish.mjs +486 -0
  145. package/tests/operations/tests/URLEncodeDecode.mjs +26 -0
  146. package/tests/operations/tests/UnescapeUnicodeCharacters.mjs +88 -0
  147. package/tests/operations/tests/Wrap.mjs +44 -0
  148. package/webpack.config.js +3 -3
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @author Medjedtxm
3
+ * @copyright Crown Copyright 2026
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import Utils from "../Utils.mjs";
9
+ import OperationError from "../errors/OperationError.mjs";
10
+ import { toHex } from "../lib/Hex.mjs";
11
+ import { decryptPRESENT } from "../lib/Present.mjs";
12
+
13
+ /**
14
+ * PRESENT Decrypt operation
15
+ */
16
+ class PRESENTDecrypt extends Operation {
17
+
18
+ /**
19
+ * PRESENTDecrypt constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "PRESENT Decrypt";
25
+ this.module = "Ciphers";
26
+ this.description = "PRESENT is an ultra-lightweight block cipher designed for constrained environments such as RFID tags and sensor networks. It operates on 64-bit blocks and supports 80-bit or 128-bit keys with 31 rounds. Standardised in ISO/IEC 29192-2:2019.<br><br>When using CBC mode, the PKCS#7 padding scheme is used.";
27
+ this.infoURL = "https://wikipedia.org/wiki/PRESENT_(cipher)";
28
+ this.inputType = "string";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ },
37
+ {
38
+ "name": "IV",
39
+ "type": "toggleString",
40
+ "value": "",
41
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
42
+ },
43
+ {
44
+ "name": "Mode",
45
+ "type": "option",
46
+ "value": ["CBC", "ECB"]
47
+ },
48
+ {
49
+ "name": "Input",
50
+ "type": "option",
51
+ "value": ["Hex", "Raw"]
52
+ },
53
+ {
54
+ "name": "Output",
55
+ "type": "option",
56
+ "value": ["Raw", "Hex"]
57
+ },
58
+ {
59
+ "name": "Padding",
60
+ "type": "option",
61
+ "value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
62
+ }
63
+ ];
64
+ }
65
+
66
+ /**
67
+ * @param {string} input
68
+ * @param {Object[]} args
69
+ * @returns {string}
70
+ */
71
+ run(input, args) {
72
+ const key = Utils.convertToByteArray(args[0].string, args[0].option),
73
+ iv = Utils.convertToByteArray(args[1].string, args[1].option),
74
+ [,, mode, inputType, outputType, padding] = args;
75
+
76
+ if (key.length !== 10 && key.length !== 16)
77
+ throw new OperationError(`Invalid key length: ${key.length} bytes
78
+
79
+ PRESENT uses a key length of 10 bytes (80 bits) or 16 bytes (128 bits).`);
80
+
81
+ if (iv.length !== 8 && mode !== "ECB")
82
+ throw new OperationError(`Invalid IV length: ${iv.length} bytes
83
+
84
+ PRESENT uses an IV length of 8 bytes (64 bits).
85
+ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
86
+
87
+ input = Utils.convertToByteArray(input, inputType);
88
+ const output = decryptPRESENT(input, key, iv, mode, padding);
89
+ return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
90
+ }
91
+
92
+ }
93
+
94
+ export default PRESENTDecrypt;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @author Medjedtxm
3
+ * @copyright Crown Copyright 2026
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import Utils from "../Utils.mjs";
9
+ import OperationError from "../errors/OperationError.mjs";
10
+ import { toHex } from "../lib/Hex.mjs";
11
+ import { encryptPRESENT } from "../lib/Present.mjs";
12
+
13
+ /**
14
+ * PRESENT Encrypt operation
15
+ */
16
+ class PRESENTEncrypt extends Operation {
17
+
18
+ /**
19
+ * PRESENTEncrypt constructor
20
+ */
21
+ constructor() {
22
+ super();
23
+
24
+ this.name = "PRESENT Encrypt";
25
+ this.module = "Ciphers";
26
+ this.description = "PRESENT is an ultra-lightweight block cipher designed for constrained environments such as RFID tags and sensor networks. It operates on 64-bit blocks and supports 80-bit or 128-bit keys with 31 rounds. Standardised in ISO/IEC 29192-2:2019.<br><br>When using CBC mode, the PKCS#7 padding scheme is used.";
27
+ this.infoURL = "https://wikipedia.org/wiki/PRESENT_(cipher)";
28
+ this.inputType = "string";
29
+ this.outputType = "string";
30
+ this.args = [
31
+ {
32
+ "name": "Key",
33
+ "type": "toggleString",
34
+ "value": "",
35
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
36
+ },
37
+ {
38
+ "name": "IV",
39
+ "type": "toggleString",
40
+ "value": "",
41
+ "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
42
+ },
43
+ {
44
+ "name": "Mode",
45
+ "type": "option",
46
+ "value": ["CBC", "ECB"]
47
+ },
48
+ {
49
+ "name": "Input",
50
+ "type": "option",
51
+ "value": ["Raw", "Hex"]
52
+ },
53
+ {
54
+ "name": "Output",
55
+ "type": "option",
56
+ "value": ["Hex", "Raw"]
57
+ },
58
+ {
59
+ "name": "Padding",
60
+ "type": "option",
61
+ "value": ["PKCS5", "NO", "ZERO", "RANDOM", "BIT"]
62
+ }
63
+ ];
64
+ }
65
+
66
+ /**
67
+ * @param {string} input
68
+ * @param {Object[]} args
69
+ * @returns {string}
70
+ */
71
+ run(input, args) {
72
+ const key = Utils.convertToByteArray(args[0].string, args[0].option),
73
+ iv = Utils.convertToByteArray(args[1].string, args[1].option),
74
+ [,, mode, inputType, outputType, padding] = args;
75
+
76
+ if (key.length !== 10 && key.length !== 16)
77
+ throw new OperationError(`Invalid key length: ${key.length} bytes
78
+
79
+ PRESENT uses a key length of 10 bytes (80 bits) or 16 bytes (128 bits).`);
80
+
81
+ if (iv.length !== 8 && mode !== "ECB")
82
+ throw new OperationError(`Invalid IV length: ${iv.length} bytes
83
+
84
+ PRESENT uses an IV length of 8 bytes (64 bits).
85
+ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
86
+
87
+ input = Utils.convertToByteArray(input, inputType);
88
+ const output = encryptPRESENT(input, key, iv, mode, padding);
89
+ return outputType === "Hex" ? toHex(output, "") : Utils.byteArrayToUtf8(output);
90
+ }
91
+
92
+ }
93
+
94
+ export default PRESENTEncrypt;
@@ -20,7 +20,7 @@ class ParityBit extends Operation {
20
20
 
21
21
  this.name = "Parity Bit";
22
22
  this.module = "Default";
23
- this.description = "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurence of the delimiter character";
23
+ this.description = "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurrence of the delimiter character";
24
24
  this.infoURL = "https://wikipedia.org/wiki/Parity_bit";
25
25
  this.inputType = "string";
26
26
  this.outputType = "string";
@@ -74,7 +74,7 @@ class ParseIPv4Header extends Operation {
74
74
  checksum = input[10] << 8 | input[11],
75
75
  srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15],
76
76
  dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19],
77
- checksumHeader = input.slice(0, 10).concat([0, 0]).concat(input.slice(12, 20));
77
+ checksumHeader = [...input.slice(0, 10), 0, 0, ...input.slice(12, 20)];
78
78
  let version = (input[0] >>> 4) & 0x0f,
79
79
  options = [];
80
80
 
@@ -33,7 +33,7 @@ class ParseURI extends Operation {
33
33
  * @returns {string}
34
34
  */
35
35
  run(input, args) {
36
- const uri = url.parse(input, true);
36
+ const uri = url.parse(input, false);
37
37
 
38
38
  let output = "";
39
39
 
@@ -43,7 +43,20 @@ class ParseURI extends Operation {
43
43
  if (uri.port) output += "Port:\t\t" + uri.port + "\n";
44
44
  if (uri.pathname) output += "Path name:\t" + uri.pathname + "\n";
45
45
  if (uri.query) {
46
- const keys = Object.keys(uri.query);
46
+ const queryObj = Object.create(null);
47
+ for (const [key, value] of new URLSearchParams(uri.query)) {
48
+ if (Object.prototype.hasOwnProperty.call(queryObj, key)) {
49
+ if (Array.isArray(queryObj[key])) {
50
+ queryObj[key].push(value);
51
+ } else {
52
+ queryObj[key] = [queryObj[key], value];
53
+ }
54
+ } else {
55
+ queryObj[key] = value;
56
+ }
57
+ }
58
+
59
+ const keys = Object.keys(queryObj);
47
60
  let padding = 0;
48
61
 
49
62
  keys.forEach(k => {
@@ -51,10 +64,10 @@ class ParseURI extends Operation {
51
64
  });
52
65
 
53
66
  output += "Arguments:\n";
54
- for (const key in uri.query) {
67
+ for (const key in queryObj) {
55
68
  output += "\t" + key.padEnd(padding, " ");
56
- if (uri.query[key].length) {
57
- output += " = " + uri.query[key] + "\n";
69
+ if (queryObj[key].length) {
70
+ output += " = " + queryObj[key] + "\n";
58
71
  } else {
59
72
  output += "\n";
60
73
  }
@@ -31,7 +31,8 @@ class PseudoRandomNumberGenerator extends Operation {
31
31
  {
32
32
  "name": "Number of bytes",
33
33
  "type": "number",
34
- "value": 32
34
+ "value": 32,
35
+ "min": 1
35
36
  },
36
37
  {
37
38
  "name": "Output as",
@@ -0,0 +1,154 @@
1
+ /**
2
+ * @author p-leriche [philip.leriche@cantab.net]
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+ import OperationError from "../errors/OperationError.mjs";
9
+ import { modPow } from "../lib/BigIntUtils.mjs";
10
+
11
+ /* ---------- helper functions ---------- */
12
+
13
+ /**
14
+ * Generate random BigInt with specified bit length
15
+ */
16
+ function randBigInt(bits) {
17
+ const bytes = Math.ceil(bits / 8);
18
+ const a = new Uint8Array(bytes);
19
+ crypto.getRandomValues(a);
20
+
21
+ // Set high bit to ensure correct bit length
22
+ a[0] |= 1 << (7 - ((8 * bytes - bits)));
23
+ // Set low bit to ensure odd (primes > 2 are odd)
24
+ a[bytes - 1] |= 1;
25
+
26
+ let h = "";
27
+ for (const b of a) h += b.toString(16).padStart(2, "0");
28
+ return BigInt("0x" + h);
29
+ }
30
+
31
+ /**
32
+ * Miller-Rabin primality test
33
+ */
34
+ function isProbablePrime(n, rounds) {
35
+ if (n < 2n) return false;
36
+ if (n === 2n || n === 3n) return true;
37
+ if (n % 2n === 0n) return false;
38
+
39
+ // Write n-1 as 2^r * d
40
+ let d = n - 1n;
41
+ let r = 0n;
42
+ while (d % 2n === 0n) {
43
+ d /= 2n;
44
+ r++;
45
+ }
46
+
47
+ // Witness loop
48
+ for (let i = 0; i < rounds; i++) {
49
+ const a = randBigInt(n.toString(2).length - 1) % (n - 3n) + 2n;
50
+ let x = modPow(a, d, n);
51
+
52
+ if (x === 1n || x === n - 1n) continue;
53
+
54
+ let composite = true;
55
+ for (let j = 0n; j < r - 1n; j++) {
56
+ x = modPow(x, 2n, n);
57
+ if (x === n - 1n) {
58
+ composite = false;
59
+ break;
60
+ }
61
+ }
62
+
63
+ if (composite) return false;
64
+ }
65
+
66
+ return true;
67
+ }
68
+
69
+ /* ---------- operation class ---------- */
70
+
71
+ /**
72
+ * Generate Prime Number operation
73
+ */
74
+ class GeneratePrime extends Operation {
75
+ /**
76
+ * GeneratePrime constructor
77
+ */
78
+ constructor() {
79
+ super();
80
+
81
+ this.name = "Pseudo-Random Prime Generator";
82
+ this.module = "Crypto";
83
+ this.description =
84
+ "Generates a random probable prime number of specified bit length using the Miller-Rabin primality test.<br><br>" +
85
+ "<b>Primality guarantee:</b><br>" +
86
+ "For numbers . 3,317, the result is guaranteed prime (deterministic test).<br>" +
87
+ "For larger numbers, uses probabilistic testing:<br>" +
88
+ "- <b>Standard (7 rounds):</b> Probability of composite approx 1 in 16,000)<br><br>" +
89
+ "- <b>Crypto grade (40 rounds):</b> Probability of composite(approx 1 in 10^24)<br>" +
90
+ "Crypto grade is recommended for cryptographic applications (RSA, Diffie-Hellman, etc.).<br><br>" ;
91
+ this.infoURL = "https://wikipedia.org/wiki/Miller-Rabin_primality_test";
92
+ this.inputType = "string";
93
+ this.outputType = "string";
94
+ this.args = [
95
+ {
96
+ name: "Bit length",
97
+ type: "number",
98
+ value: 512,
99
+ min: 2
100
+ },
101
+ {
102
+ name: "Crypto grade",
103
+ type: "boolean",
104
+ value: false
105
+ },
106
+ {
107
+ name: "Output format",
108
+ type: "option",
109
+ value: ["Decimal", "Hexadecimal"]
110
+ }
111
+ ];
112
+ }
113
+
114
+ /**
115
+ * @param {string} input
116
+ * @param {Object[]} args
117
+ * @returns {string}
118
+ */
119
+ run(input, args) {
120
+ const [bits, cryptoGrade, outputFormat] = args;
121
+
122
+ if (bits < 2) {
123
+ throw new OperationError("Bit length must be at least 2");
124
+ }
125
+
126
+ if (bits > 4096) {
127
+ throw new OperationError("Bit length limited to 4096 bits for performance reasons");
128
+ }
129
+
130
+ const rounds = cryptoGrade ? 40 : 7;
131
+ let attempts = 0;
132
+ const maxAttempts = 10000;
133
+
134
+ let n = randBigInt(bits);
135
+
136
+ while (!isProbablePrime(n, rounds)) {
137
+ n = randBigInt(bits);
138
+ attempts++;
139
+
140
+ if (attempts > maxAttempts) {
141
+ throw new OperationError(`Failed to generate prime after ${maxAttempts} attempts. Try a different bit length.`);
142
+ }
143
+ }
144
+
145
+ // Return only the prime for pipeability
146
+ if (outputFormat === "Hexadecimal") {
147
+ return "0x" + n.toString(16);
148
+ } else {
149
+ return n.toString();
150
+ }
151
+ }
152
+ }
153
+
154
+ export default GeneratePrime;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @author Shailendra [singhshailendra.in]
3
+ * @copyright Crown Copyright 2017
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import { fromBase64, toBase64 } from "../lib/Base64.mjs";
8
+ import Operation from "../Operation.mjs";
9
+ import OperationError from "../errors/OperationError.mjs";
10
+ import Utils from "../Utils.mjs";
11
+
12
+ /**
13
+ * Render PDF operation
14
+ */
15
+ class RenderPDF extends Operation {
16
+
17
+ /**
18
+ * RenderPDF constructor
19
+ */
20
+ constructor() {
21
+ super();
22
+
23
+ this.name = "Render PDF";
24
+ this.module = "File";
25
+ this.description = "Displays the input as a PDF preview. Supports Raw and Base64 input formats.";
26
+ this.inputType = "string";
27
+ this.outputType = "byteArray";
28
+ this.presentType = "html";
29
+ this.args = [
30
+ {
31
+ "name": "Input format",
32
+ "type": "option",
33
+ "value": ["Base64", "Raw"],
34
+ }
35
+ ];
36
+ this.checks = [
37
+ {
38
+ pattern: "^%PDF-",
39
+ flags: "",
40
+ args: ["Raw"],
41
+ useful: true,
42
+ output: {
43
+ mime: "application/pdf"
44
+ }
45
+ }
46
+ ];
47
+ }
48
+
49
+ /**
50
+ * @param {string} input
51
+ * @param {Object[]} args
52
+ * @returns {byteArray}
53
+ */
54
+ run(input, args) {
55
+ const inputFormat = args[0];
56
+
57
+ if (!input.length) return [];
58
+
59
+ // Convert input to raw bytes
60
+ switch (inputFormat) {
61
+ case "Base64":
62
+ input = fromBase64(input, undefined, "byteArray");
63
+ break;
64
+ case "Raw":
65
+ default:
66
+ input = Utils.strToByteArray(input);
67
+ break;
68
+ }
69
+
70
+ // Check PDF signature
71
+ if (
72
+ input[0] !== 0x25 || // %
73
+ input[1] !== 0x50 || // P
74
+ input[2] !== 0x44 || // D
75
+ input[3] !== 0x46 // F
76
+ ) {
77
+ throw new OperationError("Input does not appear to be a PDF file.");
78
+ }
79
+
80
+ return input;
81
+ }
82
+
83
+ /**
84
+ * Displays the PDF using HTML for web apps.
85
+ *
86
+ * @param {byteArray} data
87
+ * @returns {html}
88
+ */
89
+ async present(data) {
90
+ if (!data.length) return "";
91
+
92
+ const base64 = toBase64(data);
93
+ const dataURI = "data:application/pdf;base64," + base64;
94
+
95
+ return `<iframe src="${dataURI}" style="width:100%;height:100%;border:1px solid #ccc;"></iframe>`;
96
+ }
97
+
98
+ }
99
+
100
+ export default RenderPDF;
@@ -20,7 +20,7 @@ class SHA2 extends Operation {
20
20
 
21
21
  this.name = "SHA2";
22
22
  this.module = "Crypto";
23
- this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
23
+ this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bits.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bits.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
24
24
  this.infoURL = "https://wikipedia.org/wiki/SHA-2";
25
25
  this.inputType = "ArrayBuffer";
26
26
  this.outputType = "string";
@@ -43,7 +43,7 @@ class SM4Encrypt extends Operation {
43
43
  {
44
44
  "name": "Mode",
45
45
  "type": "option",
46
- "value": ["CBC", "CFB", "OFB", "CTR", "ECB"]
46
+ "value": ["CBC", "CFB", "OFB", "CTR", "ECB", "CBC/NoPadding", "ECB/NoPadding"]
47
47
  },
48
48
  {
49
49
  "name": "Input",
@@ -75,9 +75,16 @@ class SetDifference extends Operation {
75
75
  * @returns {Object[]}
76
76
  */
77
77
  runSetDifference(a, b) {
78
+ const excluded = new Set(b);
79
+ const seen = new Set();
80
+
78
81
  return a
79
82
  .filter((item) => {
80
- return b.indexOf(item) === -1;
83
+ if (excluded.has(item) || seen.has(item)) {
84
+ return false;
85
+ }
86
+ seen.add(item);
87
+ return true;
81
88
  })
82
89
  .join(this.itemDelimiter);
83
90
  }
@@ -75,9 +75,16 @@ class SetIntersection extends Operation {
75
75
  * @returns {Object[]}
76
76
  */
77
77
  runIntersect(a, b) {
78
+ const included = new Set(b);
79
+ const seen = new Set();
80
+
78
81
  return a
79
82
  .filter((item) => {
80
- return b.indexOf(item) > -1;
83
+ if (!included.has(item) || seen.has(item)) {
84
+ return false;
85
+ }
86
+ seen.add(item);
87
+ return true;
81
88
  })
82
89
  .join(this.itemDelimiter);
83
90
  }
@@ -36,7 +36,8 @@ class ShowOnMap extends Operation {
36
36
  {
37
37
  name: "Input Format",
38
38
  type: "option",
39
- value: ["Auto"].concat(FORMATS)
39
+ value: ["Auto"].concat(FORMATS),
40
+ allowEmpty: false
40
41
  },
41
42
  {
42
43
  name: "Input Delimiter",
@@ -49,7 +50,8 @@ class ShowOnMap extends Operation {
49
50
  "Comma",
50
51
  "Semi-colon",
51
52
  "Colon"
52
- ]
53
+ ],
54
+ allowEmpty: false
53
55
  }
54
56
  ];
55
57
  }
@@ -71,6 +73,16 @@ class ShowOnMap extends Operation {
71
73
  }
72
74
  latLong = latLong.replace(/[,]$/, "");
73
75
  latLong = latLong.replace(/°/g, "");
76
+
77
+ // The map requires a latitude and longitude pair. If the conversion only produced a
78
+ // single value (e.g. because the chosen input delimiter didn't match the input), bail
79
+ // out with a helpful message rather than passing it on to the map, which would throw an
80
+ // uncaught TypeError in the browser.
81
+ const coords = latLong.split(",").map(v => v.trim());
82
+ if (coords.length !== 2 || coords.some(v => v === "" || isNaN(Number(v)))) {
83
+ throw new OperationError(`Could not show coordinates '${latLong}' on the map. Expected a latitude and longitude pair - check that the input format and delimiter are correct.`);
84
+ }
85
+
74
86
  return latLong;
75
87
  }
76
88
  return input;