Default user text to UTF-8

This commit is contained in:
C85297 2026-07-06 23:05:18 +01:00
parent 002ed911b1
commit 1ed998b9dc
No known key found for this signature in database
27 changed files with 198 additions and 52 deletions

View File

@ -7,7 +7,7 @@
import Dish from "./Dish.mjs";
import Recipe from "./Recipe.mjs";
import log from "loglevel";
import { isWorkerEnvironment } from "./Utils.mjs";
import Utils, { isWorkerEnvironment } from "./Utils.mjs";
/**
* The main controller for CyberChef.
@ -48,7 +48,13 @@ class Chef {
if (containsFc && isWorkerEnvironment()) self.setOption("attemptHighlight", false);
// Load data
const type = input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING;
let type = Dish.STRING;
if (input instanceof ArrayBuffer) {
type = Dish.ARRAY_BUFFER;
} else if (typeof input === "string" && recipe.firstActiveInputType() === "ArrayBuffer") {
input = Utils.strToUtf8ArrayBuffer(input);
type = Dish.ARRAY_BUFFER;
}
this.dish.set(input, type);
try {

View File

@ -169,6 +169,17 @@ class Recipe {
}
/**
* Returns the input type for the first active operation in the recipe.
*
* @returns {string|null}
*/
firstActiveInputType() {
const firstActiveOp = this.opList.find(op => !op.disabled);
return firstActiveOp ? OperationConfig[firstActiveOp.name]?.inputType || null : null;
}
/**
* Executes each operation in the recipe over the given Dish.
*

View File

@ -52,9 +52,9 @@ class BLAKE3 extends Operation {
const key = args[1];
const size = args[0];
const opts = { dkLen: size };
const inputBytes = new Uint8Array(Utils.strToArrayBuffer(input));
const inputBytes = new Uint8Array(Utils.strToUtf8ArrayBuffer(input));
if (key !== "") {
const keyBytes = new Uint8Array(Utils.strToArrayBuffer(key));
const keyBytes = new Uint8Array(Utils.strToUtf8ArrayBuffer(key));
if (keyBytes.length !== 32) {
throw new OperationError("The key must be exactly 32 bytes long");
}

View File

@ -83,6 +83,13 @@ class NodeRecipe {
this.opList = recipeConfig.map((ing) => this._validateIngredient(ing));
}
firstActiveInputType() {
const first = this.opList[0];
if (!first) return null;
const op = Object.prototype.hasOwnProperty.call(first, "op") ? first.op : first;
return op.inputType || null;
}
/**
* Run the dish through each operation, one at a time.
* @param {NodeDish} dish

View File

@ -10,6 +10,8 @@
import NodeDish from "./NodeDish.mjs";
import NodeRecipe from "./NodeRecipe.mjs";
import Dish from "../core/Dish.mjs";
import Utils from "../core/Utils.mjs";
import OperationConfig from "../core/config/OperationConfig.json" with { type: "json" };
import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs";
import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs";
@ -118,7 +120,9 @@ function ensureIsDish(input) {
* @param args - operation args
*/
function prepareOp(opInstance, input, args) {
const dish = ensureIsDish(input);
const dish = typeof input === "string" && opInstance.inputType === "ArrayBuffer" ?
new NodeDish(Utils.strToUtf8ArrayBuffer(input), Dish.ARRAY_BUFFER) :
ensureIsDish(input);
// Transform object-style args to original args array
const transformedArgs = transformArgs(opInstance.args, args);
const transformedInput = dish.get(opInstance.inputType);
@ -242,6 +246,7 @@ export function _wrap(OpClass) {
// used in chef.help
wrapped.opName = OpClass.name;
wrapped.inputType = opInstance.inputType;
wrapped.args = createArgInfo(opInstance);
// Used in NodeRecipe to check for flowControl ops
wrapped.flowControl = isFlowControl;
@ -329,7 +334,9 @@ export function help(input) {
*/
export async function bake(input, recipeConfig) {
const recipe = new NodeRecipe(recipeConfig);
const dish = ensureIsDish(input);
const dish = typeof input === "string" && recipe.firstActiveInputType() === "ArrayBuffer" ?
new NodeDish(Utils.strToUtf8ArrayBuffer(input), Dish.ARRAY_BUFFER) :
ensureIsDish(input);
return await recipe.execute(dish);
}

View File

@ -537,12 +537,17 @@ class App {
if (this.uriParams.input) {
try {
let inputVal;
const inputChrEnc = this.manager.input.getChrEnc();
const inputData = fromBase64(this.uriParams.input, null, "byteArray");
if (inputChrEnc > 0) {
inputVal = cptable.utils.decode(inputChrEnc, inputData);
if (this.uriParams.ienc) {
const inputChrEnc = this.manager.input.getChrEnc();
if (inputChrEnc > 0) {
inputVal = cptable.utils.decode(inputChrEnc, inputData);
} else {
inputVal = Utils.byteArrayToChars(inputData);
}
} else {
inputVal = Utils.byteArrayToChars(inputData);
this.manager.input.chrEncChange(0, true, true);
}
this.setInput(inputVal);
} catch (err) {}

View File

@ -656,10 +656,9 @@ class InputWaiter {
this.setInput(inputVal, silent);
// Set URL to current input
if (inputVal.length >= 0 && inputVal.length <= 51200) {
const inputStr = toBase64(inputVal, "A-Za-z0-9+/");
this.app.updateURL(true, inputStr);
}
const inputStr = inputData.buffer.byteLength < 51200 ? toBase64(inputData.buffer, "A-Za-z0-9+/") : "";
const includeInput = inputStr.length > 0 && inputData.buffer.byteLength < 51200;
this.app.updateURL(includeInput, inputStr);
}.bind(this));
}

View File

@ -756,7 +756,7 @@ self.addInput = function(
file: null,
status: "pending",
progress: 0,
encoding: 0,
encoding: type === "userinput" ? 65001 : 0,
eolSequence: "\u000a"
};

View File

@ -125,7 +125,7 @@ module.exports = {
browser.waitForElementVisible("#input-text .cm-status-bar .stats-lines-value")
.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("1");
browser.waitForElementVisible("#input-text .cm-status-bar .chr-enc-value")
.expect.element("#input-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes");
.expect.element("#input-text .cm-status-bar .chr-enc-value").text.to.equal("UTF-8");
browser.waitForElementVisible("#input-text .cm-status-bar .eol-value")
.expect.element("#input-text .cm-status-bar .eol-value").text.to.equal("LF");
@ -149,7 +149,7 @@ module.exports = {
browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("301");
browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("3");
browser.expect.element("#input-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes");
browser.expect.element("#input-text .cm-status-bar .chr-enc-value").text.to.equal("UTF-8");
browser.expect.element("#input-text .cm-status-bar .eol-value").text.to.equal("LF");
browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("0");
@ -167,6 +167,22 @@ module.exports = {
browser.expect.element("#output-text .cm-status-bar .eol-value").text.to.equal("LF");
},
"Manual input To Hex uses selected encoding": browser => {
utils.loadRecipe(browser, "To Hex", "á", ["Space", 0]);
utils.bake(browser);
utils.expectOutput(browser, "c3 a1", true);
utils.setChrEnc(browser, "input", "Raw Bytes");
browser.execute(text => {
window.app.setInput(text);
}, ["á"]);
utils.expectInput(browser, "á");
utils.bake(browser);
utils.expectOutput(browser, "e1", true);
utils.setChrEnc(browser, "input", "UTF-8");
},
"Autobaking the latest input": browser => {
// Use the sleep recipe to simulate a long running task
utils.loadRecipe(browser, "Sleep", "input", [2000]);
@ -433,7 +449,7 @@ module.exports = {
browser
.click("#btn-new-tab")
.waitForElementVisible("#input-tabs li:nth-of-type(2).active-input-tab");
browser.expect.element("#input-text .chr-enc-value").text.that.equals("Raw Bytes");
browser.expect.element("#input-text .chr-enc-value").text.that.equals("UTF-8");
browser.expect.element("#output-text .chr-enc-value").text.that.equals("Raw Bytes");
utils.setChrEnc(browser, "input", "UTF-7");

View File

@ -980,6 +980,18 @@ smothering ampersand abreast`;
assert.strictEqual(result.toString(), "73:6f:6d:65:20:69:6e:70:75:74");
}),
it("toHex: Latin-1 text input uses UTF-8", () => {
const result = toHex("á", {
delimiter: "Space",
});
assert.strictEqual(result.toString(), "c3 a1");
}),
it("bake: byte-first Latin-1 text input uses UTF-8", async () => {
const result = await chef.bake("á", "to hex");
assert.strictEqual(result.toString(), "c3 a1");
}),
it("To Kebab case", () => {
assert.strictEqual(chef.toKebabCase("Elfin Gold").toString(), "elfin-gold");
}),

View File

@ -8,6 +8,8 @@
import TestRegister from "../../lib/TestRegister.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "Avro to JSON: no input (force JSON true)",
@ -33,12 +35,12 @@ TestRegister.addTests([
},
{
name: "Avro to JSON: small (force JSON true)",
input: "\x4f\x62\x6a\x01\x04\x16\x61\x76\x72\x6f\x2e\x73\x63\x68\x65\x6d\x61\x96\x01\x7b\x22\x74\x79\x70\x65\x22\x3a\x22\x72\x65" +
input: rawStringToArrayBuffer("\x4f\x62\x6a\x01\x04\x16\x61\x76\x72\x6f\x2e\x73\x63\x68\x65\x6d\x61\x96\x01\x7b\x22\x74\x79\x70\x65\x22\x3a\x22\x72\x65" +
"\x63\x6f\x72\x64\x22\x2c\x22\x6e\x61\x6d\x65\x22\x3a\x22\x73\x6d\x61\x6c\x6c\x22\x2c\x22\x66\x69\x65\x6c\x64\x73\x22\x3a" +
"\x5b\x7b\x22\x6e\x61\x6d\x65\x22\x3a\x22\x6e\x61\x6d\x65\x22\x2c\x22\x74\x79\x70\x65\x22\x3a\x22\x73\x74\x72\x69\x6e\x67" +
"\x22\x7d\x5d\x7d\x14\x61\x76\x72\x6f\x2e\x63\x6f\x64\x65\x63\x08\x6e\x75\x6c\x6c\x00\x4e\x02\x47\x63\x2e\x37\x02\xe5\xb7" +
"\x5c\xda\xb9\xa6\x2f\x15\x41\x02\x0e\x0c\x6d\x79\x6e\x61\x6d\x65\x4e\x02\x47\x63\x2e\x37\x02\xe5\xb7\x5c\xda\xb9\xa6\x2f" +
"\x15\x41",
"\x15\x41"),
expectedOutput: "{\n \"name\": \"myname\"\n}",
recipeConfig: [
{
@ -49,12 +51,12 @@ TestRegister.addTests([
},
{
name: "Avro to JSON: small (force JSON false)",
input: "\x4f\x62\x6a\x01\x04\x16\x61\x76\x72\x6f\x2e\x73\x63\x68\x65\x6d\x61\x96\x01\x7b\x22\x74\x79\x70\x65\x22\x3a\x22\x72\x65" +
input: rawStringToArrayBuffer("\x4f\x62\x6a\x01\x04\x16\x61\x76\x72\x6f\x2e\x73\x63\x68\x65\x6d\x61\x96\x01\x7b\x22\x74\x79\x70\x65\x22\x3a\x22\x72\x65" +
"\x63\x6f\x72\x64\x22\x2c\x22\x6e\x61\x6d\x65\x22\x3a\x22\x73\x6d\x61\x6c\x6c\x22\x2c\x22\x66\x69\x65\x6c\x64\x73\x22\x3a" +
"\x5b\x7b\x22\x6e\x61\x6d\x65\x22\x3a\x22\x6e\x61\x6d\x65\x22\x2c\x22\x74\x79\x70\x65\x22\x3a\x22\x73\x74\x72\x69\x6e\x67" +
"\x22\x7d\x5d\x7d\x14\x61\x76\x72\x6f\x2e\x63\x6f\x64\x65\x63\x08\x6e\x75\x6c\x6c\x00\x4e\x02\x47\x63\x2e\x37\x02\xe5\xb7" +
"\x5c\xda\xb9\xa6\x2f\x15\x41\x02\x0e\x0c\x6d\x79\x6e\x61\x6d\x65\x4e\x02\x47\x63\x2e\x37\x02\xe5\xb7\x5c\xda\xb9\xa6\x2f" +
"\x15\x41",
"\x15\x41"),
expectedOutput: "{\"name\":\"myname\"}\n",
recipeConfig: [
{

View File

@ -25,6 +25,15 @@ TestRegister.addTests([
"args": [16, ""] }
]
},
{
name: "BLAKE3: 16 - Latin-1 text input uses UTF-8",
input: "á",
expectedOutput: "bb9c95e4b863990afb5259512240f785",
recipeConfig: [
{ "op": "BLAKE3",
"args": [16, ""] }
]
},
{
name: "BLAKE3: 32 - Hello world",
input: "Hello world",

View File

@ -36,6 +36,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
const ALL_BYTES_EXTENDED_OUT = "000G40O40K30E209185GO38E1S8124GJ2GAHC5OO34D1M70T3OFI08924CI2A9H750KIKAPC5KN2UC1H68PJ8D9M6SS3IEHR7GUJSFQ085146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB9DLONAUBTG62OJ3CHIMCPR8D5L6MR3DDPNN0SBIEDQ7ATJNF1SNKURSFLV7V041GA1O91C6GU48J2KBHI6OT3SGI699754LIQBPH6CQJEE9R7KVK2GQ58T4KMJAFA59LALQPBDELUOB3CLJMIQRDDTON6TBNF5TNQVS1GE2OF2CBHM7P34SLIUCPN7CVK6HQB9T9LEMQVCDJMMRRJETTNV0S7HE7P75SRJUHQFATFMERRNFU3OV5SVKUNRFFU7PVBTVPVFUVS======";
const ALL_BYTES_STANDARD_OUT = "AAAQEAYEAUDAOCAJBIFQYDIOB4IBCEQTCQKRMFYYDENBWHA5DYPSAIJCEMSCKJRHFAUSUKZMFUXC6MBRGIZTINJWG44DSOR3HQ6T4P2AIFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLJNVYXK6L5QGCYTDMRSWMZ3INFVGW3DNNZXXA4LSON2HK5TXPB4XU634PV7H7AEBQKBYJBMGQ6EITCULRSGY5D4QSGJJHFEVS2LZRGM2TOOJ3HU7UCQ2FI5EUWTKPKFJVKV2ZLNOV6YLDMVTWS23NN5YXG5LXPF5X274BQOCYPCMLRWHZDE4VS6MZXHM7UGR2LJ5JVOW27MNTWW33TO55X7A4HROHZHF43T6R2PK5PWO33XP6DY7F47U6X3PP6HZ7L57Z7P674======";
@ -130,7 +132,7 @@ TestRegister.addTests([
},
{
name: "To Base32 Hex Standard: All Bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: ALL_BYTES_STANDARD_OUT,
recipeConfig: [
{
@ -141,7 +143,7 @@ TestRegister.addTests([
},
{
name: "To Base32 Hex Extended: All Bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: ALL_BYTES_EXTENDED_OUT,
recipeConfig: [
{

View File

@ -27,6 +27,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "To Base64: nothing",
@ -63,7 +65,7 @@ TestRegister.addTests([
},
{
name: "To Base64: All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==",
recipeConfig: [
{
@ -118,7 +120,7 @@ TestRegister.addTests([
},
{
name: "Show Base64 offsets: escapes static output",
input: "\x00\x10\x83\x10\x51\x87",
input: rawStringToArrayBuffer("\x00\x10\x83\x10\x51\x87"),
expectedOutput: "&lt;script&gt;\n&lt;AQmsBRk66\n&lt;ia1AEIM6",
recipeConfig: [
{

View File

@ -7,6 +7,8 @@
*/
import TestRegister from "../../lib/TestRegister.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
// Example from Wikipedia
const wpExample = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
// Escape newline, quote & backslash
@ -51,7 +53,7 @@ TestRegister.addTests([
},
{
name: "To Base85",
input: allZeroExample,
input: rawStringToArrayBuffer(allZeroExample),
expectedOutput: allZeroOutput,
recipeConfig: [
{ "op": "To Base85",

View File

@ -26,6 +26,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "To Octal: nothing",
@ -106,7 +108,7 @@ TestRegister.addTests([
},
{
name: "To Hex: All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff",
recipeConfig: [
{
@ -126,6 +128,28 @@ TestRegister.addTests([
},
]
},
{
name: "To Hex: Latin-1 text input uses UTF-8",
input: "á",
expectedOutput: "c3 a1",
recipeConfig: [
{
op: "To Hex",
args: ["Space", 0]
},
]
},
{
name: "To Hex: mixed Latin-1 and Arabic text input uses UTF-8",
input: "اá",
expectedOutput: "d8 a7 c3 a1",
recipeConfig: [
{
op: "To Hex",
args: ["Space", 0]
},
]
},
{
name: "From Hex: nothing",
input: "",
@ -172,7 +196,7 @@ TestRegister.addTests([
},
{
name: "To Charcode: All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff",
recipeConfig: [
{

View File

@ -26,6 +26,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "CRC-16: nothing",
@ -62,7 +64,7 @@ TestRegister.addTests([
},
{
name: "CRC-16: all bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "bad3",
recipeConfig: [
{
@ -106,7 +108,7 @@ TestRegister.addTests([
},
{
name: "CRC-32: all bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "29058c73",
recipeConfig: [
{

View File

@ -8,6 +8,8 @@
*/
import TestRegister from "../../lib/TestRegister.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "CipherSaber2 Encrypt",
@ -23,9 +25,9 @@ TestRegister.addTests([
{
// input taken from https://ciphersaber.gurus.org/
name: "CipherSaber2 Decrypt",
input: "\x6f\x6d\x0b\xab\xf3\xaa\x67\x19\x03\x15\x30\xed\xb6\x77" +
input: rawStringToArrayBuffer("\x6f\x6d\x0b\xab\xf3\xaa\x67\x19\x03\x15\x30\xed\xb6\x77" +
"\xca\x74\xe0\x08\x9d\xd0\xe7\xb8\x85\x43\x56\xbb\x14\x48\xe3" +
"\x7c\xdb\xef\xe7\xf3\xa8\x4f\x4f\x5f\xb3\xfd",
"\x7c\xdb\xef\xe7\xf3\xa8\x4f\x4f\x5f\xb3\xfd"),
expectedOutput: "This is a test of CipherSaber.",
recipeConfig: [
{

View File

@ -27,6 +27,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "Comment: nothing",
@ -60,7 +62,7 @@ TestRegister.addTests([
},
{
name: "Label, Comment: Complex content",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: ALL_BYTES,
recipeConfig: [
{

View File

@ -8,6 +8,8 @@
import TestRegister from "../../lib/TestRegister.mjs";
import {ALL_BYTES, ASCII_TEXT, UTF8_TEXT} from "../../samples/Ciphers.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
const SOME_HEX_BYTES = "cdb23f958e018418621d9e489b7bba0f0c481f604eba2eb1ea35e38f99490cc0";
const SOME_BASE64_BYTES = "zbI/lY4BhBhiHZ5Im3u6DwxIH2BOui6x6jXjj5lJDMA=";
@ -481,7 +483,7 @@ TestRegister.addTests([
},
{
name: "ECDSA Sign/Verify: P-256 with SHA256 bytes raw",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "Verified OK",
recipeConfig: [
{

View File

@ -41,6 +41,28 @@ TestRegister.addTests([
}
]
},
{
name: "MD5: Latin-1 text input uses UTF-8",
input: "á",
expectedOutput: "36b7148acc1b607c473a15a47fa17706",
recipeConfig: [
{
"op": "MD5",
"args": []
}
]
},
{
name: "MD5: Arabic text input remains UTF-8",
input: "ا",
expectedOutput: "c86823319368792bf39bd59b9328d292",
recipeConfig: [
{
"op": "MD5",
"args": []
}
]
},
{
name: "MD6",
input: "Hello, World!",

View File

@ -27,6 +27,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "Hexdump: nothing",
@ -75,7 +77,7 @@ TestRegister.addTests([
},
{
name: "Hexdump: All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: ALL_BYTES,
recipeConfig: [
{
@ -102,7 +104,7 @@ TestRegister.addTests([
},
{
name: "To Hexdump: All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: `00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./|

View File

@ -9,6 +9,8 @@
import TestRegister from "../../lib/TestRegister.mjs";
import { JPG_RAW } from "../../samples/Images.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "Magic: nothing",
@ -34,7 +36,7 @@ TestRegister.addTests([
},
{
name: "Magic: jpeg render",
input: JPG_RAW,
input: rawStringToArrayBuffer(JPG_RAW),
expectedMatch: /Render_Image\('Raw'\)/,
recipeConfig: [
{
@ -45,7 +47,7 @@ TestRegister.addTests([
},
{
name: "Magic: mojibake",
input: "\xd0\x91\xd1\x8b\xd1\0\xd1\x82\xd1\x80\xd0\xb0\xd1\0\x20\xd0\xba\xd0\xbe\xd1\x80\xd0\xb8\xd1\x87\xd0\xbd\xd0\xb5\xd0\xb2\xd0\xb0\xd1\0\x20\xd0\xbb\xd0\xb8\xd1\0\xd0\xb0\x20\xd0\xbf\xd1\x80\xd1\x8b\xd0\xb3\xd0\xb0\xd0\xb5\xd1\x82\x20\xd1\x87\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb7\x20\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb2\xd1\x83\xd1\x8e\x20\xd1\0\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd1\x83\x2e",
input: rawStringToArrayBuffer("\xd0\x91\xd1\x8b\xd1\0\xd1\x82\xd1\x80\xd0\xb0\xd1\0\x20\xd0\xba\xd0\xbe\xd1\x80\xd0\xb8\xd1\x87\xd0\xbd\xd0\xb5\xd0\xb2\xd0\xb0\xd1\0\x20\xd0\xbb\xd0\xb8\xd1\0\xd0\xb0\x20\xd0\xbf\xd1\x80\xd1\x8b\xd0\xb3\xd0\xb0\xd0\xb5\xd1\x82\x20\xd1\x87\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb7\x20\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb2\xd1\x83\xd1\x8e\x20\xd1\0\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd1\x83\x2e"),
expectedMatch: /Быртрар коричневар лира прыгает через ленивую робаку./,
recipeConfig: [
{
@ -122,7 +124,7 @@ TestRegister.addTests([
},
{
name: "Magic: Raw Inflate",
input: "\x4d\x52\xb1\x6e\xdc\x30\x0c\xdd\xf3\x15\x44\x80\x6e\xae\x91\x02\x4d\x80\x8e\x4d\x9a\x21\x53\x8b\xa6\x43\x56\x5a\xe2\x9d\x84\x93\x25\x43\x94\xed\xf8\xef\xf3\xe8\x6b\x0e\xb7\x1c\xce\xd4\x7b\x8f\x8f\x7c\x7c\xda\x06\xa9\x4f\x41\x0e\x14\x95\x98\x34\x8e\x53\x92\x8e\x62\x6e\x73\x6c\x71\x11\x5a\x65\x20\x9e\x26\x3a\x94\x4a\x8e\x6b\xdd\x62\x3e\x52\x99\x1b\x71\x4a\x34\x72\xce\x52\xa9\x1c\xe8\xd6\x99\xd0\x2d\x95\x49\x2a\xb7\x58\xb2\xd2\x1a\x5b\x88\x19\xa2\x26\x31\xd4\xb2\xaa\xd4\x9e\xfe\x05\x51\xb9\x86\xc5\xec\xd2\xec\xe5\x7f\x6b\x92\xec\x8a\xb7\x1e\x29\x9e\x84\xde\x7e\xff\x25\x34\x7e\x64\x95\x87\xef\x1d\x8d\xa5\x0a\xb9\x62\xc0\x77\x43\xd6\x6d\x32\x91\x33\xf6\xe7\xf3\x6b\x47\xbf\x9e\x5f\x89\xb3\xa7\xc7\x54\xd6\x43\xd4\xd0\x91\xab\x82\x4e\x10\x1c\x62\xe6\xba\xed\xaf\x41\xde\xfd\x3c\x4e\x8a\x57\x88\x55\x51\x35\x15\x7b\xf1\x72\x5d\xc1\x60\x9e\x1b\x03\xc6\xc9\xcd\xe9\xac\x13\x58\x31\xc3\x8e\x76\x41\xdc\x49\xe7\x11\x42\x2f\x7f\x96\x87\xbd\xf6\xd6\xdf\xdf\xfd\xa0\x89\xab\x02\x0c\x66\xe0\x7c\x34\x1a\xfe\x54\x76\x0d\xeb\xfa\x1c\x11\x2c\x23\x8c\xb3\x0b\xfb\x64\xfd\xcd\x0d\xb6\x43\xad\x94\x64\x69\x78\xd1\x78\xcc\xe2\x51\x00\x85\x07\x2c\x67\x28\x2d\x50\x13\x17\x72\x84\xa3\x9d\x9d\x4b\xfe\x7a\x5d\xe1\xb4\x69\x53\xe3\x20\x9c\x38\x99\x69\xd9\x87\xc0\xa2\x2f\xab\x5b\x79\x3b\xe7\x63\x41\x06\x5e\xcc\x1f\x18\x5e\x20\x61\xe5\x0b\xd0\xbc\xa8\x25\xc0\xe9\x58\x2a\x5e\x46\xed\xe9\xa5\x41\x40\x81\xc9\x4e\x70\x22\xbe\xbb\x58\xed\x68\x98\x63\xc2\x6d\xc0\x18\x72\xad\x32\x4a\x6e\x38\x94\x8d\x10\x6e\x2d\xc0\xd2\x60\x09\x7c\xfa\x34\x4f\x2d\x48\xac\xf4\xed\xee\x0b\x3e\x72\x59\xf6\xab\xa0\x16\x47\x1c\xc9\x82\x65\xa9\xe0\x17\xb6\x36\xc1\x46\xfb\x0f",
input: rawStringToArrayBuffer("\x4d\x52\xb1\x6e\xdc\x30\x0c\xdd\xf3\x15\x44\x80\x6e\xae\x91\x02\x4d\x80\x8e\x4d\x9a\x21\x53\x8b\xa6\x43\x56\x5a\xe2\x9d\x84\x93\x25\x43\x94\xed\xf8\xef\xf3\xe8\x6b\x0e\xb7\x1c\xce\xd4\x7b\x8f\x8f\x7c\x7c\xda\x06\xa9\x4f\x41\x0e\x14\x95\x98\x34\x8e\x53\x92\x8e\x62\x6e\x73\x6c\x71\x11\x5a\x65\x20\x9e\x26\x3a\x94\x4a\x8e\x6b\xdd\x62\x3e\x52\x99\x1b\x71\x4a\x34\x72\xce\x52\xa9\x1c\xe8\xd6\x99\xd0\x2d\x95\x49\x2a\xb7\x58\xb2\xd2\x1a\x5b\x88\x19\xa2\x26\x31\xd4\xb2\xaa\xd4\x9e\xfe\x05\x51\xb9\x86\xc5\xec\xd2\xec\xe5\x7f\x6b\x92\xec\x8a\xb7\x1e\x29\x9e\x84\xde\x7e\xff\x25\x34\x7e\x64\x95\x87\xef\x1d\x8d\xa5\x0a\xb9\x62\xc0\x77\x43\xd6\x6d\x32\x91\x33\xf6\xe7\xf3\x6b\x47\xbf\x9e\x5f\x89\xb3\xa7\xc7\x54\xd6\x43\xd4\xd0\x91\xab\x82\x4e\x10\x1c\x62\xe6\xba\xed\xaf\x41\xde\xfd\x3c\x4e\x8a\x57\x88\x55\x51\x35\x15\x7b\xf1\x72\x5d\xc1\x60\x9e\x1b\x03\xc6\xc9\xcd\xe9\xac\x13\x58\x31\xc3\x8e\x76\x41\xdc\x49\xe7\x11\x42\x2f\x7f\x96\x87\xbd\xf6\xd6\xdf\xdf\xfd\xa0\x89\xab\x02\x0c\x66\xe0\x7c\x34\x1a\xfe\x54\x76\x0d\xeb\xfa\x1c\x11\x2c\x23\x8c\xb3\x0b\xfb\x64\xfd\xcd\x0d\xb6\x43\xad\x94\x64\x69\x78\xd1\x78\xcc\xe2\x51\x00\x85\x07\x2c\x67\x28\x2d\x50\x13\x17\x72\x84\xa3\x9d\x9d\x4b\xfe\x7a\x5d\xe1\xb4\x69\x53\xe3\x20\x9c\x38\x99\x69\xd9\x87\xc0\xa2\x2f\xab\x5b\x79\x3b\xe7\x63\x41\x06\x5e\xcc\x1f\x18\x5e\x20\x61\xe5\x0b\xd0\xbc\xa8\x25\xc0\xe9\x58\x2a\x5e\x46\xed\xe9\xa5\x41\x40\x81\xc9\x4e\x70\x22\xbe\xbb\x58\xed\x68\x98\x63\xc2\x6d\xc0\x18\x72\xad\x32\x4a\x6e\x38\x94\x8d\x10\x6e\x2d\xc0\xd2\x60\x09\x7c\xfa\x34\x4f\x2d\x48\xac\xf4\xed\xee\x0b\x3e\x72\x59\xf6\xab\xa0\x16\x47\x1c\xc9\x82\x65\xa9\xe0\x17\xb6\x36\xc1\x46\xfb\x0f"),
expectedMatch: /#recipe=Raw_Inflate(.|\n)+CyberChef is a simple, intuitive web app for carrying out all manner of /,
recipeConfig: [
{

View File

@ -8,6 +8,8 @@
import TestRegister from "../../lib/TestRegister.mjs";
import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../../samples/Ciphers.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
// RSA-1024
const ALICE_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: Keybase OpenPGP v2.1.17
@ -168,7 +170,7 @@ TestRegister.addTests([
},
{
name: "PGP Encrypt/Decrypt: RSA, All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: ALL_BYTES,
recipeConfig: [
{
@ -198,7 +200,7 @@ TestRegister.addTests([
},
{
name: "PGP Encrypt/Decrypt: ECC, All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: ALL_BYTES,
recipeConfig: [
{
@ -213,7 +215,7 @@ TestRegister.addTests([
},
{
name: "PGP Sign/Verify: RSA, All bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedMatch: /Signed by PGP key ID: 2ADF8D8C\nPGP fingerprint: 7afe93ff7614167c3fe831fe1b75204b2adf8d8c\nSigned on .*\n----------------------------------\n/,
recipeConfig: [
{

View File

@ -8,6 +8,8 @@
import TestRegister from "../../lib/TestRegister.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "Parse TLV: LengthValue",
@ -55,7 +57,7 @@ TestRegister.addTests([
},
{
name: "Parse TLV: BER long-form length (two-byte length encoding)",
input: "\x01\x82\x01\x00" + "A".repeat(256) + "\x02\x03\x41\x42\x43",
input: rawStringToArrayBuffer("\x01\x82\x01\x00" + "A".repeat(256) + "\x02\x03\x41\x42\x43"),
expectedOutput: JSON.stringify([
{"key": [1], "length": 256, "value": Array(256).fill(65)},
{"key": [2], "length": 3, "value": [65, 66, 67]}
@ -69,7 +71,7 @@ TestRegister.addTests([
},
{
name: "Parse TLV: BER long-form length (one-byte length encoding)",
input: "\x01\x81\x80" + "B".repeat(128),
input: rawStringToArrayBuffer("\x01\x81\x80" + "B".repeat(128)),
expectedOutput: JSON.stringify([
{"key": [1], "length": 128, "value": Array(128).fill(66)}
], null, 4),
@ -82,7 +84,7 @@ TestRegister.addTests([
},
{
name: "Parse TLV: BER multiple entries with mixed short and long-form lengths",
input: "\x01\x05\x48\x65\x6c\x6c\x6f\x02\x81\x05\x57\x6f\x72\x6c\x64",
input: rawStringToArrayBuffer("\x01\x05\x48\x65\x6c\x6c\x6f\x02\x81\x05\x57\x6f\x72\x6c\x64"),
expectedOutput: JSON.stringify([
{"key": [1], "length": 5, "value": [72, 101, 108, 108, 111]},
{"key": [2], "length": 5, "value": [87, 111, 114, 108, 100]}

View File

@ -8,6 +8,8 @@
import TestRegister from "../../lib/TestRegister.mjs";
import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../../samples/Ciphers.mjs";
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
const PEM_PRIV_2048 = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwfaUOpUEutKyU3wkCv6kYunz4MqxzSuTSckRz1IxwZtwIiqq
+ejkM6ioXPyGadfFNvG0JVOgr1q4KQglq0vXaYG57HZ8iinXnHgy1vr8i+fWYITB
@ -94,7 +96,7 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, All bytes",
input: ALL_BYTES.substr(0, 100),
input: rawStringToArrayBuffer(ALL_BYTES.substr(0, 100)),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
@ -154,7 +156,7 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, All bytes",
input: ALL_BYTES.substr(0, 100),
input: rawStringToArrayBuffer(ALL_BYTES.substr(0, 100)),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
@ -214,7 +216,7 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, All bytes",
input: ALL_BYTES.substr(0, 100),
input: rawStringToArrayBuffer(ALL_BYTES.substr(0, 100)),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
@ -274,7 +276,7 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, All bytes",
input: ALL_BYTES.substr(0, 100),
input: rawStringToArrayBuffer(ALL_BYTES.substr(0, 100)),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
@ -334,7 +336,7 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, All bytes",
input: ALL_BYTES.substr(0, 100),
input: rawStringToArrayBuffer(ALL_BYTES.substr(0, 100)),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{

View File

@ -28,6 +28,8 @@ const ALL_BYTES = [
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
const rawStringToArrayBuffer = str => Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
TestRegister.addTests([
{
name: "XOR Checksum (1): nothing",
@ -64,7 +66,7 @@ TestRegister.addTests([
},
{
name: "XOR Checksum (1): all bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "00",
recipeConfig: [
{
@ -108,7 +110,7 @@ TestRegister.addTests([
},
{
name: "XOR Checksum (4): all bytes",
input: ALL_BYTES,
input: rawStringToArrayBuffer(ALL_BYTES),
expectedOutput: "00000000",
recipeConfig: [
{