2
0
mirror of https://github.com/gchq/CyberChef synced 2025-12-05 23:53:27 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
n1474335
dcc28438ff 7.11.1 2018-05-10 15:34:23 +00:00
n1474335
df7c1721f5 PGP ops no longer require a key to be in date 2018-05-10 15:34:10 +00:00
n1474335
403296cc59 7.11.0 2018-05-04 16:11:50 +00:00
n1474335
addb2b4448 Merge branch 'JustAnotherMark-totable-operation' 2018-05-04 16:10:39 +00:00
n1474335
8556bdcdeb Tidied up 'To Table' operation, adding better CSV parsing support. 2018-05-04 16:10:22 +00:00
n1474335
8fc5f59647 Merge branch 'totable-operation' of https://github.com/JustAnotherMark/CyberChef into JustAnotherMark-totable-operation 2018-05-01 15:41:51 +00:00
n1474335
f7729c0fd2 7.10.3 2018-04-30 17:55:26 +00:00
n1474335
e2376c7c71 'BSON serialise' errors are now thrown correctly 2018-04-30 17:55:21 +00:00
n1474335
2cefd3b941 Updated dependencies 2018-04-30 17:52:43 +00:00
n1474335
68ab2da866 7.10.2 2018-04-30 16:51:24 +00:00
n1474335
72f7f0b70c Utils.fromHex function now defaults to automatically strip all delimiters. Fixes #295 2018-04-30 16:51:04 +00:00
Mark Jones
411bba53a8 Fix code style issues raised by linting. 2018-04-26 13:00:35 +01:00
Mark Jones
e2af3c78e7 Added ToTable operation to output data as ASCII or HTML tables. 2018-04-26 00:33:19 +01:00
10 changed files with 952 additions and 1863 deletions

2532
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "7.10.1",
"version": "7.11.1",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -30,7 +30,7 @@
"main": "build/node/CyberChef.js",
"bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
@@ -50,33 +50,33 @@
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.2.1",
"grunt-webpack": "^3.1.1",
"html-webpack-plugin": "^3.1.0",
"html-webpack-plugin": "^3.2.0",
"imports-loader": "^0.8.0",
"ink-docstrap": "^1.3.2",
"jsdoc-babel": "^0.4.0",
"less": "^3.0.1",
"less": "^3.0.2",
"less-loader": "^4.1.0",
"postcss-css-variables": "^0.8.1",
"postcss-import": "^11.1.0",
"postcss-loader": "^2.1.3",
"postcss-loader": "^2.1.4",
"sitemap": "^1.13.0",
"style-loader": "^0.20.3",
"style-loader": "^0.21.0",
"url-loader": "^1.0.1",
"val-loader": "^1.1.0",
"web-resource-inliner": "^4.2.1",
"webpack": "^4.3.0",
"webpack-dev-server": "^3.1.1",
"webpack-node-externals": "^1.6.0",
"webpack": "^4.6.0",
"webpack-dev-server": "^3.1.3",
"webpack-node-externals": "^1.7.2",
"worker-loader": "^1.1.1"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"bcryptjs": "^2.4.3",
"bignumber.js": "^6.0.0",
"bignumber.js": "^7.0.1",
"bootstrap": "^3.3.7",
"bootstrap-colorpicker": "^2.5.2",
"bootstrap-switch": "^3.3.4",
"bson": "^2.0.4",
"bson": "^2.0.6",
"crypto-api": "^0.8.0",
"crypto-js": "^3.1.9-1",
"ctph.js": "0.0.5",
@@ -94,14 +94,14 @@
"jsbn": "^1.1.0",
"jsesc": "^2.5.1",
"jsonpath": "^1.0.0",
"jsrsasign": "8.0.7",
"lodash": "^4.17.5",
"jsrsasign": "8.0.12",
"lodash": "^4.17.10",
"loglevel": "^1.6.1",
"kbpgp": "^2.0.77",
"loglevel-message-prefix": "^3.0.0",
"moment": "^2.21.0",
"moment-timezone": "^0.5.14",
"node-forge": "^0.7.4",
"moment": "^2.22.1",
"moment-timezone": "^0.5.16",
"node-forge": "^0.7.5",
"node-md6": "^0.1.0",
"nwmatcher": "^1.4.4",
"otp": "^0.1.3",

View File

