mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-20 06:55:08 -04:00
Merge branch 'master' into feature/docker-multiplatform-build
This commit is contained in:
commit
b2981d3cc7
27 changed files with 2454 additions and 74 deletions
17
.cspell.json
Normal file
17
.cspell.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"version": "0.2",
|
||||||
|
"language": "en,en-gb",
|
||||||
|
"words": [],
|
||||||
|
"dictionaries": [
|
||||||
|
"npm",
|
||||||
|
"softwareTerms",
|
||||||
|
"node",
|
||||||
|
"html",
|
||||||
|
"css",
|
||||||
|
"bash",
|
||||||
|
"en-gb",
|
||||||
|
"misc"
|
||||||
|
],
|
||||||
|
"ignorePaths": ["package.json", "package-lock.json", "node_modules"]
|
||||||
|
}
|
||||||
|
|
1136
package-lock.json
generated
1136
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -61,6 +61,7 @@
|
||||||
"compression-webpack-plugin": "^11.1.0",
|
"compression-webpack-plugin": "^11.1.0",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^12.0.2",
|
||||||
"core-js": "^3.37.1",
|
"core-js": "^3.37.1",
|
||||||
|
"cspell": "^8.17.3",
|
||||||
"css-loader": "7.1.2",
|
"css-loader": "7.1.2",
|
||||||
"eslint": "^9.4.0",
|
"eslint": "^9.4.0",
|
||||||
"eslint-plugin-jsdoc": "^48.2.9",
|
"eslint-plugin-jsdoc": "^48.2.9",
|
||||||
|
@ -193,6 +194,7 @@
|
||||||
"testui": "npx grunt testui",
|
"testui": "npx grunt testui",
|
||||||
"testuidev": "npx nightwatch --env=dev",
|
"testuidev": "npx nightwatch --env=dev",
|
||||||
"lint": "npx grunt lint",
|
"lint": "npx grunt lint",
|
||||||
|
"lint:grammar": "cspell ./src",
|
||||||
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup && npx grunt exec:fixJimpModule",
|
"postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup && npx grunt exec:fixJimpModule",
|
||||||
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
||||||
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
|
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
|
||||||
|
|
|
@ -74,7 +74,10 @@
|
||||||
"CBOR Decode",
|
"CBOR Decode",
|
||||||
"Caret/M-decode",
|
"Caret/M-decode",
|
||||||
"Rison Encode",
|
"Rison Encode",
|
||||||
"Rison Decode"
|
"Rison Decode",
|
||||||
|
"To Modhex",
|
||||||
|
"From Modhex",
|
||||||
|
"MIME Decoding"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,3 +62,9 @@ export const URL_REGEX = new RegExp(protocol + hostname + "(?:" + port + ")?(?:"
|
||||||
* Domain name regular expression
|
* Domain name regular expression
|
||||||
*/
|
*/
|
||||||
export const DOMAIN_REGEX = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
export const DOMAIN_REGEX = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DMARC Domain name regular expression
|
||||||
|
*/
|
||||||
|
export const DMARC_DOMAIN_REGEX = /\b((?=[a-z0-9_-]{1,63}\.)(xn--)?[a-z0-9_]+(-[a-z0-9_]+)*\.)+[a-z]{2,63}\b/ig;
|
||||||
|
|
165
src/core/lib/Modhex.mjs
Normal file
165
src/core/lib/Modhex.mjs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/**
|
||||||
|
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import { fromHex, toHex } from "./Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modhex alphabet.
|
||||||
|
*/
|
||||||
|
const MODHEX_ALPHABET = "cbdefghijklnrtuv";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modhex alphabet map.
|
||||||
|
*/
|
||||||
|
const MODHEX_ALPHABET_MAP = MODHEX_ALPHABET.split("");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hex alphabet to substitute Modhex.
|
||||||
|
*/
|
||||||
|
const HEX_ALPHABET = "0123456789abcdef";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hex alphabet map to substitute Modhex.
|
||||||
|
*/
|
||||||
|
const HEX_ALPHABET_MAP = HEX_ALPHABET.split("");
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a byte array into a modhex string.
|
||||||
|
*
|
||||||
|
* @param {byteArray|Uint8Array|ArrayBuffer} data
|
||||||
|
* @param {string} [delim=" "]
|
||||||
|
* @param {number} [padding=2]
|
||||||
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns "cl bf bu"
|
||||||
|
* toModhex([10,20,30]);
|
||||||
|
*
|
||||||
|
* // returns "cl:bf:bu"
|
||||||
|
* toModhex([10,20,30], ":");
|
||||||
|
*/
|
||||||
|
export function toModhex(data, delim=" ", padding=2, extraDelim="", lineSize=0) {
|
||||||
|
if (!data) return "";
|
||||||
|
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
||||||
|
|
||||||
|
const regularHexString = toHex(data, "", padding, "", 0);
|
||||||
|
|
||||||
|
let modhexString = "";
|
||||||
|
for (const letter of regularHexString.split("")) {
|
||||||
|
modhexString += MODHEX_ALPHABET_MAP[HEX_ALPHABET_MAP.indexOf(letter)];
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
const groupingRegexp = new RegExp(`.{1,${padding}}`, "g");
|
||||||
|
const groupedModhex = modhexString.match(groupingRegexp);
|
||||||
|
|
||||||
|
for (let i = 0; i < groupedModhex.length; i++) {
|
||||||
|
const group = groupedModhex[i];
|
||||||
|
output += group + delim;
|
||||||
|
|
||||||
|
if (extraDelim) {
|
||||||
|
output += extraDelim;
|
||||||
|
}
|
||||||
|
// Add LF after each lineSize amount of bytes but not at the end
|
||||||
|
if ((i !== groupedModhex.length - 1) && ((i + 1) % lineSize === 0)) {
|
||||||
|
output += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the extraDelim at the end (if there is one)
|
||||||
|
// and remove the delim at the end, but if it's prepended there's nothing to remove
|
||||||
|
const rTruncLen = extraDelim.length + delim.length;
|
||||||
|
if (rTruncLen) {
|
||||||
|
// If rTruncLen === 0 then output.slice(0,0) will be returned, which is nothing
|
||||||
|
return output.slice(0, -rTruncLen);
|
||||||
|
} else {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a byte array into a modhex string as efficiently as possible with no options.
|
||||||
|
*
|
||||||
|
* @param {byteArray|Uint8Array|ArrayBuffer} data
|
||||||
|
* @returns {string}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns "clbfbu"
|
||||||
|
* toModhexFast([10,20,30]);
|
||||||
|
*/
|
||||||
|
export function toModhexFast(data) {
|
||||||
|
if (!data) return "";
|
||||||
|
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
||||||
|
|
||||||
|
const output = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
output.push(MODHEX_ALPHABET_MAP[(data[i] >> 4) & 0xf]);
|
||||||
|
output.push(MODHEX_ALPHABET_MAP[data[i] & 0xf]);
|
||||||
|
}
|
||||||
|
return output.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a modhex string into a byte array.
|
||||||
|
*
|
||||||
|
* @param {string} data
|
||||||
|
* @param {string} [delim]
|
||||||
|
* @param {number} [byteLen=2]
|
||||||
|
* @returns {byteArray}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // returns [10,20,30]
|
||||||
|
* fromModhex("cl bf bu");
|
||||||
|
*
|
||||||
|
* // returns [10,20,30]
|
||||||
|
* fromModhex("cl:bf:bu", "Colon");
|
||||||
|
*/
|
||||||
|
export function fromModhex(data, delim="Auto", byteLen=2) {
|
||||||
|
if (byteLen < 1 || Math.round(byteLen) !== byteLen)
|
||||||
|
throw new OperationError("Byte length must be a positive integer");
|
||||||
|
|
||||||
|
// The `.replace(/\s/g, "")` an interesting workaround: Hex "multiline" tests aren't actually
|
||||||
|
// multiline. Tests for Modhex fixes that, thus exposing the issue.
|
||||||
|
data = data.toLowerCase().replace(/\s/g, "");
|
||||||
|
|
||||||
|
if (delim !== "None") {
|
||||||
|
const delimRegex = delim === "Auto" ? /[^cbdefghijklnrtuv]/gi : Utils.regexRep(delim);
|
||||||
|
data = data.split(delimRegex);
|
||||||
|
} else {
|
||||||
|
data = [data];
|
||||||
|
}
|
||||||
|
|
||||||
|
let regularHexString = "";
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
for (const letter of data[i].split("")) {
|
||||||
|
regularHexString += HEX_ALPHABET_MAP[MODHEX_ALPHABET_MAP.indexOf(letter)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = fromHex(regularHexString, "None", byteLen);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To Modhex delimiters.
|
||||||
|
*/
|
||||||
|
export const TO_MODHEX_DELIM_OPTIONS = ["Space", "Percent", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From Modhex delimiters.
|
||||||
|
*/
|
||||||
|
export const FROM_MODHEX_DELIM_OPTIONS = ["Auto"].concat(TO_MODHEX_DELIM_OPTIONS);
|
|
@ -18,7 +18,7 @@ class ConvertLeetSpeak extends Operation {
|
||||||
|
|
||||||
this.name = "Convert Leet Speak";
|
this.name = "Convert Leet Speak";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Converts to and from Leet Speak";
|
this.description = "Converts to and from Leet Speak.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Leet";
|
this.infoURL = "https://wikipedia.org/wiki/Leet";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -39,13 +39,16 @@ class ConvertLeetSpeak extends Operation {
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const direction = args[0];
|
const direction = args[0];
|
||||||
|
|
||||||
if (direction === "To Leet Speak") {
|
if (direction === "To Leet Speak") {
|
||||||
return input.replace(/[abcdefghijklmnopqrstuvwxyz]/gi, char => {
|
return input.replace(/[a-z]/gi, char => {
|
||||||
return toLeetMap[char.toLowerCase()] || char;
|
const leetChar = toLeetMap[char.toLowerCase()] || char;
|
||||||
|
return char === char.toUpperCase() ? leetChar.toUpperCase() : leetChar;
|
||||||
});
|
});
|
||||||
} else if (direction === "From Leet Speak") {
|
} else if (direction === "From Leet Speak") {
|
||||||
return input.replace(/[48cd3f6h1jklmn0pqr57uvwxyz]/g, char => {
|
return input.replace(/[48cd3f6h1jklmn0pqr57uvwxyz]/gi, char => {
|
||||||
return fromLeetMap[char] || char;
|
const normalChar = fromLeetMap[char] || char;
|
||||||
|
return normalChar;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ class DESDecrypt extends Operation {
|
||||||
|
|
||||||
this.name = "DES Decrypt";
|
this.name = "DES Decrypt";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
|
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
|
this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -72,8 +72,7 @@ class DESDecrypt extends Operation {
|
||||||
if (key.length !== 8) {
|
if (key.length !== 8) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
DES uses a key length of 8 bytes (64 bits).
|
DES uses a key length of 8 bytes (64 bits).`);
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).`);
|
|
||||||
}
|
}
|
||||||
if (iv.length !== 8 && mode !== "ECB") {
|
if (iv.length !== 8 && mode !== "ECB") {
|
||||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
||||||
|
|
|
@ -22,7 +22,7 @@ class DESEncrypt extends Operation {
|
||||||
|
|
||||||
this.name = "DES Encrypt";
|
this.name = "DES Encrypt";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
|
this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
|
this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -70,8 +70,7 @@ class DESEncrypt extends Operation {
|
||||||
if (key.length !== 8) {
|
if (key.length !== 8) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
DES uses a key length of 8 bytes (64 bits).
|
DES uses a key length of 8 bytes (64 bits).`);
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).`);
|
|
||||||
}
|
}
|
||||||
if (iv.length !== 8 && mode !== "ECB") {
|
if (iv.length !== 8 && mode !== "ECB") {
|
||||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import { search, DOMAIN_REGEX } from "../lib/Extract.mjs";
|
import { search, DOMAIN_REGEX, DMARC_DOMAIN_REGEX } from "../lib/Extract.mjs";
|
||||||
import { caseInsensitiveSort } from "../lib/Sort.mjs";
|
import { caseInsensitiveSort } from "../lib/Sort.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +39,11 @@ class ExtractDomains extends Operation {
|
||||||
name: "Unique",
|
name: "Unique",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false
|
value: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Underscore (DMARC, DKIM, etc)",
|
||||||
|
type: "boolean",
|
||||||
|
value: false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -49,11 +54,11 @@ class ExtractDomains extends Operation {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const [displayTotal, sort, unique] = args;
|
const [displayTotal, sort, unique, dmarc] = args;
|
||||||
|
|
||||||
const results = search(
|
const results = search(
|
||||||
input,
|
input,
|
||||||
DOMAIN_REGEX,
|
dmarc ? DMARC_DOMAIN_REGEX : DOMAIN_REGEX,
|
||||||
null,
|
null,
|
||||||
sort ? caseInsensitiveSort : null,
|
sort ? caseInsensitiveSort : null,
|
||||||
unique
|
unique
|
||||||
|
|
84
src/core/operations/FromModhex.mjs
Normal file
84
src/core/operations/FromModhex.mjs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import { FROM_MODHEX_DELIM_OPTIONS, fromModhex } from "../lib/Modhex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From Modhex operation
|
||||||
|
*/
|
||||||
|
class FromModhex extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FromModhex constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "From Modhex";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Converts a modhex byte string back into its raw value.";
|
||||||
|
this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "byteArray";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Delimiter",
|
||||||
|
type: "option",
|
||||||
|
value: FROM_MODHEX_DELIM_OPTIONS
|
||||||
|
}
|
||||||
|
];
|
||||||
|
this.checks = [
|
||||||
|
{
|
||||||
|
pattern: "^(?:[cbdefghijklnrtuv]{2})+$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["None"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^[cbdefghijklnrtuv]{2}(?: [cbdefghijklnrtuv]{2})*$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Space"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^[cbdefghijklnrtuv]{2}(?:,[cbdefghijklnrtuv]{2})*$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Comma"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^[cbdefghijklnrtuv]{2}(?:;[cbdefghijklnrtuv]{2})*$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Semi-colon"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^[cbdefghijklnrtuv]{2}(?::[cbdefghijklnrtuv]{2})*$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Colon"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^[cbdefghijklnrtuv]{2}(?:\\n[cbdefghijklnrtuv]{2})*$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["Line feed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^[cbdefghijklnrtuv]{2}(?:\\r\\n[cbdefghijklnrtuv]{2})*$",
|
||||||
|
flags: "i",
|
||||||
|
args: ["CRLF"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {byteArray}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const delim = args[0] || "Auto";
|
||||||
|
return fromModhex(input, delim, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FromModhex;
|
|
@ -1,5 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @author n1073645 [n1073645@gmail.com]
|
* @author n1073645 [n1073645@gmail.com]
|
||||||
|
* @author k3ach [k3ach@proton.me]
|
||||||
* @copyright Crown Copyright 2020
|
* @copyright Crown Copyright 2020
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -20,39 +21,46 @@ class LuhnChecksum extends Operation {
|
||||||
|
|
||||||
this.name = "Luhn Checksum";
|
this.name = "Luhn Checksum";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "The Luhn algorithm, also known as the modulus 10 or mod 10 algorithm, is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers and Canadian Social Insurance Numbers.";
|
this.description = "The Luhn mod N algorithm using the english alphabet. The Luhn mod N algorithm is an extension to the Luhn algorithm (also known as mod 10 algorithm) that allows it to work with sequences of values in any even-numbered base. This can be useful when a check digit is required to validate an identification string composed of letters, a combination of letters and digits or any arbitrary set of N characters where N is divisible by 2.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Luhn_algorithm";
|
this.infoURL = "https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [];
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Radix",
|
||||||
|
"type": "number",
|
||||||
|
"value": 10
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the Luhn Checksum from the input.
|
* Generates the Luhn checksum from the input.
|
||||||
*
|
*
|
||||||
* @param {string} inputStr
|
* @param {string} inputStr
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
checksum(inputStr) {
|
checksum(inputStr, radix = 10) {
|
||||||
let even = false;
|
let even = false;
|
||||||
return inputStr.split("").reverse().reduce((acc, elem) => {
|
return inputStr.split("").reverse().reduce((acc, elem) => {
|
||||||
// Convert element to integer.
|
// Convert element to an integer based on the provided radix.
|
||||||
let temp = parseInt(elem, 10);
|
let temp = parseInt(elem, radix);
|
||||||
|
|
||||||
// If element is not an integer.
|
// If element is not a valid number in the given radix.
|
||||||
if (isNaN(temp))
|
if (isNaN(temp)) {
|
||||||
throw new OperationError("Character: " + elem + " is not a digit.");
|
throw new Error("Character: " + elem + " is not valid in radix " + radix + ".");
|
||||||
|
}
|
||||||
|
|
||||||
// If element is in an even position
|
// If element is in an even position
|
||||||
if (even) {
|
if (even) {
|
||||||
// Double the element and add the quotient and remainder together.
|
// Double the element and sum the quotient and remainder.
|
||||||
temp = 2 * elem;
|
temp = 2 * temp;
|
||||||
temp = Math.floor(temp/10) + (temp % 10);
|
temp = Math.floor(temp / radix) + (temp % radix);
|
||||||
}
|
}
|
||||||
|
|
||||||
even = !even;
|
even = !even;
|
||||||
return acc + temp;
|
return acc + temp;
|
||||||
}, 0) % 10;
|
}, 0) % radix; // Use radix as the modulus base
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,9 +71,20 @@ class LuhnChecksum extends Operation {
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
if (!input) return "";
|
if (!input) return "";
|
||||||
|
|
||||||
const checkSum = this.checksum(input);
|
const radix = args[0];
|
||||||
let checkDigit = this.checksum(input + "0");
|
|
||||||
checkDigit = checkDigit === 0 ? 0 : (10-checkDigit);
|
if (radix < 2 || radix > 36) {
|
||||||
|
throw new OperationError("Error: Radix argument must be between 2 and 36");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (radix % 2 !== 0) {
|
||||||
|
throw new OperationError("Error: Radix argument must be divisible by 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkSum = this.checksum(input, radix).toString(radix);
|
||||||
|
let checkDigit = this.checksum(input + "0", radix);
|
||||||
|
checkDigit = checkDigit === 0 ? 0 : (radix - checkDigit);
|
||||||
|
checkDigit = checkDigit.toString(radix);
|
||||||
|
|
||||||
return `Checksum: ${checkSum}
|
return `Checksum: ${checkSum}
|
||||||
Checkdigit: ${checkDigit}
|
Checkdigit: ${checkDigit}
|
||||||
|
|
171
src/core/operations/MIMEDecoding.mjs
Normal file
171
src/core/operations/MIMEDecoding.mjs
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
/**
|
||||||
|
* @author mshwed [m@ttshwed.com]
|
||||||
|
* @copyright Crown Copyright 2019
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { fromHex } from "../lib/Hex.mjs";
|
||||||
|
import { fromBase64 } from "../lib/Base64.mjs";
|
||||||
|
import cptable from "codepage";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIME Decoding operation
|
||||||
|
*/
|
||||||
|
class MIMEDecoding extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIMEDecoding constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "MIME Decoding";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Enables the decoding of MIME message header extensions for non-ASCII text";
|
||||||
|
this.infoURL = "https://tools.ietf.org/html/rfc2047";
|
||||||
|
this.inputType = "byteArray";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {byteArray} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const mimeEncodedText = Utils.byteArrayToUtf8(input);
|
||||||
|
const encodedHeaders = mimeEncodedText.replace(/\r\n/g, "\n");
|
||||||
|
|
||||||
|
const decodedHeader = this.decodeHeaders(encodedHeaders);
|
||||||
|
|
||||||
|
return decodedHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode MIME header strings
|
||||||
|
*
|
||||||
|
* @param headerString
|
||||||
|
*/
|
||||||
|
decodeHeaders(headerString) {
|
||||||
|
// No encoded words detected
|
||||||
|
let i = headerString.indexOf("=?");
|
||||||
|
if (i === -1) return headerString;
|
||||||
|
|
||||||
|
let decodedHeaders = headerString.slice(0, i);
|
||||||
|
let header = headerString.slice(i);
|
||||||
|
|
||||||
|
let isBetweenWords = false;
|
||||||
|
let start, cur, charset, encoding, j, end, text;
|
||||||
|
while (header.length > -1) {
|
||||||
|
start = header.indexOf("=?");
|
||||||
|
if (start === -1) break;
|
||||||
|
cur = start + "=?".length;
|
||||||
|
|
||||||
|
i = header.slice(cur).indexOf("?");
|
||||||
|
if (i === -1) break;
|
||||||
|
|
||||||
|
charset = header.slice(cur, cur + i);
|
||||||
|
cur += i + "?".length;
|
||||||
|
|
||||||
|
if (header.length < cur + "Q??=".length) break;
|
||||||
|
|
||||||
|
encoding = header[cur];
|
||||||
|
cur += 1;
|
||||||
|
|
||||||
|
if (header[cur] !== "?") break;
|
||||||
|
|
||||||
|
cur += 1;
|
||||||
|
|
||||||
|
j = header.slice(cur).indexOf("?=");
|
||||||
|
if (j === -1) break;
|
||||||
|
|
||||||
|
text = header.slice(cur, cur + j);
|
||||||
|
end = cur + j + "?=".length;
|
||||||
|
|
||||||
|
if (encoding.toLowerCase() === "b") {
|
||||||
|
text = fromBase64(text);
|
||||||
|
} else if (encoding.toLowerCase() === "q") {
|
||||||
|
text = this.parseQEncodedWord(text);
|
||||||
|
} else {
|
||||||
|
isBetweenWords = false;
|
||||||
|
decodedHeaders += header.slice(0, start + 2);
|
||||||
|
header = header.slice(start + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start > 0 && (!isBetweenWords || header.slice(0, start).search(/\S/g) > -1)) {
|
||||||
|
decodedHeaders += header.slice(0, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedHeaders += this.convertFromCharset(charset, text);
|
||||||
|
|
||||||
|
header = header.slice(end);
|
||||||
|
isBetweenWords = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.length > 0) {
|
||||||
|
decodedHeaders += header;
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodedHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts decoded text for supported charsets.
|
||||||
|
* Supports UTF-8, US-ASCII, ISO-8859-*
|
||||||
|
*
|
||||||
|
* @param encodedWord
|
||||||
|
*/
|
||||||
|
convertFromCharset(charset, encodedText) {
|
||||||
|
charset = charset.toLowerCase();
|
||||||
|
const parsedCharset = charset.split("-");
|
||||||
|
|
||||||
|
if (parsedCharset.length === 2 && parsedCharset[0] === "utf" && charset === "utf-8") {
|
||||||
|
return cptable.utils.decode(65001, encodedText);
|
||||||
|
} else if (parsedCharset.length === 2 && charset === "us-ascii") {
|
||||||
|
return cptable.utils.decode(20127, encodedText);
|
||||||
|
} else if (parsedCharset.length === 3 && parsedCharset[0] === "iso" && parsedCharset[1] === "8859") {
|
||||||
|
const isoCharset = parseInt(parsedCharset[2], 10);
|
||||||
|
if (isoCharset >= 1 && isoCharset <= 16) {
|
||||||
|
return cptable.utils.decode(28590 + isoCharset, encodedText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new OperationError("Unhandled Charset");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a Q encoded word
|
||||||
|
*
|
||||||
|
* @param encodedWord
|
||||||
|
*/
|
||||||
|
parseQEncodedWord(encodedWord) {
|
||||||
|
let decodedWord = "";
|
||||||
|
for (let i = 0; i < encodedWord.length; i++) {
|
||||||
|
if (encodedWord[i] === "_") {
|
||||||
|
decodedWord += " ";
|
||||||
|
// Parse hex encoding
|
||||||
|
} else if (encodedWord[i] === "=") {
|
||||||
|
if ((i + 2) >= encodedWord.length) throw new OperationError("Incorrectly Encoded Word");
|
||||||
|
const decodedHex = Utils.byteArrayToChars(fromHex(encodedWord.substring(i + 1, i + 3)));
|
||||||
|
decodedWord += decodedHex;
|
||||||
|
i += 2;
|
||||||
|
} else if (
|
||||||
|
(encodedWord[i].charCodeAt(0) >= " ".charCodeAt(0) && encodedWord[i].charCodeAt(0) <= "~".charCodeAt(0)) ||
|
||||||
|
encodedWord[i] === "\n" ||
|
||||||
|
encodedWord[i] === "\r" ||
|
||||||
|
encodedWord[i] === "\t") {
|
||||||
|
decodedWord += encodedWord[i];
|
||||||
|
} else {
|
||||||
|
throw new OperationError("Incorrectly Encoded Word");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodedWord;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MIMEDecoding;
|
|
@ -59,15 +59,16 @@ class ROT13 extends Operation {
|
||||||
rot13Upperacse = args[1],
|
rot13Upperacse = args[1],
|
||||||
rotNumbers = args[2];
|
rotNumbers = args[2];
|
||||||
let amount = args[3],
|
let amount = args[3],
|
||||||
chr;
|
amountNumbers = args[3];
|
||||||
|
|
||||||
if (amount) {
|
if (amount) {
|
||||||
if (amount < 0) {
|
if (amount < 0) {
|
||||||
amount = 26 - (Math.abs(amount) % 26);
|
amount = 26 - (Math.abs(amount) % 26);
|
||||||
|
amountNumbers = 10 - (Math.abs(amountNumbers) % 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
chr = input[i];
|
let chr = input[i];
|
||||||
if (rot13Upperacse && chr >= 65 && chr <= 90) { // Upper case
|
if (rot13Upperacse && chr >= 65 && chr <= 90) { // Upper case
|
||||||
chr = (chr - 65 + amount) % 26;
|
chr = (chr - 65 + amount) % 26;
|
||||||
output[i] = chr + 65;
|
output[i] = chr + 65;
|
||||||
|
@ -75,7 +76,7 @@ class ROT13 extends Operation {
|
||||||
chr = (chr - 97 + amount) % 26;
|
chr = (chr - 97 + amount) % 26;
|
||||||
output[i] = chr + 97;
|
output[i] = chr + 97;
|
||||||
} else if (rotNumbers && chr >= 48 && chr <= 57) { // Numbers
|
} else if (rotNumbers && chr >= 48 && chr <= 57) { // Numbers
|
||||||
chr = (chr - 48 + amount) % 10;
|
chr = (chr - 48 + amountNumbers) % 10;
|
||||||
output[i] = chr + 48;
|
output[i] = chr + 48;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
55
src/core/operations/ToModhex.mjs
Normal file
55
src/core/operations/ToModhex.mjs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import { TO_MODHEX_DELIM_OPTIONS, toModhex } from "../lib/Modhex.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To Modhex operation
|
||||||
|
*/
|
||||||
|
class ToModhex extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ToModhex constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "To Modhex";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Converts the input string to modhex bytes separated by the specified delimiter.";
|
||||||
|
this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex";
|
||||||
|
this.inputType = "ArrayBuffer";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Delimiter",
|
||||||
|
type: "option",
|
||||||
|
value: TO_MODHEX_DELIM_OPTIONS
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bytes per line",
|
||||||
|
type: "number",
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const delim = Utils.charRep(args[0]);
|
||||||
|
const lineSize = args[1];
|
||||||
|
|
||||||
|
return toModhex(new Uint8Array(input), delim, 2, "", lineSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ToModhex;
|
|
@ -22,7 +22,7 @@ class TripleDESDecrypt extends Operation {
|
||||||
|
|
||||||
this.name = "Triple DES Decrypt";
|
this.name = "Triple DES Decrypt";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description = "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
|
this.description = "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Triple_DES";
|
this.infoURL = "https://wikipedia.org/wiki/Triple_DES";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -73,8 +73,7 @@ class TripleDESDecrypt extends Operation {
|
||||||
if (key.length !== 24 && key.length !== 16) {
|
if (key.length !== 24 && key.length !== 16) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).`);
|
||||||
DES uses a key length of 8 bytes (64 bits).`);
|
|
||||||
}
|
}
|
||||||
if (iv.length !== 8 && mode !== "ECB") {
|
if (iv.length !== 8 && mode !== "ECB") {
|
||||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
||||||
|
|
|
@ -22,7 +22,7 @@ class TripleDESEncrypt extends Operation {
|
||||||
|
|
||||||
this.name = "Triple DES Encrypt";
|
this.name = "Triple DES Encrypt";
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description = "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
|
this.description = "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Triple_DES";
|
this.infoURL = "https://wikipedia.org/wiki/Triple_DES";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -72,8 +72,7 @@ class TripleDESEncrypt extends Operation {
|
||||||
if (key.length !== 24 && key.length !== 16) {
|
if (key.length !== 24 && key.length !== 16) {
|
||||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).`);
|
||||||
DES uses a key length of 8 bytes (64 bits).`);
|
|
||||||
}
|
}
|
||||||
if (iv.length !== 8 && mode !== "ECB") {
|
if (iv.length !== 8 && mode !== "ECB") {
|
||||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
throw new OperationError(`Invalid IV length: ${iv.length} bytes
|
||||||
|
|
3
src/web/App.mjs
Executable file → Normal file
3
src/web/App.mjs
Executable file → Normal file
|
@ -60,6 +60,7 @@ class App {
|
||||||
|
|
||||||
this.initialiseSplitter();
|
this.initialiseSplitter();
|
||||||
this.loadLocalStorage();
|
this.loadLocalStorage();
|
||||||
|
this.manager.options.applyPreferredColorScheme();
|
||||||
this.populateOperationsList();
|
this.populateOperationsList();
|
||||||
this.manager.setup();
|
this.manager.setup();
|
||||||
this.manager.output.saveBombe();
|
this.manager.output.saveBombe();
|
||||||
|
@ -536,6 +537,8 @@ class App {
|
||||||
// Read in theme from URI params
|
// Read in theme from URI params
|
||||||
if (this.uriParams.theme) {
|
if (this.uriParams.theme) {
|
||||||
this.manager.options.changeTheme(Utils.escapeHtml(this.uriParams.theme));
|
this.manager.options.changeTheme(Utils.escapeHtml(this.uriParams.theme));
|
||||||
|
} else {
|
||||||
|
this.manager.options.applyPreferredColorScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.dispatchEvent(this.manager.statechange);
|
window.dispatchEvent(this.manager.statechange);
|
||||||
|
|
8
src/web/waiters/OptionsWaiter.mjs
Executable file → Normal file
8
src/web/waiters/OptionsWaiter.mjs
Executable file → Normal file
|
@ -163,6 +163,14 @@ class OptionsWaiter {
|
||||||
themeSelect.selectedIndex = themeSelect.querySelector(`option[value="${theme}"`).index;
|
themeSelect.selectedIndex = themeSelect.querySelector(`option[value="${theme}"`).index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the user's preferred color scheme using the `prefers-color-scheme` media query.
|
||||||
|
*/
|
||||||
|
applyPreferredColorScheme() {
|
||||||
|
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
const theme = prefersDarkScheme ? "dark" : "classic";
|
||||||
|
this.changeTheme(theme);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the console logging level.
|
* Changes the console logging level.
|
||||||
|
|
|
@ -119,7 +119,7 @@ TestRegister.addApiTests([
|
||||||
assert.strictEqual(result[0].module, "Ciphers");
|
assert.strictEqual(result[0].module, "Ciphers");
|
||||||
assert.strictEqual(result[0].inputType, "string");
|
assert.strictEqual(result[0].inputType, "string");
|
||||||
assert.strictEqual(result[0].outputType, "string");
|
assert.strictEqual(result[0].outputType, "string");
|
||||||
assert.strictEqual(result[0].description, "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.");
|
assert.strictEqual(result[0].description, "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.");
|
||||||
assert.strictEqual(result[0].args.length, 5);
|
assert.strictEqual(result[0].args.length, 5);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,8 @@ import "./tests/LZNT1Decompress.mjs";
|
||||||
import "./tests/LZString.mjs";
|
import "./tests/LZString.mjs";
|
||||||
import "./tests/Magic.mjs";
|
import "./tests/Magic.mjs";
|
||||||
import "./tests/Media.mjs";
|
import "./tests/Media.mjs";
|
||||||
|
import "./tests/MIMEDecoding.mjs";
|
||||||
|
import "./tests/Modhex.mjs";
|
||||||
import "./tests/MorseCode.mjs";
|
import "./tests/MorseCode.mjs";
|
||||||
import "./tests/MS.mjs";
|
import "./tests/MS.mjs";
|
||||||
import "./tests/MultipleBombe.mjs";
|
import "./tests/MultipleBombe.mjs";
|
||||||
|
|
|
@ -28,6 +28,28 @@ TestRegister.addTests([
|
||||||
args: ["From Leet Speak"]
|
args: ["From Leet Speak"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Convert to Leet Speak: basic text, keep case",
|
||||||
|
input: "HELLO",
|
||||||
|
expectedOutput: "H3LL0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Convert Leet Speak",
|
||||||
|
args: ["To Leet Speak"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Convert from Leet Speak: basic leet, keep case",
|
||||||
|
input: "H3LL0",
|
||||||
|
expectedOutput: "HeLLo",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Convert Leet Speak",
|
||||||
|
args: ["From Leet Speak"]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -580,8 +580,7 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`,
|
||||||
input: "",
|
input: "",
|
||||||
expectedOutput: `Invalid key length: 0 bytes
|
expectedOutput: `Invalid key length: 0 bytes
|
||||||
|
|
||||||
DES uses a key length of 8 bytes (64 bits).
|
DES uses a key length of 8 bytes (64 bits).`,
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).`,
|
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "DES Encrypt",
|
"op": "DES Encrypt",
|
||||||
|
@ -674,8 +673,7 @@ Triple DES uses a key length of 24 bytes (192 bits).`,
|
||||||
input: "",
|
input: "",
|
||||||
expectedOutput: `Invalid key length: 0 bytes
|
expectedOutput: `Invalid key length: 0 bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).`,
|
||||||
DES uses a key length of 8 bytes (64 bits).`,
|
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Triple DES Encrypt",
|
"op": "Triple DES Encrypt",
|
||||||
|
@ -1300,8 +1298,7 @@ The following algorithms will be used based on the size of the key:
|
||||||
input: "",
|
input: "",
|
||||||
expectedOutput: `Invalid key length: 0 bytes
|
expectedOutput: `Invalid key length: 0 bytes
|
||||||
|
|
||||||
DES uses a key length of 8 bytes (64 bits).
|
DES uses a key length of 8 bytes (64 bits).`,
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).`,
|
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "DES Decrypt",
|
"op": "DES Decrypt",
|
||||||
|
@ -1394,8 +1391,7 @@ Triple DES uses a key length of 24 bytes (192 bits).`,
|
||||||
input: "",
|
input: "",
|
||||||
expectedOutput: `Invalid key length: 0 bytes
|
expectedOutput: `Invalid key length: 0 bytes
|
||||||
|
|
||||||
Triple DES uses a key length of 24 bytes (192 bits).
|
Triple DES uses a key length of 24 bytes (192 bits).`,
|
||||||
DES uses a key length of 8 bytes (64 bits).`,
|
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Triple DES Decrypt",
|
"op": "Triple DES Decrypt",
|
||||||
|
|
|
@ -2,11 +2,392 @@
|
||||||
* From Decimal tests
|
* From Decimal tests
|
||||||
*
|
*
|
||||||
* @author n1073645 [n1073645@gmail.com]
|
* @author n1073645 [n1073645@gmail.com]
|
||||||
|
* @author k3ach [k3ach@proton.me]
|
||||||
* @copyright Crown Copyright 2020
|
* @copyright Crown Copyright 2020
|
||||||
* @licence Apache-2.0
|
* @licence Apache-2.0
|
||||||
*/
|
*/
|
||||||
import TestRegister from "../../lib/TestRegister.mjs";
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
const testCases = [
|
||||||
|
{
|
||||||
|
radix: 2,
|
||||||
|
input: "01",
|
||||||
|
checksum: "1",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 2,
|
||||||
|
input: "001111",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "0",
|
||||||
|
}, {
|
||||||
|
radix: 2,
|
||||||
|
input: "00011101",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "0",
|
||||||
|
}, {
|
||||||
|
radix: 2,
|
||||||
|
input: "0100101101",
|
||||||
|
checksum: "1",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 4,
|
||||||
|
input: "0123",
|
||||||
|
checksum: "1",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 4,
|
||||||
|
input: "130100",
|
||||||
|
checksum: "2",
|
||||||
|
checkdigit: "2",
|
||||||
|
}, {
|
||||||
|
radix: 4,
|
||||||
|
input: "32020313",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "0",
|
||||||
|
}, {
|
||||||
|
radix: 4,
|
||||||
|
input: "302233210112",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "0",
|
||||||
|
}, {
|
||||||
|
radix: 6,
|
||||||
|
input: "012345",
|
||||||
|
checksum: "4",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 6,
|
||||||
|
input: "134255",
|
||||||
|
checksum: "2",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 6,
|
||||||
|
input: "15021453",
|
||||||
|
checksum: "5",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 6,
|
||||||
|
input: "211450230513",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 8,
|
||||||
|
input: "01234567",
|
||||||
|
checksum: "2",
|
||||||
|
checkdigit: "2",
|
||||||
|
}, {
|
||||||
|
radix: 8,
|
||||||
|
input: "340624",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 8,
|
||||||
|
input: "07260247",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "3",
|
||||||
|
}, {
|
||||||
|
radix: 8,
|
||||||
|
input: "026742114675",
|
||||||
|
checksum: "7",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 10,
|
||||||
|
input: "0123456789",
|
||||||
|
checksum: "7",
|
||||||
|
checkdigit: "7",
|
||||||
|
}, {
|
||||||
|
radix: 10,
|
||||||
|
input: "468543",
|
||||||
|
checksum: "7",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 10,
|
||||||
|
input: "59377601",
|
||||||
|
checksum: "5",
|
||||||
|
checkdigit: "6",
|
||||||
|
}, {
|
||||||
|
radix: 10,
|
||||||
|
input: "013909981254",
|
||||||
|
checksum: "1",
|
||||||
|
checkdigit: "3",
|
||||||
|
}, {
|
||||||
|
radix: 12,
|
||||||
|
input: "0123456789ab",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "3",
|
||||||
|
}, {
|
||||||
|
radix: 12,
|
||||||
|
input: "284685",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "6",
|
||||||
|
}, {
|
||||||
|
radix: 12,
|
||||||
|
input: "951a2661",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "8",
|
||||||
|
}, {
|
||||||
|
radix: 12,
|
||||||
|
input: "898202676387",
|
||||||
|
checksum: "b",
|
||||||
|
checkdigit: "9",
|
||||||
|
}, {
|
||||||
|
radix: 14,
|
||||||
|
input: "0123456789abcd",
|
||||||
|
checksum: "a",
|
||||||
|
checkdigit: "a",
|
||||||
|
}, {
|
||||||
|
radix: 14,
|
||||||
|
input: "33db25",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "d",
|
||||||
|
}, {
|
||||||
|
radix: 14,
|
||||||
|
input: "0b4ac128",
|
||||||
|
checksum: "b",
|
||||||
|
checkdigit: "3",
|
||||||
|
}, {
|
||||||
|
radix: 14,
|
||||||
|
input: "3d1c6d16160d",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "c",
|
||||||
|
}, {
|
||||||
|
radix: 16,
|
||||||
|
input: "0123456789abcdef",
|
||||||
|
checksum: "4",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 16,
|
||||||
|
input: "e1fe64",
|
||||||
|
checksum: "b",
|
||||||
|
checkdigit: "6",
|
||||||
|
}, {
|
||||||
|
radix: 16,
|
||||||
|
input: "241a5dcd",
|
||||||
|
checksum: "1",
|
||||||
|
checkdigit: "9",
|
||||||
|
}, {
|
||||||
|
radix: 16,
|
||||||
|
input: "1fea740e0e1f",
|
||||||
|
checksum: "7",
|
||||||
|
checkdigit: "4",
|
||||||
|
}, {
|
||||||
|
radix: 18,
|
||||||
|
input: "0123456789abcdefgh",
|
||||||
|
checksum: "d",
|
||||||
|
checkdigit: "d",
|
||||||
|
}, {
|
||||||
|
radix: 18,
|
||||||
|
input: "995dgf",
|
||||||
|
checksum: "9",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 18,
|
||||||
|
input: "9f80h32h",
|
||||||
|
checksum: "1",
|
||||||
|
checkdigit: "0",
|
||||||
|
}, {
|
||||||
|
radix: 18,
|
||||||
|
input: "5f9428e493g4",
|
||||||
|
checksum: "8",
|
||||||
|
checkdigit: "c",
|
||||||
|
}, {
|
||||||
|
radix: 20,
|
||||||
|
input: "0123456789abcdefghij",
|
||||||
|
checksum: "5",
|
||||||
|
checkdigit: "5",
|
||||||
|
}, {
|
||||||
|
radix: 20,
|
||||||
|
input: "918jci",
|
||||||
|
checksum: "h",
|
||||||
|
checkdigit: "d",
|
||||||
|
}, {
|
||||||
|
radix: 20,
|
||||||
|
input: "jab7j50d",
|
||||||
|
checksum: "g",
|
||||||
|
checkdigit: "j",
|
||||||
|
}, {
|
||||||
|
radix: 20,
|
||||||
|
input: "c56fe85eb6gg",
|
||||||
|
checksum: "g",
|
||||||
|
checkdigit: "5",
|
||||||
|
}, {
|
||||||
|
radix: 22,
|
||||||
|
input: "0123456789abcdefghijkl",
|
||||||
|
checksum: "g",
|
||||||
|
checkdigit: "g",
|
||||||
|
}, {
|
||||||
|
radix: 22,
|
||||||
|
input: "de57le",
|
||||||
|
checksum: "5",
|
||||||
|
checkdigit: "l",
|
||||||
|
}, {
|
||||||
|
radix: 22,
|
||||||
|
input: "e3fg6dfc",
|
||||||
|
checksum: "f",
|
||||||
|
checkdigit: "d",
|
||||||
|
}, {
|
||||||
|
radix: 22,
|
||||||
|
input: "1f8l80ai4kbg",
|
||||||
|
checksum: "l",
|
||||||
|
checkdigit: "f",
|
||||||
|
}, {
|
||||||
|
radix: 24,
|
||||||
|
input: "0123456789abcdefghijklmn",
|
||||||
|
checksum: "6",
|
||||||
|
checkdigit: "6",
|
||||||
|
}, {
|
||||||
|
radix: 24,
|
||||||
|
input: "agne7d",
|
||||||
|
checksum: "4",
|
||||||
|
checkdigit: "f",
|
||||||
|
}, {
|
||||||
|
radix: 24,
|
||||||
|
input: "1l4d9cf4",
|
||||||
|
checksum: "d",
|
||||||
|
checkdigit: "c",
|
||||||
|
}, {
|
||||||
|
radix: 24,
|
||||||
|
input: "blc1j09i3296",
|
||||||
|
checksum: "8",
|
||||||
|
checkdigit: "7",
|
||||||
|
}, {
|
||||||
|
radix: 26,
|
||||||
|
input: "0123456789abcdefghijklmnop",
|
||||||
|
checksum: "j",
|
||||||
|
checkdigit: "j",
|
||||||
|
}, {
|
||||||
|
radix: 26,
|
||||||
|
input: "82n9op",
|
||||||
|
checksum: "i",
|
||||||
|
checkdigit: "2",
|
||||||
|
}, {
|
||||||
|
radix: 26,
|
||||||
|
input: "e9cddn70",
|
||||||
|
checksum: "9",
|
||||||
|
checkdigit: "i",
|
||||||
|
}, {
|
||||||
|
radix: 26,
|
||||||
|
input: "ck0ep419knom",
|
||||||
|
checksum: "p",
|
||||||
|
checkdigit: "g",
|
||||||
|
}, {
|
||||||
|
radix: 28,
|
||||||
|
input: "0123456789abcdefghijklmnopqr",
|
||||||
|
checksum: "7",
|
||||||
|
checkdigit: "7",
|
||||||
|
}, {
|
||||||
|
radix: 28,
|
||||||
|
input: "a6hnoo",
|
||||||
|
checksum: "h",
|
||||||
|
checkdigit: "9",
|
||||||
|
}, {
|
||||||
|
radix: 28,
|
||||||
|
input: "lblc7kh0",
|
||||||
|
checksum: "a",
|
||||||
|
checkdigit: "f",
|
||||||
|
}, {
|
||||||
|
radix: 28,
|
||||||
|
input: "64k5piod3lmf",
|
||||||
|
checksum: "0",
|
||||||
|
checkdigit: "p",
|
||||||
|
}, {
|
||||||
|
radix: 30,
|
||||||
|
input: "0123456789abcdefghijklmnopqrst",
|
||||||
|
checksum: "m",
|
||||||
|
checkdigit: "m",
|
||||||
|
}, {
|
||||||
|
radix: 30,
|
||||||
|
input: "t69j7d",
|
||||||
|
checksum: "9",
|
||||||
|
checkdigit: "s",
|
||||||
|
}, {
|
||||||
|
radix: 30,
|
||||||
|
input: "p54o9ig3",
|
||||||
|
checksum: "a",
|
||||||
|
checkdigit: "o",
|
||||||
|
}, {
|
||||||
|
radix: 30,
|
||||||
|
input: "gc1njrt55030",
|
||||||
|
checksum: "6",
|
||||||
|
checkdigit: "1",
|
||||||
|
}, {
|
||||||
|
radix: 32,
|
||||||
|
input: "0123456789abcdefghijklmnopqrstuv",
|
||||||
|
checksum: "8",
|
||||||
|
checkdigit: "8",
|
||||||
|
}, {
|
||||||
|
radix: 32,
|
||||||
|
input: "rdou19",
|
||||||
|
checksum: "u",
|
||||||
|
checkdigit: "3",
|
||||||
|
}, {
|
||||||
|
radix: 32,
|
||||||
|
input: "ighj0pc7",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "8",
|
||||||
|
}, {
|
||||||
|
radix: 32,
|
||||||
|
input: "op4nn5fvjsrs",
|
||||||
|
checksum: "g",
|
||||||
|
checkdigit: "j",
|
||||||
|
}, {
|
||||||
|
radix: 34,
|
||||||
|
input: "0123456789abcdefghijklmnopqrstuvwx",
|
||||||
|
checksum: "p",
|
||||||
|
checkdigit: "p",
|
||||||
|
}, {
|
||||||
|
radix: 34,
|
||||||
|
input: "nvftj5",
|
||||||
|
checksum: "b",
|
||||||
|
checkdigit: "f",
|
||||||
|
}, {
|
||||||
|
radix: 34,
|
||||||
|
input: "u9v9g162",
|
||||||
|
checksum: "j",
|
||||||
|
checkdigit: "b",
|
||||||
|
}, {
|
||||||
|
radix: 34,
|
||||||
|
input: "o5gqg5d7gjh9",
|
||||||
|
checksum: "5",
|
||||||
|
checkdigit: "q",
|
||||||
|
}, {
|
||||||
|
radix: 36,
|
||||||
|
input: "0123456789abcdefghijklmnopqrstuvwxyz",
|
||||||
|
checksum: "9",
|
||||||
|
checkdigit: "9",
|
||||||
|
}, {
|
||||||
|
radix: 36,
|
||||||
|
input: "29zehu",
|
||||||
|
checksum: "i",
|
||||||
|
checkdigit: "j",
|
||||||
|
}, {
|
||||||
|
radix: 36,
|
||||||
|
input: "1snmikbu",
|
||||||
|
checksum: "s",
|
||||||
|
checkdigit: "v",
|
||||||
|
}, {
|
||||||
|
radix: 36,
|
||||||
|
input: "jpkar545q7gb",
|
||||||
|
checksum: "3",
|
||||||
|
checkdigit: "d",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
testCases.forEach(element => {
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Luhn Checksum Mod " + element.radix + " on " + element.input,
|
||||||
|
input: element.input,
|
||||||
|
expectedOutput: "Checksum: " + element.checksum + "\nCheckdigit: " + element.checkdigit + "\nLuhn Validated String: " + element.input + element.checkdigit,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Luhn Checksum",
|
||||||
|
args: [element.radix]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "Luhn Checksum on standard data",
|
name: "Luhn Checksum on standard data",
|
||||||
|
@ -15,7 +396,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "Luhn Checksum",
|
op: "Luhn Checksum",
|
||||||
args: []
|
args: [10]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -26,7 +407,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "Luhn Checksum",
|
op: "Luhn Checksum",
|
||||||
args: []
|
args: [10]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -37,18 +418,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "Luhn Checksum",
|
op: "Luhn Checksum",
|
||||||
args: []
|
args: [10]
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Luhn Checksum on invalid data",
|
|
||||||
input: "35641709b012469",
|
|
||||||
expectedOutput: "Character: b is not a digit.",
|
|
||||||
recipeConfig: [
|
|
||||||
{
|
|
||||||
op: "Luhn Checksum",
|
|
||||||
args: []
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -59,8 +429,8 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "Luhn Checksum",
|
op: "Luhn Checksum",
|
||||||
args: []
|
args: [10]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
89
tests/operations/tests/MIMEDecoding.mjs
Normal file
89
tests/operations/tests/MIMEDecoding.mjs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
* MIME Header Decoding tests
|
||||||
|
*
|
||||||
|
* @author mshwed [m@ttshwed.com]
|
||||||
|
* @copyright Crown Copyright 2019
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Encoded comments",
|
||||||
|
input: "(=?ISO-8859-1?Q?a?=)",
|
||||||
|
expectedOutput: "(a)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Encoded adjacent comments whitespace",
|
||||||
|
input: "(=?ISO-8859-1?Q?a?= b)",
|
||||||
|
expectedOutput: "(a b)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Encoded adjacent single whitespace ignored",
|
||||||
|
input: "(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)",
|
||||||
|
expectedOutput: "(ab)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Encoded adjacent double whitespace ignored",
|
||||||
|
input: "(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)",
|
||||||
|
expectedOutput: "(ab)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Encoded adjacent CRLF whitespace ignored",
|
||||||
|
input: "(=?ISO-8859-1?Q?a?=\r\n =?ISO-8859-1?Q?b?=)",
|
||||||
|
expectedOutput: "(ab)",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UTF-8 Encodings Multiple Headers",
|
||||||
|
input: "=?utf-8?q?=C3=89ric?= <eric@example.org>, =?utf-8?q?Ana=C3=AFs?= <anais@example.org>",
|
||||||
|
expectedOutput: "Éric <eric@example.org>, Anaïs <anais@example.org>",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ISO Decoding",
|
||||||
|
input: "From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>\nTo: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>\nCC: =?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>\nSubject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\n=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=",
|
||||||
|
expectedOutput: "From: Keith Moore <moore@cs.utk.edu>\nTo: Keld Jørn Simonsen <keld@dkuug.dk>\nCC: André Pirard <PIRARD@vm1.ulg.ac.be>\nSubject: If you can read this you understand the example.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "MIME Decoding",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
150
tests/operations/tests/Modhex.mjs
Normal file
150
tests/operations/tests/Modhex.mjs
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
* Modhex operation tests.
|
||||||
|
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||||
|
* @copyright Crown Copyright 2024
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "ASCII to Modhex stream",
|
||||||
|
input: "aberystwyth",
|
||||||
|
expectedOutput: "hbhdhgidikieifiiikifhj",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Modhex",
|
||||||
|
"args": [
|
||||||
|
"None",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ASCII to Modhex with colon deliminator",
|
||||||
|
input: "aberystwyth",
|
||||||
|
expectedOutput: "hb:hd:hg:id:ik:ie:if:ii:ik:if:hj",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Modhex",
|
||||||
|
"args": [
|
||||||
|
"Colon",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Modhex stream to UTF-8",
|
||||||
|
input: "uhkgkbuhkgkbugltlkugltkc",
|
||||||
|
expectedOutput: "救救孩子",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Modhex",
|
||||||
|
"args": [
|
||||||
|
"Auto"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mixed case Modhex stream to UTF-8",
|
||||||
|
input: "uhKGkbUHkgkBUGltlkugltkc",
|
||||||
|
expectedOutput: "救救孩子",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Modhex",
|
||||||
|
"args": [
|
||||||
|
"Auto"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mutiline Modhex with comma to ASCII (Auto Mode)",
|
||||||
|
input: "fk,dc,ie,hb,ii,dc,ht,ik,ie,hg,hr,hh,dc,ie,hk,\n\
|
||||||
|
if,if,hk,hu,hi,dc,hk,hu,dc,if,hj,hg,dc,he,id,\n\
|
||||||
|
hv,if,he,hj,dc,hv,hh,dc,if,hj,hg,dc,if,hj,hk,\n\
|
||||||
|
ie,dc,hh,hk,hi,dc,if,id,hg,hg,dr,dc,ie,if,hb,\n\
|
||||||
|
id,ih,hk,hu,hi,dc,if,hv,dc,hf,hg,hb,if,hj,dr,\n\
|
||||||
|
dc,hl,ig,ie,if,dc,hd,hg,he,hb,ig,ie,hg,dc,fk,\n\
|
||||||
|
dc,he,hv,ig,hr,hf,hu,di,if,dc,ht,hb,hn,hg,dc,\n\
|
||||||
|
ig,ic,dc,ht,ik,dc,ht,hk,hu,hf,dc,ii,hj,hk,he,\n\
|
||||||
|
hj,dc,hv,hh,dc,if,hj,hg,dc,hh,hk,hi,ie,dc,fk,\n\
|
||||||
|
dc,ii,hv,ig,hr,hf,dc,he,hj,hv,hv,ie,hg,du",
|
||||||
|
expectedOutput: "I saw myself sitting in the crotch of the this fig tree, starving to death, just because I couldn't make up my mind which of the figs I would choose.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Modhex",
|
||||||
|
"args": [
|
||||||
|
"Auto"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mutiline Modhex with percent to ASCII (Percent Mode)",
|
||||||
|
input: "fk%dc%ie%hb%ii%dc%ht%ik%ie%hg%hr%hh%dc%ie%hk%\n\
|
||||||
|
if%if%hk%hu%hi%dc%hk%hu%dc%if%hj%hg%dc%he%id%\n\
|
||||||
|
hv%if%he%hj%dc%hv%hh%dc%if%hj%hg%dc%if%hj%hk%\n\
|
||||||
|
ie%dc%hh%hk%hi%dc%if%id%hg%hg%dr%dc%ie%if%hb%\n\
|
||||||
|
id%ih%hk%hu%hi%dc%if%hv%dc%hf%hg%hb%if%hj%dr%\n\
|
||||||
|
dc%hl%ig%ie%if%dc%hd%hg%he%hb%ig%ie%hg%dc%fk%\n\
|
||||||
|
dc%he%hv%ig%hr%hf%hu%di%if%dc%ht%hb%hn%hg%dc%\n\
|
||||||
|
ig%ic%dc%ht%ik%dc%ht%hk%hu%hf%dc%ii%hj%hk%he%\n\
|
||||||
|
hj%dc%hv%hh%dc%if%hj%hg%dc%hh%hk%hi%ie%dc%fk%\n\
|
||||||
|
dc%ii%hv%ig%hr%hf%dc%he%hj%hv%hv%ie%hg%du",
|
||||||
|
expectedOutput: "I saw myself sitting in the crotch of the this fig tree, starving to death, just because I couldn't make up my mind which of the figs I would choose.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Modhex",
|
||||||
|
"args": [
|
||||||
|
"Percent"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mutiline Modhex with semicolon to ASCII (Semi-colon Mode)",
|
||||||
|
input: "fk;dc;ie;hb;ii;dc;ht;ik;ie;hg;hr;hh;dc;ie;hk;\n\
|
||||||
|
if;if;hk;hu;hi;dc;hk;hu;dc;if;hj;hg;dc;he;id;\n\
|
||||||
|
hv;if;he;hj;dc;hv;hh;dc;if;hj;hg;dc;if;hj;hk;\n\
|
||||||
|
ie;dc;hh;hk;hi;dc;if;id;hg;hg;dr;dc;ie;if;hb;\n\
|
||||||
|
id;ih;hk;hu;hi;dc;if;hv;dc;hf;hg;hb;if;hj;dr;\n\
|
||||||
|
dc;hl;ig;ie;if;dc;hd;hg;he;hb;ig;ie;hg;dc;fk;\n\
|
||||||
|
dc;he;hv;ig;hr;hf;hu;di;if;dc;ht;hb;hn;hg;dc;\n\
|
||||||
|
ig;ic;dc;ht;ik;dc;ht;hk;hu;hf;dc;ii;hj;hk;he;\n\
|
||||||
|
hj;dc;hv;hh;dc;if;hj;hg;dc;hh;hk;hi;ie;dc;fk;\n\
|
||||||
|
dc;ii;hv;ig;hr;hf;dc;he;hj;hv;hv;ie;hg;du",
|
||||||
|
expectedOutput: "I saw myself sitting in the crotch of the this fig tree, starving to death, just because I couldn't make up my mind which of the figs I would choose.",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Modhex",
|
||||||
|
"args": [
|
||||||
|
"Semi-colon"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ASCII to Modhex with comma and line breaks",
|
||||||
|
input: "aberystwyth",
|
||||||
|
expectedOutput: "hb,hd,hg,id,\nik,ie,if,ii,\nik,if,hj",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "To Modhex",
|
||||||
|
"args": [
|
||||||
|
"Comma",
|
||||||
|
4
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
|
@ -135,10 +135,21 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: no shift amount",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [true, true, true, 0]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ROT13: normal",
|
name: "ROT13: normal",
|
||||||
input: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
expectedOutput: "Gur Dhvpx Oebja Sbk Whzcrq Bire Gur Ynml Qbt.",
|
expectedOutput: "Gur Dhvpx Oebja Sbk Whzcrq Bire Gur Ynml Qbt. 3456789012",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "ROT13",
|
op: "ROT13",
|
||||||
|
@ -146,10 +157,21 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: negative shift amount",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "Gur Dhvpx Oebja Sbk Whzcrq Bire Gur Ynml Qbt. 7890123456",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [true, true, true, -13]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ROT13: full loop",
|
name: "ROT13: full loop",
|
||||||
input: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 6789012345",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "ROT13",
|
op: "ROT13",
|
||||||
|
@ -157,10 +179,21 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: full loop (negative shift amount)",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 4567890123",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [true, true, true, -26]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ROT13: lowercase only",
|
name: "ROT13: lowercase only",
|
||||||
input: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
expectedOutput: "Tur Qhvpx Bebja Fbk Jhzcrq Oire Tur Lnml Dbt.",
|
expectedOutput: "Tur Qhvpx Bebja Fbk Jhzcrq Oire Tur Lnml Dbt. 0123456789",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "ROT13",
|
op: "ROT13",
|
||||||
|
@ -170,8 +203,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ROT13: uppercase only",
|
name: "ROT13: uppercase only",
|
||||||
input: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
expectedOutput: "Ghe Duick Orown Sox Wumped Bver Ghe Yazy Qog.",
|
expectedOutput: "Ghe Duick Orown Sox Wumped Bver Ghe Yazy Qog. 0123456789",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
op: "ROT13",
|
op: "ROT13",
|
||||||
|
@ -179,6 +212,50 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: numbers only",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 5678901234",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [false, false, true, 5]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: numbers only (negative shift amount)",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 5678901234",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [false, false, true, 5]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: numbers only loop",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [false, false, true, 10]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ROT13: numbers only loop (negative shift amount)",
|
||||||
|
input: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog. 0123456789",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "ROT13",
|
||||||
|
args: [false, false, true, -10]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "ROT47: nothing",
|
name: "ROT47: nothing",
|
||||||
input: "",
|
input: "",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue