mirror of
https://github.com/gchq/CyberChef.git
synced 2025-05-10 16:25:01 -04:00
Merge pull request #33 from linuxgemini/linuxgemini-patch-modhex
feat(Modhex): Introduce basic Modhex conversion
This commit is contained in:
commit
4c145c50dd
6 changed files with 444 additions and 0 deletions
|
@ -10,6 +10,8 @@
|
|||
"From Hexdump",
|
||||
"To Hex",
|
||||
"From Hex",
|
||||
"To Modhex",
|
||||
"From Modhex",
|
||||
"To Charcode",
|
||||
"From Charcode",
|
||||
"To Decimal",
|
||||
|
|
65
src/core/lib/Modhex.mjs
Normal file
65
src/core/lib/Modhex.mjs
Normal file
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Modhex helpers.
|
||||
*
|
||||
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Modhex to Hex conversion map.
|
||||
*/
|
||||
export const MODHEX_TO_HEX_CONVERSION_MAP = {
|
||||
"c": "0",
|
||||
"b": "1",
|
||||
"d": "2",
|
||||
"e": "3",
|
||||
"f": "4",
|
||||
"g": "5",
|
||||
"h": "6",
|
||||
"i": "7",
|
||||
"j": "8",
|
||||
"k": "9",
|
||||
"l": "a",
|
||||
"n": "b",
|
||||
"r": "c",
|
||||
"t": "d",
|
||||
"u": "e",
|
||||
"v": "f"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hex to Modhex conversion map.
|
||||
*/
|
||||
export const HEX_TO_MODHEX_CONVERSION_MAP = {
|
||||
"0": "c",
|
||||
"1": "b",
|
||||
"2": "d",
|
||||
"3": "e",
|
||||
"4": "f",
|
||||
"5": "g",
|
||||
"6": "h",
|
||||
"7": "i",
|
||||
"8": "j",
|
||||
"9": "k",
|
||||
"a": "l",
|
||||
"b": "n",
|
||||
"c": "r",
|
||||
"d": "t",
|
||||
"e": "u",
|
||||
"f": "v"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
123
src/core/operations/FromModhex.mjs
Normal file
123
src/core/operations/FromModhex.mjs
Normal file
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import { FROM_MODHEX_DELIM_OPTIONS, MODHEX_TO_HEX_CONVERSION_MAP } from "../lib/Modhex.mjs";
|
||||
import { fromHex } from "../lib/Hex.mjs";
|
||||
import Utils from "../Utils.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"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hex 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");
|
||||
*/
|
||||
fromModhex(data, delim="Auto", byteLen=2) {
|
||||
if (!data || data.length === 0) return [];
|
||||
|
||||
data = data.toLowerCase();
|
||||
|
||||
if (delim !== "None") {
|
||||
const delimRegex = delim === "Auto" ? /[^cbdefghijklnrtuv]/gi : Utils.regexRep(delim);
|
||||
data = data.replace(delimRegex, "");
|
||||
}
|
||||
|
||||
data = data.replace(/\s/g, "");
|
||||
|
||||
let hexconv = "";
|
||||
for (const letter of data.split("")) {
|
||||
hexconv += MODHEX_TO_HEX_CONVERSION_MAP[letter];
|
||||
}
|
||||
|
||||
const output = fromHex(hexconv, "None", byteLen);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = args[0] || "Auto";
|
||||
return this.fromModhex(input, delim, 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromModhex;
|
110
src/core/operations/ToModhex.mjs
Normal file
110
src/core/operations/ToModhex.mjs
Normal file
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* @author linuxgemini [ilteris@asenkron.com.tr]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import { TO_MODHEX_DELIM_OPTIONS, HEX_TO_MODHEX_CONVERSION_MAP } from "../lib/Modhex.mjs";
|
||||
import { toHex } from "../lib/Hex.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
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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], ":");
|
||||
*/
|
||||
toModhex(data, delim=" ", padding=2, extraDelim="", lineSize=0) {
|
||||
if (!data || data.length === 0) return "";
|
||||
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
||||
|
||||
const hexconv = toHex(data, "", padding, "", 0);
|
||||
let modhexconv = "";
|
||||
let output = "";
|
||||
|
||||
for (const letter of hexconv.split("")) {
|
||||
modhexconv += HEX_TO_MODHEX_CONVERSION_MAP[letter];
|
||||
}
|
||||
|
||||
const groupedModhex = modhexconv.match(/.{1,2}/g);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0]);
|
||||
const lineSize = args[1];
|
||||
|
||||
return this.toModhex(new Uint8Array(input), delim, 2, "", lineSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToModhex;
|
Loading…
Add table
Add a link
Reference in a new issue