@@ -718,10 +718,10 @@ const Utils = {
* Utils.fromHex("0a:14:1e", "Colon");
*/
fromHex: function(data, delim, byteLen) {
delim = delim || (data.indexOf(" ") >= 0 ? "Space" : "None");
delim = delim || "Auto";
byteLen = byteLen || 2;
if (delim !== "None") {
const delimRegex = Utils.regexRep[delim];
const delimRegex = delim === "Auto" ? /[^a-f\d]/gi : Utils.regexRep[delim];
data = data.replace(delimRegex, "");
}
@@ -737,37 +737,43 @@ const Utils = {
* Parses CSV data and returns it as a two dimensional array or strings.
*
* @param {string} data
* @param {string[]} [cellDelims=[","]]
* @param {string[]} [lineDelims=["\n", "\r"]]
* @returns {string[][]}
*
* @example
* // returns [["head1", "head2"], ["data1", "data2"]]
* Utils.parseCSV("head1,head2\ndata1,data2");
*/
parseCSV: function(data) {
parseCSV: function(data, cellDelims=[","], lineDelims=["\n", "\r"]) {
let b,
ignoreNext = false,
next,
renderNext = false,
inString = false,
cell = "",
line = [],
lines = [];
// Remove BOM, often present in Excel CSV files
if (data.length && data[0] === "\uFEFF") data = data.substr(1);
for (let i = 0; i < data.length; i++) {
b = data[i];
if (ignoreNext) {
next = data[i+1] || "";
if (renderNext) {
cell += b;
ignoreNext = false;
renderNext = false;
} else if (b === "\\") {
cell += b;
ignoreNext = true;
renderNext = true;
} else if (b === "\"" && !inString) {
inString = true;
} else if (b === "\"" && inString) {
inString = false;
} else if (b === "," && !inString) {
if (next === "\"") renderNext = true;
else inString = false;
} else if (!inString && cellDelims.indexOf(b) >= 0) {
line.push(cell);
cell = "";
} else if ((b === "\n" || b === "\r") && !inString) {
} else if (!inString && lineDelims.indexOf(b) >= 0) {
line.push(cell);
cell = "";
lines.push(line);

View File

@@ -182,6 +182,7 @@ const Categories = [
"To Lower case",
"Add line numbers",
"Remove line numbers",
"To Table",
"Reverse",
"Sort",
"Unique",

View File

@@ -37,6 +37,7 @@ import SeqUtils from "../operations/SeqUtils.js";
import Shellcode from "../operations/Shellcode.js";
import StrUtils from "../operations/StrUtils.js";
import Tidy from "../operations/Tidy.js";
import ToTable from "../operations/ToTable.js";
import Unicode from "../operations/Unicode.js";
import URL_ from "../operations/URL.js";
@@ -613,6 +614,34 @@ const OperationConfig = {
}
]
},
"To Table": {
module: "Default",
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.",
inputType: "string",
outputType: "html",
args: [
{
name: "Cell delimiters",
type: "binaryShortString",
value: ","
},
{
name: "Row delimiters",
type: "binaryShortString",
value: "\\n\\r"
},
{
name: "Make first row header",
type: "boolean",
value: false
},
{
name: "Format",
type: "option",
value: ToTable.FORMATS
}
]
},
"From Hex": {
module: "Default",
description: "Converts a hexadecimal byte string back into its raw value.<br><br>e.g. <code>ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a</code> becomes the UTF-8 encoded string <code>Γειά σου</code>",
@@ -624,7 +653,7 @@ const OperationConfig = {
{
name: "Delimiter",
type: "option",
value: ByteRepr.HEX_DELIM_OPTIONS
value: ByteRepr.FROM_HEX_DELIM_OPTIONS
}
]
},
@@ -639,7 +668,7 @@ const OperationConfig = {
{
name: "Delimiter",
type: "option",
value: ByteRepr.HEX_DELIM_OPTIONS
value: ByteRepr.TO_HEX_DELIM_OPTIONS
}
]
},

View File

@@ -27,6 +27,7 @@ import Rotate from "../../operations/Rotate.js";
import SeqUtils from "../../operations/SeqUtils.js";
import StrUtils from "../../operations/StrUtils.js";
import Tidy from "../../operations/Tidy.js";
import ToTable from "../../operations/ToTable.js";
import Unicode from "../../operations/Unicode.js";
import UUID from "../../operations/UUID.js";
import XKCD from "../../operations/XKCD.js";
@@ -163,6 +164,7 @@ OpModules.Default = {
"Mean": Arithmetic.runMean,
"Median": Arithmetic.runMedian,
"Standard Deviation": Arithmetic.runStdDev,
"To Table": ToTable.runToTable,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
"XKCD Random Number": XKCD.runRandomNumber,

View File

@@ -29,7 +29,7 @@ const BSON = {
const data = JSON.parse(input);
return bson.serialize(data).buffer;
} catch (err) {
return err.toString();
throw err.toString();
}
},

View File

@@ -21,7 +21,12 @@ const ByteRepr = {
* @constant
* @default
*/
HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
TO_HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
/**
* @constant
* @default
*/
FROM_HEX_DELIM_OPTIONS: ["Auto", "Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
/**
* @constant
* @default

View File

@@ -90,13 +90,16 @@ const PGP = {
try {
const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
armored: privateKey,
opts: {
"no_check_keys": true
}
});
if (key.is_pgp_locked() && passphrase) {
if (key.is_pgp_locked()) {
if (passphrase) {
await promisify(key.unlock_pgp.bind(key))({
passphrase
});
} else if (!passphrase) {
} else {
throw "Did not provide passphrase with locked private key.";
}
}
@@ -118,6 +121,9 @@ const PGP = {
try {
const key = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({
armored: publicKey,
opts: {
"no_check_keys": true
}
});
return key;
} catch (err) {

164
src/core/operations/ToTable.js Executable file
View File

@@ -0,0 +1,164 @@
/**
* ToTable operations.
*
* @author Mark Jones [github.com/justanothermark]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*
* @namespace
*/
import Utils from "../Utils.js";
const ToTable = {
/**
* @constant
* @default
*/
FORMATS: [
"ASCII",
"HTML"
],
/**
* To Table operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runToTable: function (input, args) {
const [cellDelims, rowDelims, firstRowHeader, format] = args;
// Process the input into a nested array of elements.
const tableData = Utils.parseCSV(input, cellDelims.split(""), rowDelims.split(""));
if (!tableData.length) return "";
// Render the data in the requested format.
switch (format) {
case "ASCII":
return asciiOutput(tableData);
case "HTML":
default:
return htmlOutput(tableData);
}
/**
* Outputs an array of data as an ASCII table.
*
* @param {string[][]} tableData
* @returns {string}
*/
function asciiOutput(tableData) {
const horizontalBorder = "-";
const verticalBorder = "|";
const crossBorder = "+";
let output = "";
let 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;
}
});
});
// Add the top border of the table to the output.
output += outputHorizontalBorder(longestCells);
// If the first row is a header, remove the row from the data and
// add it to the output with another horizontal border.
if (firstRowHeader) {
let row = tableData.shift();
output += outputRow(row, longestCells);
output += outputHorizontalBorder(longestCells);
}
// Add the rest of the table rows.
tableData.forEach(function(row, index) {
output += outputRow(row, longestCells);
});
// Close the table with a final horizontal border.
output += outputHorizontalBorder(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;
}
/**
* Outputs a horizontal border with a different character where
* the horizontal border meets a vertical border.
*/
function outputHorizontalBorder(longestCells) {
let rowOutput = crossBorder;
longestCells.forEach(function(cellLength) {
rowOutput += horizontalBorder.repeat(cellLength + 2) + crossBorder;
});
rowOutput += "\n";
return rowOutput;
}
}
/**
* Outputs a table of data as a HTML table.
*
* @param {string[][]} tableData
* @returns {string}
*/
function htmlOutput(tableData) {
// Start the HTML output with suitable classes for styling.
let output = "<table class='table table-hover table-condensed table-bordered table-nonfluid'>";
// If the first row is a header then put it in <thead> with <th> cells.
if (firstRowHeader) {
let row = tableData.shift();
output += "<thead>";
output += outputRow(row, "th");
output += "</thead>";
}
// Output the rest of the rows in the <tbody>.
output += "<tbody>";
tableData.forEach(function(row, index) {
output += outputRow(row, "td");
});
// Close the body and table elements.
output += "</tbody></table>";
return output;
/**
* Outputs a table row.
*
* @param {string[]} row
* @param {string} cellType
*/
function outputRow(row, cellType) {
let output = "<tr>";
row.forEach(function(cell) {
output += "<" + cellType + ">" + cell + "</" + cellType + ">";
});
output += "</tr>";
return output;
}
}
}
};
export default ToTable;