mirror of
https://github.com/gchq/CyberChef.git
synced 2026-02-25 11:11:43 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00058bd5c7 | ||
|
|
383fe50fc9 | ||
|
|
e4fdadc573 | ||
|
|
032f8808ef | ||
|
|
10cf0d13c2 | ||
|
|
6c9fea97ef | ||
|
|
4c2d612bdd | ||
|
|
8e9fece77d | ||
|
|
c818370123 | ||
|
|
2d9e8773f5 |
@@ -1,6 +1,9 @@
|
||||
# Changelog
|
||||
All notable changes to CyberChef will be documented in this file.
|
||||
|
||||
### [8.4.0] - 2018-08-23
|
||||
- 'To Base85' and 'From Base85' operations added [@PenguinGeorge] | [#340]
|
||||
|
||||
### [8.3.0] - 2018-08-21
|
||||
- 'To MessagePack' and 'From MessagePack' operations added [@artemisbot] | [#338]
|
||||
|
||||
@@ -38,6 +41,7 @@ All notable changes to CyberChef will be documented in this file.
|
||||
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
||||
|
||||
|
||||
[8.4.0]: https://github.com/gchq/CyberChef/releases/tag/v8.4.0
|
||||
[8.3.0]: https://github.com/gchq/CyberChef/releases/tag/v8.3.0
|
||||
[8.2.0]: https://github.com/gchq/CyberChef/releases/tag/v8.2.0
|
||||
[8.1.0]: https://github.com/gchq/CyberChef/releases/tag/v8.1.0
|
||||
@@ -69,3 +73,4 @@ All notable changes to CyberChef will be documented in this file.
|
||||
[#311]: https://github.com/gchq/CyberChef/pull/311
|
||||
[#325]: https://github.com/gchq/CyberChef/pull/325
|
||||
[#338]: https://github.com/gchq/CyberChef/pull/338
|
||||
[#340]: https://github.com/gchq/CyberChef/pull/340
|
||||
|
||||
24
package-lock.json
generated
24
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "8.3.1",
|
||||
"version": "8.4.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -4197,14 +4197,12 @@
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -4219,20 +4217,17 @@
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@@ -4349,8 +4344,7 @@
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@@ -4362,7 +4356,6 @@
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@@ -4377,7 +4370,6 @@
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@@ -4489,8 +4481,7 @@
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@@ -4623,7 +4614,6 @@
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "8.3.1",
|
||||
"version": "8.4.2",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
"From Base32",
|
||||
"To Base58",
|
||||
"From Base58",
|
||||
"To Base85",
|
||||
"From Base85",
|
||||
"To Base",
|
||||
"From Base",
|
||||
"To BCD",
|
||||
|
||||
45
src/core/lib/Base85.mjs
Normal file
45
src/core/lib/Base85.mjs
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Base85 resources.
|
||||
*
|
||||
* @author PenguinGeorge [george@penguingeorge.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base85 alphabet options.
|
||||
*/
|
||||
export const ALPHABET_OPTIONS = [
|
||||
{
|
||||
name: "Standard",
|
||||
value: "!-u",
|
||||
},
|
||||
{
|
||||
name: "Z85 (ZeroMQ)",
|
||||
value: "0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#",
|
||||
},
|
||||
{
|
||||
name: "IPv6",
|
||||
value: "0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|~}",
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the alphabet, when given the alphabet.
|
||||
*
|
||||
* @param {string} alphabet
|
||||
* @returns {string}
|
||||
*/
|
||||
export function alphabetName(alphabet) {
|
||||
alphabet = alphabet.replace("'", "'");
|
||||
alphabet = alphabet.replace("\"", """);
|
||||
alphabet = alphabet.replace("\\", "\");
|
||||
let name;
|
||||
|
||||
ALPHABET_OPTIONS.forEach(function(a) {
|
||||
if (escape(alphabet) === escape(a.value)) name = a.name;
|
||||
});
|
||||
|
||||
return name;
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Drop bytes operation
|
||||
@@ -20,7 +19,7 @@ class DropBytes extends Operation {
|
||||
|
||||
this.name = "Drop bytes";
|
||||
this.module = "Default";
|
||||
this.description = "Cuts a slice of the specified number of bytes out of the data.";
|
||||
this.description = "Cuts a slice of the specified number of bytes out of the data. Negative values are allowed.";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [
|
||||
@@ -50,14 +49,25 @@ class DropBytes extends Operation {
|
||||
* @throws {OperationError} if invalid input
|
||||
*/
|
||||
run(input, args) {
|
||||
const start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw new OperationError("Error: Invalid value");
|
||||
let start = args[0],
|
||||
length = args[1];
|
||||
const applyToEachLine = args[2];
|
||||
|
||||
if (!applyToEachLine) {
|
||||
if (start < 0) { // Take from the end
|
||||
start = input.byteLength + start;
|
||||
}
|
||||
|
||||
if (length < 0) { // Flip start point
|
||||
start = start + length;
|
||||
if (start < 0) {
|
||||
start = input.byteLength + start;
|
||||
length = start - length;
|
||||
} else {
|
||||
length = -length;
|
||||
}
|
||||
}
|
||||
|
||||
const left = input.slice(0, start),
|
||||
right = input.slice(start + length, input.byteLength);
|
||||
const result = new Uint8Array(left.byteLength + right.byteLength);
|
||||
@@ -82,10 +92,28 @@ class DropBytes extends Operation {
|
||||
}
|
||||
lines.push(line);
|
||||
|
||||
let output = [];
|
||||
let output = [],
|
||||
s = start,
|
||||
l = length;
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length)));
|
||||
if (s < 0) { // Take from the end
|
||||
s = lines[i].length + s;
|
||||
}
|
||||
|
||||
if (l < 0) { // Flip start point
|
||||
s = s + l;
|
||||
if (s < 0) {
|
||||
s = lines[i].length + s;
|
||||
l = s - l;
|
||||
} else {
|
||||
l = -l;
|
||||
}
|
||||
}
|
||||
|
||||
output = output.concat(lines[i].slice(0, s).concat(lines[i].slice(s+l, lines[i].length)));
|
||||
output.push(0x0a);
|
||||
s = start;
|
||||
l = length;
|
||||
}
|
||||
return new Uint8Array(output.slice(0, output.length-1)).buffer;
|
||||
}
|
||||
|
||||
105
src/core/operations/FromBase85.mjs
Normal file
105
src/core/operations/FromBase85.mjs
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @author PenguinGeorge [george@penguingeorge.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Utils from "../Utils";
|
||||
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85";
|
||||
|
||||
/**
|
||||
* From Base85 operation
|
||||
*/
|
||||
class FromBase85 extends Operation {
|
||||
|
||||
/**
|
||||
* From Base85 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Base85";
|
||||
this.module = "Default";
|
||||
this.description = "Base85 (also called Ascii85) 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.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Ascii85";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "editableOption",
|
||||
value: ALPHABET_OPTIONS
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
||||
encoding = alphabetName(alphabet),
|
||||
result = [];
|
||||
|
||||
if (alphabet.length !== 85 ||
|
||||
[].unique.call(alphabet).length !== 85) {
|
||||
throw new OperationError("Alphabet must be of length 85");
|
||||
}
|
||||
|
||||
if (input.length === 0) return [];
|
||||
|
||||
const 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) => {
|
||||
const 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromBase85;
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* Take bytes operation
|
||||
@@ -20,7 +19,7 @@ class TakeBytes extends Operation {
|
||||
|
||||
this.name = "Take bytes";
|
||||
this.module = "Default";
|
||||
this.description = "Takes a slice of the specified number of bytes from the data.";
|
||||
this.description = "Takes a slice of the specified number of bytes from the data. Negative values are allowed.";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [
|
||||
@@ -50,15 +49,27 @@ class TakeBytes extends Operation {
|
||||
* @throws {OperationError} if invalid value
|
||||
*/
|
||||
run(input, args) {
|
||||
const start = args[0],
|
||||
length = args[1],
|
||||
applyToEachLine = args[2];
|
||||
let start = args[0],
|
||||
length = args[1];
|
||||
const applyToEachLine = args[2];
|
||||
|
||||
if (start < 0 || length < 0)
|
||||
throw new OperationError("Error: Invalid value");
|
||||
if (!applyToEachLine) {
|
||||
if (start < 0) { // Take from the end
|
||||
start = input.byteLength + start;
|
||||
}
|
||||
|
||||
if (length < 0) { // Flip start point
|
||||
start = start + length;
|
||||
if (start < 0) {
|
||||
start = input.byteLength + start;
|
||||
length = start - length;
|
||||
} else {
|
||||
length = -length;
|
||||
}
|
||||
}
|
||||
|
||||
if (!applyToEachLine)
|
||||
return input.slice(start, start+length);
|
||||
}
|
||||
|
||||
// Split input into lines
|
||||
const data = new Uint8Array(input);
|
||||
@@ -77,9 +88,26 @@ class TakeBytes extends Operation {
|
||||
lines.push(line);
|
||||
|
||||
let output = [];
|
||||
let s = start,
|
||||
l = length;
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
output = output.concat(lines[i].slice(start, start+length));
|
||||
if (s < 0) { // Take from the end
|
||||
s = lines[i].length + s;
|
||||
}
|
||||
|
||||
if (l < 0) { // Flip start point
|
||||
s = s + l;
|
||||
if (s < 0) {
|
||||
s = lines[i].length + s;
|
||||
l = s - l;
|
||||
} else {
|
||||
l = -l;
|
||||
}
|
||||
}
|
||||
output = output.concat(lines[i].slice(s, s+l));
|
||||
output.push(0x0a);
|
||||
s = start;
|
||||
l = length;
|
||||
}
|
||||
return new Uint8Array(output.slice(0, output.length-1)).buffer;
|
||||
}
|
||||
|
||||
93
src/core/operations/ToBase85.mjs
Normal file
93
src/core/operations/ToBase85.mjs
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @author PenguinGeorge [george@penguingeorge.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Utils from "../Utils";
|
||||
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85";
|
||||
|
||||
/**
|
||||
* To Base85 operation
|
||||
*/
|
||||
class ToBase85 extends Operation {
|
||||
|
||||
/**
|
||||
* To Base85 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Base85";
|
||||
this.module = "Default";
|
||||
this.description = "Base85 (also called Ascii85) 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.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Ascii85";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "editableOption",
|
||||
value: ALPHABET_OPTIONS
|
||||
},
|
||||
{
|
||||
name: "Include delimeter",
|
||||
type: "boolean",
|
||||
value: false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
||||
encoding = alphabetName(alphabet),
|
||||
includeDelim = args[1];
|
||||
let result = "";
|
||||
|
||||
if (alphabet.length !== 85 ||
|
||||
[].unique.call(alphabet).length !== 85) {
|
||||
throw new OperationError("Error: Alphabet must be of length 85");
|
||||
}
|
||||
|
||||
if (input.length === 0) return "";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return includeDelim ? `<~${result}~>` : result;
|
||||
}
|
||||
}
|
||||
|
||||
export default ToBase85;
|
||||
Reference in New Issue
Block a user