mirror of
https://github.com/gchq/CyberChef
synced 2026-01-06 18:43:23 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a19aea1516 | ||
|
|
137f8d9471 | ||
|
|
1f57f1f000 | ||
|
|
468071ee98 | ||
|
|
23403f55a5 | ||
|
|
c25cf44d92 | ||
|
|
e5644b5712 | ||
|
|
5b134d7e9e | ||
|
|
cb023089bb | ||
|
|
8e57354307 | ||
|
|
126debf44e |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.50.9",
|
"version": "9.50.12",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.50.9",
|
"version": "9.50.12",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.50.9",
|
"version": "9.50.12",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
|
|||||||
@@ -103,3 +103,15 @@ export function hexadecimalSort(a, b) {
|
|||||||
|
|
||||||
return a.localeCompare(b);
|
return a.localeCompare(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparison operation for sorting by length
|
||||||
|
*
|
||||||
|
* @param {string} a
|
||||||
|
* @param {string} b
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function lengthSort(a, b) {
|
||||||
|
return a.length - b.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,18 @@ class Fletcher32Checksum extends Operation {
|
|||||||
run(input, args) {
|
run(input, args) {
|
||||||
let a = 0,
|
let a = 0,
|
||||||
b = 0;
|
b = 0;
|
||||||
input = new Uint8Array(input);
|
if (ArrayBuffer.isView(input)) {
|
||||||
|
input = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else {
|
||||||
|
input = new DataView(input);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.byteLength - 1; i += 2) {
|
||||||
a = (a + input[i]) % 0xffff;
|
a = (a + input.getUint16(i, true)) % 0xffff;
|
||||||
|
b = (b + a) % 0xffff;
|
||||||
|
}
|
||||||
|
if (input.byteLength % 2 !== 0) {
|
||||||
|
a = (a + input.getUint8(input.byteLength - 1)) % 0xffff;
|
||||||
b = (b + a) % 0xffff;
|
b = (b + a) % 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,22 @@ class Fletcher64Checksum extends Operation {
|
|||||||
run(input, args) {
|
run(input, args) {
|
||||||
let a = 0,
|
let a = 0,
|
||||||
b = 0;
|
b = 0;
|
||||||
input = new Uint8Array(input);
|
if (ArrayBuffer.isView(input)) {
|
||||||
|
input = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else {
|
||||||
|
input = new DataView(input);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.byteLength - 3; i += 4) {
|
||||||
a = (a + input[i]) % 0xffffffff;
|
a = (a + input.getUint32(i, true)) % 0xffffffff;
|
||||||
|
b = (b + a) % 0xffffffff;
|
||||||
|
}
|
||||||
|
if (input.byteLength % 4 !== 0) {
|
||||||
|
let lastValue = 0;
|
||||||
|
for (let i = 0; i < input.byteLength % 4; i++) {
|
||||||
|
lastValue = (lastValue << 8) | input.getUint8(input.byteLength - 1 - i);
|
||||||
|
}
|
||||||
|
a = (a + lastValue) % 0xffffffff;
|
||||||
b = (b + a) % 0xffffffff;
|
b = (b + a) % 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||||
import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort} from "../lib/Sort.mjs";
|
import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort, lengthSort} from "../lib/Sort.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort operation
|
* Sort operation
|
||||||
@@ -39,7 +39,7 @@ class Sort extends Operation {
|
|||||||
{
|
{
|
||||||
"name": "Order",
|
"name": "Order",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)"]
|
"value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)", "Length"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,8 @@ class Sort extends Operation {
|
|||||||
sorted = sorted.sort(numericSort);
|
sorted = sorted.sort(numericSort);
|
||||||
} else if (order === "Numeric (hexadecimal)") {
|
} else if (order === "Numeric (hexadecimal)") {
|
||||||
sorted = sorted.sort(hexadecimalSort);
|
sorted = sorted.sort(hexadecimalSort);
|
||||||
|
} else if (order === "Length") {
|
||||||
|
sorted = sorted.sort(lengthSort);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortReverse) sorted.reverse();
|
if (sortReverse) sorted.reverse();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class ToTable extends Operation {
|
|||||||
|
|
||||||
this.name = "To Table";
|
this.name = "To Table";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Data can be split on different characters and rendered as an HTML or ASCII table with an optional header row.<br><br>Supports the CSV (Comma Separated Values) file format by default. Change the cell delimiter argument to <code>\\t</code> to support TSV (Tab Separated Values) or <code>|</code> for PSV (Pipe Separated Values).<br><br>You can enter as many delimiters as you like. Each character will be treat as a separate possible delimiter.";
|
this.description = "Data can be split on different characters and rendered as an HTML, ASCII or Markdown table with an optional header row.<br><br>Supports the CSV (Comma Separated Values) file format by default. Change the cell delimiter argument to <code>\\t</code> to support TSV (Tab Separated Values) or <code>|</code> for PSV (Pipe Separated Values).<br><br>You can enter as many delimiters as you like. Each character will be treat as a separate possible delimiter.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "html";
|
this.outputType = "html";
|
||||||
@@ -43,7 +43,7 @@ class ToTable extends Operation {
|
|||||||
{
|
{
|
||||||
"name": "Format",
|
"name": "Format",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["ASCII", "HTML"]
|
"value": ["ASCII", "HTML", "Markdown"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -66,6 +66,9 @@ class ToTable extends Operation {
|
|||||||
case "ASCII":
|
case "ASCII":
|
||||||
return asciiOutput(tableData);
|
return asciiOutput(tableData);
|
||||||
case "HTML":
|
case "HTML":
|
||||||
|
return htmlOutput(tableData);
|
||||||
|
case "Markdown":
|
||||||
|
return markdownOutput(tableData);
|
||||||
default:
|
default:
|
||||||
return htmlOutput(tableData);
|
return htmlOutput(tableData);
|
||||||
}
|
}
|
||||||
@@ -183,6 +186,59 @@ class ToTable extends Operation {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs an array of data as a Markdown table.
|
||||||
|
*
|
||||||
|
* @param {string[][]} tableData
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function markdownOutput(tableData) {
|
||||||
|
const headerDivider = "-";
|
||||||
|
const verticalBorder = "|";
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
const longestCells = [];
|
||||||
|
|
||||||
|
// Find longestCells value per column to pad cells equally.
|
||||||
|
tableData.forEach(function(row, index) {
|
||||||
|
row.forEach(function(cell, cellIndex) {
|
||||||
|
if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) {
|
||||||
|
longestCells[cellIndex] = cell.length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ignoring the checkbox, as current Mardown renderer in CF doesn't handle table without headers
|
||||||
|
const row = tableData.shift();
|
||||||
|
output += outputRow(row, longestCells);
|
||||||
|
let rowOutput = verticalBorder;
|
||||||
|
row.forEach(function(cell, index) {
|
||||||
|
rowOutput += " " + headerDivider + " " + verticalBorder;
|
||||||
|
});
|
||||||
|
output += rowOutput += "\n";
|
||||||
|
|
||||||
|
// Add the rest of the table rows.
|
||||||
|
tableData.forEach(function(row, index) {
|
||||||
|
output += outputRow(row, longestCells);
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outputs a row of correctly padded cells.
|
||||||
|
*/
|
||||||
|
function outputRow(row, longestCells) {
|
||||||
|
let rowOutput = verticalBorder;
|
||||||
|
row.forEach(function(cell, index) {
|
||||||
|
rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder;
|
||||||
|
});
|
||||||
|
rowOutput += "\n";
|
||||||
|
return rowOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ import "./tests/LS47.mjs";
|
|||||||
import "./tests/LZString.mjs";
|
import "./tests/LZString.mjs";
|
||||||
import "./tests/NTLM.mjs";
|
import "./tests/NTLM.mjs";
|
||||||
import "./tests/Shuffle.mjs";
|
import "./tests/Shuffle.mjs";
|
||||||
|
import "./tests/FletcherChecksum.mjs";
|
||||||
|
|
||||||
// Cannot test operations that use the File type yet
|
// Cannot test operations that use the File type yet
|
||||||
// import "./tests/SplitColourChannels.mjs";
|
// import "./tests/SplitColourChannels.mjs";
|
||||||
|
|||||||
108
tests/operations/tests/FletcherChecksum.mjs
Normal file
108
tests/operations/tests/FletcherChecksum.mjs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* @author mikecat
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "c8f0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "2057",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-16 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "0627",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-16 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "f04fc729",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "56502d2a",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-32 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "ebe19591",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-32 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcde",
|
||||||
|
input: "abcde",
|
||||||
|
expectedOutput: "c8c6c527646362c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcdef",
|
||||||
|
input: "abcdef",
|
||||||
|
expectedOutput: "c8c72b276463c8c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fletcher-64 Checksum: abcdefgh",
|
||||||
|
input: "abcdefgh",
|
||||||
|
expectedOutput: "312e2b28cccac8c6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Fletcher-64 Checksum",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
@@ -58,8 +58,8 @@ CTPH: A:E:E
|
|||||||
Checksums:
|
Checksums:
|
||||||
Fletcher-8: 3d
|
Fletcher-8: 3d
|
||||||
Fletcher-16: 5dc1
|
Fletcher-16: 5dc1
|
||||||
Fletcher-32: 045901c0
|
Fletcher-32: 3f5cd9e7
|
||||||
Fletcher-64: 00000459000001c0
|
Fletcher-64: 7473657474736574
|
||||||
Adler-32: 045d01c1
|
Adler-32: 045d01c1
|
||||||
CRC-8: b9
|
CRC-8: b9
|
||||||
CRC-16: f82e
|
CRC-16: f82e
|
||||||
|
|||||||
Reference in New Issue
Block a user