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.
- package/AGENTS.md +75 -0
- package/CHANGELOG.md +173 -2
- package/Dockerfile +2 -2
- package/Gruntfile.js +1 -0
- package/README.md +7 -6
- package/SECURITY.md +3 -1
- package/package.json +22 -21
- package/src/core/Chef.mjs +2 -0
- package/src/core/Dish.mjs +1 -5
- package/src/core/Ingredient.mjs +92 -0
- package/src/core/Operation.mjs +19 -0
- package/src/core/Recipe.mjs +4 -0
- package/src/core/Utils.mjs +48 -0
- package/src/core/config/Categories.json +22 -6
- package/src/core/config/OperationConfig.json +4774 -1228
- package/src/core/config/modules/Ciphers.mjs +20 -0
- package/src/core/config/modules/Crypto.mjs +10 -0
- package/src/core/config/modules/Default.mjs +8 -0
- package/src/core/config/modules/File.mjs +16 -0
- package/src/core/config/modules/OpModules.mjs +2 -0
- package/src/core/config/scripts/generateHTMLEntities.mjs +139 -0
- package/src/core/config/scripts/htmlEntityOverrides.mjs +86 -0
- package/src/core/dishTypes/DishType.mjs +1 -1
- package/src/core/errors/ExcludedOperationError.mjs +1 -1
- package/src/core/lib/Arithmetic.mjs +21 -5
- package/src/core/lib/BigIntUtils.mjs +0 -1
- package/src/core/lib/COBS.mjs +86 -0
- package/src/core/lib/Charts.mjs +3 -3
- package/src/core/lib/Decimal.mjs +5 -5
- package/src/core/lib/HTMLEntities.mjs +2068 -0
- package/src/core/lib/Present.mjs +422 -0
- package/src/core/lib/Protocol.mjs +8 -6
- package/src/core/lib/TEA.mjs +494 -0
- package/src/core/lib/TLVParser.mjs +16 -7
- package/src/core/lib/Twofish.mjs +608 -0
- package/src/core/operations/AsconDecrypt.mjs +112 -0
- package/src/core/operations/AsconEncrypt.mjs +108 -0
- package/src/core/operations/AsconHash.mjs +49 -0
- package/src/core/operations/AsconMAC.mjs +68 -0
- package/src/core/operations/AutomatedValidationTestOp.mjs +84 -0
- package/src/core/operations/AvroToJSON.mjs +1 -1
- package/src/core/operations/BLAKE3.mjs +5 -1
- package/src/core/operations/BcryptCompare.mjs +11 -5
- package/src/core/operations/BitShiftLeft.mjs +4 -1
- package/src/core/operations/Bzip2Compress.mjs +1 -1
- package/src/core/operations/DechunkHTTPResponse.mjs +4 -1
- package/src/core/operations/ExtendedGCD.mjs +101 -0
- package/src/core/operations/FromBase.mjs +2 -1
- package/src/core/operations/FromCOBS.mjs +38 -0
- package/src/core/operations/FromDecimal.mjs +6 -1
- package/src/core/operations/FromHTMLEntity.mjs +2 -1458
- package/src/core/operations/GenerateDeBruijnSequence.mjs +8 -0
- package/src/core/operations/GenerateHOTP.mjs +21 -6
- package/src/core/operations/GenerateImage.mjs +22 -10
- package/src/core/operations/GeneratePrime.mjs +154 -0
- package/src/core/operations/GenerateTOTP.mjs +24 -7
- package/src/core/operations/Gzip.mjs +1 -3
- package/src/core/operations/Jsonata.mjs +12 -0
- package/src/core/operations/MIMEDecoding.mjs +1 -1
- package/src/core/operations/MOD.mjs +62 -0
- package/src/core/operations/ModularInverse.mjs +107 -0
- package/src/core/operations/PRESENTDecrypt.mjs +94 -0
- package/src/core/operations/PRESENTEncrypt.mjs +94 -0
- package/src/core/operations/ParityBit.mjs +1 -1
- package/src/core/operations/ParseIPv4Header.mjs +1 -1
- package/src/core/operations/ParseURI.mjs +18 -5
- package/src/core/operations/PseudoRandomNumberGenerator.mjs +2 -1
- package/src/core/operations/RandomPrime.mjs +154 -0
- package/src/core/operations/RenderPDF.mjs +100 -0
- package/src/core/operations/SHA2.mjs +1 -1
- package/src/core/operations/SM4Encrypt.mjs +1 -1
- package/src/core/operations/SetDifference.mjs +8 -1
- package/src/core/operations/SetIntersection.mjs +8 -1
- package/src/core/operations/ShowOnMap.mjs +14 -2
- package/src/core/operations/TEADecrypt.mjs +98 -0
- package/src/core/operations/TEAEncrypt.mjs +98 -0
- package/src/core/operations/ToBase.mjs +4 -4
- package/src/core/operations/ToBase32.mjs +20 -4
- package/src/core/operations/ToBinary.mjs +4 -1
- package/src/core/operations/ToCOBS.mjs +38 -0
- package/src/core/operations/ToHTMLEntity.mjs +7 -1430
- package/src/core/operations/ToHexdump.mjs +7 -1
- package/src/core/operations/TwofishDecrypt.mjs +94 -0
- package/src/core/operations/TwofishEncrypt.mjs +94 -0
- package/src/core/operations/URLEncode.mjs +22 -18
- package/src/core/operations/UnescapeUnicodeCharacters.mjs +2 -1
- package/src/core/operations/ViewBitPlane.mjs +9 -3
- package/src/core/operations/Wrap.mjs +5 -0
- package/src/core/operations/XORBruteForce.mjs +4 -1
- package/src/core/operations/XORChecksum.mjs +10 -3
- package/src/core/operations/XTEADecrypt.mjs +110 -0
- package/src/core/operations/XTEAEncrypt.mjs +110 -0
- package/src/core/operations/index.mjs +42 -0
- package/src/core/vendor/ascon.mjs +162 -0
- package/src/core/vendor/htmlEntities/entity.json +2233 -0
- package/src/core/vendor/htmlEntities/entity.txt +14 -0
- package/src/node/api.mjs +4 -1
- package/src/node/index.mjs +105 -0
- package/src/web/HTMLOperation.mjs +2 -1
- package/src/web/stylesheets/layout/_io.css +8 -0
- package/tests/browser/00_nightwatch.js +26 -0
- package/tests/browser/02_ops.js +20 -4
- package/tests/node/index.mjs +2 -0
- package/tests/node/tests/Dish.mjs +19 -0
- package/tests/node/tests/NodeDish.mjs +36 -0
- package/tests/node/tests/ToHTMLEntity.mjs +82 -0
- package/tests/node/tests/Utils.mjs +77 -0
- package/tests/node/tests/lib/ChartsProtocolPrototypePollution.mjs +90 -0
- package/tests/node/tests/nodeApi.mjs +33 -1
- package/tests/node/tests/operations.mjs +26 -1
- package/tests/operations/index.mjs +17 -0
- package/tests/operations/tests/Arithmetic.mjs +33 -0
- package/tests/operations/tests/Ascon.mjs +501 -0
- package/tests/operations/tests/AutomatedValidation.mjs +154 -0
- package/tests/operations/tests/BLAKE3.mjs +39 -1
- package/tests/operations/tests/Base32.mjs +22 -0
- package/tests/operations/tests/COBS.mjs +476 -0
- package/tests/operations/tests/CharEnc.mjs +2 -2
- package/tests/operations/tests/DechunkHTTPResponse.mjs +66 -0
- package/tests/operations/tests/ExtendedGCD.mjs +78 -0
- package/tests/operations/tests/FromBase.mjs +66 -0
- package/tests/operations/tests/FromDecimal.mjs +55 -0
- package/tests/operations/tests/GenerateLoremIpsum.mjs +2 -2
- package/tests/operations/tests/Gzip.mjs +60 -0
- package/tests/operations/tests/HTMLEntity.mjs +126 -0
- package/tests/operations/tests/Hash.mjs +44 -0
- package/tests/operations/tests/Hexdump.mjs +11 -0
- package/tests/operations/tests/Image.mjs +26 -0
- package/tests/operations/tests/Jsonata.mjs +23 -0
- package/tests/operations/tests/MIMEDecoding.mjs +33 -0
- package/tests/operations/tests/MOD.mjs +208 -0
- package/tests/operations/tests/Median.mjs +33 -0
- package/tests/operations/tests/ModularInverse.mjs +78 -0
- package/tests/operations/tests/OTP.mjs +167 -2
- package/tests/operations/tests/PRESENT.mjs +465 -0
- package/tests/operations/tests/ParseIPv4Header.mjs +11 -0
- package/tests/operations/tests/ParseTLV.mjs +41 -0
- package/tests/operations/tests/RenderPDF.mjs +55 -0
- package/tests/operations/tests/SM2.mjs +1 -1
- package/tests/operations/tests/SetDifference.mjs +22 -0
- package/tests/operations/tests/SetIntersection.mjs +23 -1
- package/tests/operations/tests/ShowOnMap.mjs +61 -0
- package/tests/operations/tests/TEA.mjs +566 -0
- package/tests/operations/tests/Twofish.mjs +486 -0
- package/tests/operations/tests/URLEncodeDecode.mjs +26 -0
- package/tests/operations/tests/UnescapeUnicodeCharacters.mjs +88 -0
- package/tests/operations/tests/Wrap.mjs +44 -0
- package/webpack.config.js +3 -3
|
@@ -50,6 +50,14 @@ class GenerateDeBruijnSequence extends Operation {
|
|
|
50
50
|
throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
if (!Number.isInteger(k)) {
|
|
54
|
+
throw new OperationError("Invalid alphabet size, required to be integer.");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!Number.isInteger(n)) {
|
|
58
|
+
throw new OperationError("Invalid key length, required to be integer.");
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
if (n < 2) {
|
|
54
62
|
throw new OperationError("Invalid key length, required to be at least 2.");
|
|
55
63
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
8
9
|
import * as OTPAuth from "otpauth";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -19,7 +20,7 @@ class GenerateHOTP extends Operation {
|
|
|
19
20
|
|
|
20
21
|
this.name = "Generate HOTP";
|
|
21
22
|
this.module = "Default";
|
|
22
|
-
this.description = "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OAUTH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated.";
|
|
23
|
+
this.description = "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OAUTH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. The secret must be a valid base32 string (characters A–Z and 2–7).";
|
|
23
24
|
this.infoURL = "https://wikipedia.org/wiki/HMAC-based_One-time_Password_algorithm";
|
|
24
25
|
this.inputType = "ArrayBuffer";
|
|
25
26
|
this.outputType = "string";
|
|
@@ -27,17 +28,23 @@ class GenerateHOTP extends Operation {
|
|
|
27
28
|
{
|
|
28
29
|
"name": "Name",
|
|
29
30
|
"type": "string",
|
|
30
|
-
"value": ""
|
|
31
|
+
"value": "Account",
|
|
32
|
+
"allowEmpty": false
|
|
31
33
|
},
|
|
32
34
|
{
|
|
33
35
|
"name": "Code length",
|
|
34
36
|
"type": "number",
|
|
35
|
-
"value": 6
|
|
37
|
+
"value": 6,
|
|
38
|
+
"min": 6,
|
|
39
|
+
"max": 8,
|
|
40
|
+
"integer": true
|
|
36
41
|
},
|
|
37
42
|
{
|
|
38
43
|
"name": "Counter",
|
|
39
44
|
"type": "number",
|
|
40
|
-
"value": 0
|
|
45
|
+
"value": 0,
|
|
46
|
+
"min": 0,
|
|
47
|
+
"integer": true
|
|
41
48
|
}
|
|
42
49
|
];
|
|
43
50
|
}
|
|
@@ -47,7 +54,15 @@ class GenerateHOTP extends Operation {
|
|
|
47
54
|
*/
|
|
48
55
|
run(input, args) {
|
|
49
56
|
const secretStr = new TextDecoder("utf-8").decode(input).trim();
|
|
50
|
-
|
|
57
|
+
|
|
58
|
+
let secret;
|
|
59
|
+
try {
|
|
60
|
+
secret = secretStr ?
|
|
61
|
+
OTPAuth.Secret.fromBase32(secretStr.toUpperCase().replace(/\s+/g, "")) :
|
|
62
|
+
new OTPAuth.Secret();
|
|
63
|
+
} catch {
|
|
64
|
+
throw new OperationError("Invalid secret. The input must be a valid base32 string (characters A–Z and 2–7).");
|
|
65
|
+
}
|
|
51
66
|
|
|
52
67
|
const hotp = new OTPAuth.HOTP({
|
|
53
68
|
issuer: "",
|
|
@@ -55,7 +70,7 @@ class GenerateHOTP extends Operation {
|
|
|
55
70
|
algorithm: "SHA1",
|
|
56
71
|
digits: args[1],
|
|
57
72
|
counter: args[2],
|
|
58
|
-
secret
|
|
73
|
+
secret
|
|
59
74
|
});
|
|
60
75
|
|
|
61
76
|
const uri = hotp.toString();
|
|
@@ -12,6 +12,14 @@ import { toBase64 } from "../lib/Base64.mjs";
|
|
|
12
12
|
import { isWorkerEnvironment } from "../Utils.mjs";
|
|
13
13
|
import { Jimp, JimpMime, ResizeStrategy, rgbaToInt } from "jimp";
|
|
14
14
|
|
|
15
|
+
// arbitrary limits to prevent resource exhaustion
|
|
16
|
+
// scale factor of 64 is big enough to likely result in scaling in the display
|
|
17
|
+
// window anyway
|
|
18
|
+
// pixels per row is harder to come up with a figure that won't inconvenience
|
|
19
|
+
// someone. 2048 feels like a reasonable compromise
|
|
20
|
+
const MAX_PIXEL_SCALE_FACTOR = 64;
|
|
21
|
+
const MAX_PIXELS_PER_ROW = 2048;
|
|
22
|
+
|
|
15
23
|
/**
|
|
16
24
|
* Generate Image operation
|
|
17
25
|
*/
|
|
@@ -40,11 +48,17 @@ class GenerateImage extends Operation {
|
|
|
40
48
|
name: "Pixel Scale Factor",
|
|
41
49
|
type: "number",
|
|
42
50
|
value: 8,
|
|
51
|
+
integer: true,
|
|
52
|
+
min: 1,
|
|
53
|
+
max: MAX_PIXEL_SCALE_FACTOR,
|
|
43
54
|
},
|
|
44
55
|
{
|
|
45
56
|
name: "Pixels per row",
|
|
46
57
|
type: "number",
|
|
47
58
|
value: 64,
|
|
59
|
+
integer: true,
|
|
60
|
+
min: 1,
|
|
61
|
+
max: MAX_PIXELS_PER_ROW,
|
|
48
62
|
},
|
|
49
63
|
];
|
|
50
64
|
}
|
|
@@ -58,14 +72,6 @@ class GenerateImage extends Operation {
|
|
|
58
72
|
const [mode, scale, width] = args;
|
|
59
73
|
input = new Uint8Array(input);
|
|
60
74
|
|
|
61
|
-
if (scale <= 0) {
|
|
62
|
-
throw new OperationError("Pixel Scale Factor needs to be > 0");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (width <= 0) {
|
|
66
|
-
throw new OperationError("Pixels per Row needs to be > 0");
|
|
67
|
-
}
|
|
68
|
-
|
|
69
75
|
const bytePerPixelMap = {
|
|
70
76
|
Greyscale: 1,
|
|
71
77
|
RG: 2,
|
|
@@ -74,6 +80,10 @@ class GenerateImage extends Operation {
|
|
|
74
80
|
Bits: 1 / 8,
|
|
75
81
|
};
|
|
76
82
|
|
|
83
|
+
if (!Object.hasOwn(bytePerPixelMap, mode)) {
|
|
84
|
+
throw new OperationError(`Unsupported Mode: (${mode})`);
|
|
85
|
+
}
|
|
86
|
+
|
|
77
87
|
const bytesPerPixel = bytePerPixelMap[mode];
|
|
78
88
|
|
|
79
89
|
if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) {
|
|
@@ -163,8 +173,10 @@ class GenerateImage extends Operation {
|
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
try {
|
|
166
|
-
|
|
167
|
-
return
|
|
176
|
+
// see https://nodejs.org/docs/latest-v24.x/api/buffer.html#bufbyteoffset
|
|
177
|
+
// for why we can't just return result.buffer
|
|
178
|
+
const result = await image.getBuffer(JimpMime.png);
|
|
179
|
+
return result.buffer.slice(result.byteOffset, result.byteOffset + result.byteLength);
|
|
168
180
|
} catch (err) {
|
|
169
181
|
throw new OperationError(`Error generating image. (${err})`);
|
|
170
182
|
}
|
|
@@ -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;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Operation from "../Operation.mjs";
|
|
8
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
8
9
|
import * as OTPAuth from "otpauth";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -18,7 +19,7 @@ class GenerateTOTP extends Operation {
|
|
|
18
19
|
super();
|
|
19
20
|
this.name = "Generate TOTP";
|
|
20
21
|
this.module = "Default";
|
|
21
|
-
this.description = "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OAUTH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. T0 and T1 are in seconds.";
|
|
22
|
+
this.description = "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OAUTH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. The secret must be a valid base32 string (characters A–Z and 2–7). T0 and T1 are in seconds.";
|
|
22
23
|
this.infoURL = "https://wikipedia.org/wiki/Time-based_One-time_Password_algorithm";
|
|
23
24
|
this.inputType = "ArrayBuffer";
|
|
24
25
|
this.outputType = "string";
|
|
@@ -26,22 +27,30 @@ class GenerateTOTP extends Operation {
|
|
|
26
27
|
{
|
|
27
28
|
"name": "Name",
|
|
28
29
|
"type": "string",
|
|
29
|
-
"value": ""
|
|
30
|
+
"value": "Account",
|
|
31
|
+
"allowEmpty": false
|
|
30
32
|
},
|
|
31
33
|
{
|
|
32
34
|
"name": "Code length",
|
|
33
35
|
"type": "number",
|
|
34
|
-
"value": 6
|
|
36
|
+
"value": 6,
|
|
37
|
+
"min": 6,
|
|
38
|
+
"max": 8,
|
|
39
|
+
"integer": true
|
|
35
40
|
},
|
|
36
41
|
{
|
|
37
42
|
"name": "Epoch offset (T0)",
|
|
38
43
|
"type": "number",
|
|
39
|
-
"value": 0
|
|
44
|
+
"value": 0,
|
|
45
|
+
"min": 0,
|
|
46
|
+
"integer": true
|
|
40
47
|
},
|
|
41
48
|
{
|
|
42
49
|
"name": "Interval (T1)",
|
|
43
50
|
"type": "number",
|
|
44
|
-
"value": 30
|
|
51
|
+
"value": 30,
|
|
52
|
+
"min": 1,
|
|
53
|
+
"integer": true
|
|
45
54
|
}
|
|
46
55
|
];
|
|
47
56
|
}
|
|
@@ -51,7 +60,15 @@ class GenerateTOTP extends Operation {
|
|
|
51
60
|
*/
|
|
52
61
|
run(input, args) {
|
|
53
62
|
const secretStr = new TextDecoder("utf-8").decode(input).trim();
|
|
54
|
-
|
|
63
|
+
|
|
64
|
+
let secret;
|
|
65
|
+
try {
|
|
66
|
+
secret = secretStr ?
|
|
67
|
+
OTPAuth.Secret.fromBase32(secretStr.toUpperCase().replace(/\s+/g, "")) :
|
|
68
|
+
new OTPAuth.Secret();
|
|
69
|
+
} catch {
|
|
70
|
+
throw new OperationError("Invalid secret. The input must be a valid base32 string (characters A–Z and 2–7).");
|
|
71
|
+
}
|
|
55
72
|
|
|
56
73
|
const totp = new OTPAuth.TOTP({
|
|
57
74
|
issuer: "",
|
|
@@ -60,7 +77,7 @@ class GenerateTOTP extends Operation {
|
|
|
60
77
|
digits: args[1],
|
|
61
78
|
period: args[3],
|
|
62
79
|
epoch: args[2] * 1000, // Convert seconds to milliseconds
|
|
63
|
-
secret
|
|
80
|
+
secret
|
|
64
81
|
});
|
|
65
82
|
|
|
66
83
|
const uri = totp.toString();
|
|
@@ -74,13 +74,11 @@ class Gzip extends Operation {
|
|
|
74
74
|
}
|
|
75
75
|
if (comment.length) {
|
|
76
76
|
options.flags.comment = true;
|
|
77
|
+
options.flags.fcomment = true;
|
|
77
78
|
options.comment = comment;
|
|
78
79
|
}
|
|
79
80
|
const gzipObj = new Zlib.Gzip(new Uint8Array(input), options);
|
|
80
81
|
const compressed = new Uint8Array(gzipObj.compress());
|
|
81
|
-
if (options.flags.comment && !(compressed[3] & 0x10)) {
|
|
82
|
-
compressed[3] |= 0x10;
|
|
83
|
-
}
|
|
84
82
|
return compressed.buffer;
|
|
85
83
|
}
|
|
86
84
|
|
|
@@ -51,6 +51,18 @@ class JsonataQuery extends Operation {
|
|
|
51
51
|
|
|
52
52
|
try {
|
|
53
53
|
const expression = jsonata(query);
|
|
54
|
+
// Override built-in base64 functions which fail in Web Worker
|
|
55
|
+
// context where `window` is undefined. The jsonata library falls
|
|
56
|
+
// back to `global.Buffer` which also does not exist in workers.
|
|
57
|
+
// `atob`/`btoa` are available in both browser and worker scopes.
|
|
58
|
+
expression.registerFunction("base64decode", (str) => {
|
|
59
|
+
if (typeof str === "undefined") return undefined;
|
|
60
|
+
return atob(str);
|
|
61
|
+
}, "<s-:s>");
|
|
62
|
+
expression.registerFunction("base64encode", (str) => {
|
|
63
|
+
if (typeof str === "undefined") return undefined;
|
|
64
|
+
return btoa(str);
|
|
65
|
+
}, "<s-:s>");
|
|
54
66
|
result = await expression.evaluate(jsonObj);
|
|
55
67
|
} catch (err) {
|
|
56
68
|
throw new OperationError(
|
|
@@ -87,7 +87,7 @@ class MIMEDecoding extends Operation {
|
|
|
87
87
|
end = cur + j + "?=".length;
|
|
88
88
|
|
|
89
89
|
if (encoding.toLowerCase() === "b") {
|
|
90
|
-
text = fromBase64(text);
|
|
90
|
+
text = fromBase64(text, undefined, "byteArray");
|
|
91
91
|
} else if (encoding.toLowerCase() === "q") {
|
|
92
92
|
text = this.parseQEncodedWord(text);
|
|
93
93
|
} else {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Apache-2.0
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import BigNumber from "bignumber.js";
|
|
6
|
+
import Operation from "../Operation.mjs";
|
|
7
|
+
import { createNumArray } from "../lib/Arithmetic.mjs";
|
|
8
|
+
import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* MOD operation
|
|
13
|
+
*/
|
|
14
|
+
class MOD extends Operation {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* MOD constructor
|
|
18
|
+
*/
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
|
|
22
|
+
this.name = "MOD";
|
|
23
|
+
this.module = "Default";
|
|
24
|
+
this.description = "Computes the modulo of each number in a list with a given modulus value. Numbers are extracted from the input based on the delimiter, and non-numeric values are ignored.<br><br>e.g. <code>15 4 7</code> with modulus <code>3</code> becomes <code>0 1 1</code>";
|
|
25
|
+
this.inputType = "string";
|
|
26
|
+
this.outputType = "string";
|
|
27
|
+
this.args = [
|
|
28
|
+
{
|
|
29
|
+
"name": "Modulus",
|
|
30
|
+
"type": "number",
|
|
31
|
+
"value": 2
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "Delimiter",
|
|
35
|
+
"type": "option",
|
|
36
|
+
"value": ARITHMETIC_DELIM_OPTIONS,
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} input
|
|
43
|
+
* @param {Object[]} args
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
run(input, args) {
|
|
47
|
+
const modulus = new BigNumber(args[0]);
|
|
48
|
+
const delimiter = args[1];
|
|
49
|
+
|
|
50
|
+
if (modulus.isZero()) {
|
|
51
|
+
throw new Error("Modulus cannot be zero");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const numbers = createNumArray(input, delimiter);
|
|
55
|
+
const results = numbers.map(num => num.mod(modulus));
|
|
56
|
+
|
|
57
|
+
return results.join(" ");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default MOD;
|
|
@@ -0,0 +1,107 @@
|
|
|
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 { parseBigInt, egcd } from "../lib/BigIntUtils.mjs";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/* ---------- operation class ---------- */
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Modular Inverse operation
|
|
16
|
+
*/
|
|
17
|
+
class ModularInverse extends Operation {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* ModularInverse constructor
|
|
21
|
+
*/
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
|
|
25
|
+
this.name = "Modular Inverse";
|
|
26
|
+
this.module = "Crypto";
|
|
27
|
+
this.description =
|
|
28
|
+
"Computes the modular multiplicative inverse of <i>a</i> modulo <i>m</i>.<br><br>" +
|
|
29
|
+
"Finds <i>x</i> such that a*x = 1 (mod m).<br><br>" +
|
|
30
|
+
"<b>Input handling:</b> If either <i>a</i> or <i>m</i> is left blank, " +
|
|
31
|
+
"its value is taken from the Input field.";
|
|
32
|
+
this.infoURL = "https://wikipedia.org/wiki/Modular_multiplicative_inverse";
|
|
33
|
+
this.inputType = "string";
|
|
34
|
+
this.outputType = "string";
|
|
35
|
+
this.args = [
|
|
36
|
+
{
|
|
37
|
+
name: "Value (a)",
|
|
38
|
+
type: "string",
|
|
39
|
+
value: ""
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "Modulus (m)",
|
|
43
|
+
type: "string",
|
|
44
|
+
value: ""
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} input
|
|
51
|
+
* @param {Object[]} args
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
run(input, args) {
|
|
55
|
+
const [aStr, mStr] = args;
|
|
56
|
+
|
|
57
|
+
// Trim everything so "" and " " count as empty
|
|
58
|
+
const aParam = aStr?.trim();
|
|
59
|
+
const mParam = mStr?.trim();
|
|
60
|
+
const inputVal = input?.trim();
|
|
61
|
+
|
|
62
|
+
let a, m;
|
|
63
|
+
|
|
64
|
+
if (aParam && mParam) {
|
|
65
|
+
// Case 1: value and modulus both given as parameters
|
|
66
|
+
a = aParam;
|
|
67
|
+
m = mParam;
|
|
68
|
+
} else if (!aParam && mParam) {
|
|
69
|
+
// Case 2: value missing - take from input
|
|
70
|
+
a = inputVal;
|
|
71
|
+
m = mParam;
|
|
72
|
+
if (!a) throw new OperationError("Value (a) must be defined");
|
|
73
|
+
} else if (aParam && !mParam) {
|
|
74
|
+
// Case 3: modulus missing - take from input
|
|
75
|
+
a = aParam;
|
|
76
|
+
m = inputVal;
|
|
77
|
+
if (!m) throw new OperationError("Modulus (m) must be defined");
|
|
78
|
+
} else if (!aParam && !mParam) {
|
|
79
|
+
// Case 4: value and modulus both missing
|
|
80
|
+
throw new OperationError("Value (a) and Modulus (m) must be defined");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const aBI = parseBigInt(a, "Value (a)");
|
|
84
|
+
const mBI = parseBigInt(m, "Modulus (m)");
|
|
85
|
+
|
|
86
|
+
if (mBI <= 0n) {
|
|
87
|
+
throw new OperationError("Modulus must be greater than zero");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const aNorm = ((aBI % mBI) + mBI) % mBI;
|
|
91
|
+
const [g, x] = egcd(aNorm, mBI);
|
|
92
|
+
|
|
93
|
+
if (g !== 1n && g !== -1n) {
|
|
94
|
+
throw new OperationError("Inverse does not exist because gcd(a, m) ≠ 1");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let inv = x;
|
|
98
|
+
if (g === -1n) inv = -inv;
|
|
99
|
+
|
|
100
|
+
inv = ((inv % mBI) + mBI) % mBI;
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
return inv.toString();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default ModularInverse;
|