mirror of
https://github.com/gchq/CyberChef.git
synced 2025-05-08 07:21:02 -04:00
Merge 30840f86e9
into dcc28438ff
This commit is contained in:
commit
ca86cdb544
6 changed files with 292 additions and 0 deletions
|
@ -44,6 +44,8 @@ const Categories = [
|
|||
"From Base32",
|
||||
"To Base58",
|
||||
"From Base58",
|
||||
"To Base85",
|
||||
"From Base85",
|
||||
"To Base",
|
||||
"From Base",
|
||||
"To BCD",
|
||||
|
|
|
@ -2,6 +2,7 @@ import Arithmetic from "../operations/Arithmetic.js";
|
|||
import Base from "../operations/Base.js";
|
||||
import Base58 from "../operations/Base58.js";
|
||||
import Base64 from "../operations/Base64.js";
|
||||
import Base85 from "../operations/Base85.js";
|
||||
import BCD from "../operations/BCD.js";
|
||||
import BitwiseOp from "../operations/BitwiseOp.js";
|
||||
import ByteRepr from "../operations/ByteRepr.js";
|
||||
|
@ -320,6 +321,37 @@ const OperationConfig = {
|
|||
}
|
||||
]
|
||||
},
|
||||
"To Base85": {
|
||||
module: "Default",
|
||||
description: "Base85 (similar to Base64) is a notation for encoding arbitrary byte data. It is usually more efficient that Base64.<br><br>This operation encodes data in an ASCII string (with an alphabet of your choosing, presets included).<br><br>e.g. <code>hello world</code> becomes <code>BOu!rD]j7BEbo7</code><br><br>Base85 is commonly used in Adobe's PostScript and PDF file formats.<br><br><strong>Options</strong><br><u>Alphabet</u><ul><li>Standard - The standard alphabet, referred to as Ascii85</li><li>Z85 (ZeroMQ) - A string-safe variant of Base85, which avoids quote marks and backslash characters</li><li>IPv6 - A variant of Base85 suitable for encoding IPv6 addresses (RFC 1924)</li></ul><u>Include delimiter</u><br>Adds a '<~' and '~>' delimiter to the start and end of the data. This is standard for Adobe's implementation of Base85.",
|
||||
inputType: "byteArray",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "editableOption",
|
||||
value: Base85.ALPHABET_OPTIONS
|
||||
},
|
||||
{
|
||||
name: "Include delimiter",
|
||||
type: "boolean",
|
||||
value: Base85.INCLUDE_DELIMITER
|
||||
},
|
||||
]
|
||||
},
|
||||
"From Base85": {
|
||||
module: "Default",
|
||||
description: "Base85 (similar to Base64) is a notation for encoding arbitrary byte data. It is usually more efficient that Base64.<br><br>This operation decodes data from an ASCII string (with an alphabet of your choosing, presets included).<br><br>e.g. <code>BOu!rD]j7BEbo7</code> becomes <code>hello world</code><br><br>Base85 is commonly used in Adobe's PostScript and PDF file formats.",
|
||||
inputType: "string",
|
||||
outputType: "byteArray",
|
||||
args: [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "editableOption",
|
||||
value: Base85.ALPHABET_OPTIONS
|
||||
},
|
||||
]
|
||||
},
|
||||
"Show Base64 offsets": {
|
||||
module: "Default",
|
||||
description: "When a string is within a block of data and the whole block is Base64'd, the string itself could be represented in Base64 in three distinct ways depending on its offset within the block.<br><br>This operation shows all possible offsets for a given string so that each possible encoding can be considered.",
|
||||
|
|
|
@ -2,6 +2,7 @@ import FlowControl from "../../FlowControl.js";
|
|||
import Arithmetic from "../../operations/Arithmetic.js";
|
||||
import Base from "../../operations/Base.js";
|
||||
import Base58 from "../../operations/Base58.js";
|
||||
import Base85 from "../../operations/Base85.js";
|
||||
import Base64 from "../../operations/Base64.js";
|
||||
import BCD from "../../operations/BCD.js";
|
||||
import BitwiseOp from "../../operations/BitwiseOp.js";
|
||||
|
@ -74,6 +75,8 @@ OpModules.Default = {
|
|||
"From Base32": Base64.runFrom32,
|
||||
"To Base58": Base58.runTo,
|
||||
"From Base58": Base58.runFrom,
|
||||
"To Base85": Base85.runTo,
|
||||
"From Base85": Base85.runFrom,
|
||||
"To Base": Base.runTo,
|
||||
"From Base": Base.runFrom,
|
||||
"To BCD": BCD.runToBCD,
|
||||
|
|
165
src/core/operations/Base85.js
Normal file
165
src/core/operations/Base85.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* Base85 operations.
|
||||
*
|
||||
* @author George J [george@penguingeorge.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Base85 = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
ALPHABET_OPTIONS: [
|
||||
{
|
||||
name: "Standard",
|
||||
value: "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu",
|
||||
},
|
||||
{
|
||||
name: "Z85 (ZeroMQ)",
|
||||
value: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#",
|
||||
},
|
||||
{
|
||||
name: "IPv6",
|
||||
value: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|~}",
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* Includes a '<~' and '~>' at the beginning and end of the Base85 data.
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
INCLUDE_DELIMITER: false,
|
||||
|
||||
/**
|
||||
* To Base85 operation.
|
||||
*
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runTo: function(input, args) {
|
||||
let alphabet = args[0] || Base85.ALPHABET_OPTIONS[0].value,
|
||||
encoding = Base85._alphabetName(alphabet),
|
||||
result = "";
|
||||
|
||||
if (alphabet.length !== 85 || [].unique.call(alphabet).length !== 85) {
|
||||
throw ("Alphabet must be of length 85");
|
||||
}
|
||||
|
||||
let block;
|
||||
for (let i = 0; i < input.length; i += 4) {
|
||||
block = (
|
||||
((input[i]) << 24) +
|
||||
((input[i + 1] || 0) << 16) +
|
||||
((input[i + 2] || 0) << 8) +
|
||||
((input[i + 3] || 0))
|
||||
) >>> 0;
|
||||
|
||||
if (encoding !== "Standard" || block > 0) {
|
||||
let digits = [];
|
||||
for (let j = 0; j < 5; j++) {
|
||||
digits.push(block % 85);
|
||||
block = Math.floor(block / 85);
|
||||
}
|
||||
|
||||
digits = digits.reverse();
|
||||
|
||||
if (input.length < i + 4) {
|
||||
digits.splice(input.length - (i + 4), 4);
|
||||
}
|
||||
|
||||
result += digits.map(digit => alphabet[digit]).join("");
|
||||
} else {
|
||||
result += (encoding === "Standard") ? "z" : null;
|
||||
}
|
||||
}
|
||||
|
||||
if (args[1] || Base85.INCLUDE_DELIMITER) result = "<~" + result + "~>";
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* From Base85 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
runFrom: function(input, args) {
|
||||
let alphabet = args[0] || Base85.ALPHABET_OPTIONS[0].value,
|
||||
encoding = Base85._alphabetName(alphabet),
|
||||
result = [];
|
||||
|
||||
if (alphabet.length !== 85 || [].unique.call(alphabet).length !== 85) {
|
||||
throw ("Alphabet must be of length 85");
|
||||
}
|
||||
|
||||
let matches = input.match(/<~(.+?)~>/);
|
||||
if (matches !== null) input = matches[1];
|
||||
|
||||
let i = 0;
|
||||
let block, blockBytes;
|
||||
while (i < input.length) {
|
||||
if (encoding === "Standard" && input[i] === "z") {
|
||||
result.push(0, 0, 0, 0);
|
||||
i++;
|
||||
} else {
|
||||
let digits = [];
|
||||
digits = input
|
||||
.substr(i, 5)
|
||||
.split("")
|
||||
.map((chr, idx) => {
|
||||
let digit = alphabet.indexOf(chr);
|
||||
if (digit < 0 || digit > 84) {
|
||||
throw "Invalid character '" + chr + "' at index " + idx;
|
||||
}
|
||||
return digit;
|
||||
});
|
||||
|
||||
block =
|
||||
digits[0] * 52200625 +
|
||||
digits[1] * 614125 +
|
||||
(i + 2 < input.length ? digits[2] : 84) * 7225 +
|
||||
(i + 3 < input.length ? digits[3] : 84) * 85 +
|
||||
(i + 4 < input.length ? digits[4] : 84);
|
||||
|
||||
blockBytes = [
|
||||
(block >> 24) & 0xff,
|
||||
(block >> 16) & 0xff,
|
||||
(block >> 8) & 0xff,
|
||||
block & 0xff
|
||||
];
|
||||
|
||||
if (input.length < i + 5) {
|
||||
blockBytes.splice(input.length - (i + 5), 5);
|
||||
}
|
||||
|
||||
result.push.apply(result, blockBytes);
|
||||
i += 5;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the name of the alphabet, when given the alphabet.
|
||||
*/
|
||||
_alphabetName: function(alphabet) {
|
||||
alphabet = alphabet.replace("'", "'");
|
||||
let name;
|
||||
Base85.ALPHABET_OPTIONS.forEach(function(a) {
|
||||
if (escape(alphabet) === escape(a.value)) name = a.name;
|
||||
});
|
||||
return name;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default Base85;
|
|
@ -15,6 +15,7 @@ import "babel-polyfill";
|
|||
import TestRegister from "./TestRegister.js";
|
||||
import "./tests/operations/Base58.js";
|
||||
import "./tests/operations/Base64.js";
|
||||
import "./tests/operations/Base85.js";
|
||||
import "./tests/operations/BCD.js";
|
||||
import "./tests/operations/BitwiseOp.js";
|
||||
import "./tests/operations/BSON.js";
|
||||
|
|
89
test/tests/operations/Base85.js
Normal file
89
test/tests/operations/Base85.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* Base85 tests.
|
||||
*
|
||||
* @author George J [george@penguingeorge.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Base85 (Standard): nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base85",
|
||||
args: [null, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base85 (Standard (Ascii85)): Hello, World!",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "87cURD_*#4DfTZ)+T",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base85",
|
||||
args: [null, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base85 (Standard (Ascii85)): UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "iIdZZK;0RJK:_%SOPth^iIdNVK:1\\NOPthc",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base85",
|
||||
args: [null, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base85 (Z85 (ZeroMQ)): Hello, World!",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "nm2QNz.92jz5PV8aP",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base85",
|
||||
args: ["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base85 (Standard): nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base85",
|
||||
args: [null, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base85 (Standard): Hello, World!",
|
||||
input: "87cURD_*#4DfTZ)+T",
|
||||
expectedOutput: "Hello, World!",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base85",
|
||||
args: [null, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base85 (Standard): UTF-8",
|
||||
input: "iIdZZK;0RJK:_%SOPth^iIdNVK:1\\NOPthc",
|
||||
expectedOutput: "ნუ პანიკას",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base85",
|
||||
args: [null, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
Loading…
Add table
Add a link
Reference in a new issue