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

Compare commits

..

29 Commits

Author SHA1 Message Date
n1474335
7061c05f77 8.6.1 2018-08-29 18:58:01 +00:00
n1474335
9b9a182f9f Merge branch 'klaxon1-feature/improve-parse-ip-range' 2018-08-29 18:57:08 +00:00
n1474335
2d9e7fcc6d Added full stop to operation description 2018-08-29 18:56:50 +00:00
n1474335
56946a66aa Merge branch 'feature/improve-parse-ip-range' of https://github.com/klaxon1/CyberChef into klaxon1-feature/improve-parse-ip-range 2018-08-29 18:48:29 +00:00
n1474335
c9242e32fe Auto-generated configs and modules are now cleaned when starting a new dev or prod task 2018-08-29 18:21:46 +00:00
n1474335
22e8883934 8.6.0 2018-08-29 18:04:55 +00:00
n1474335
552a18d89a Updated CHANGELOG 2018-08-29 18:04:49 +00:00
n1474335
6b725e9114 Merge branch 'GCHQ77703-master' 2018-08-29 18:00:06 +00:00
n1474335
415beaa0b0 Tidied up Geohash operations 2018-08-29 17:59:48 +00:00
n1474335
e9fe227ed7 Merge branch 'master' of https://github.com/GCHQ77703/CyberChef into GCHQ77703-master 2018-08-29 17:48:23 +00:00
n1474335
c1be109592 8.5.1 2018-08-29 17:36:05 +00:00
n1474335
88e603bbf1 Merge branch 'PenguinGeorge-cascadexor-new' 2018-08-29 17:35:13 +00:00
n1474335
c7b2095bb4 Updated package-lock.json 2018-08-29 17:34:47 +00:00
n1474335
7396117d89 Merge branch 'cascadexor-new' of https://github.com/PenguinGeorge/CyberChef into PenguinGeorge-cascadexor-new 2018-08-29 17:31:59 +00:00
Klaxon
2820660264 fix regex issues and ESlint errors and warnings
fix comment

fix ESlint errors and warnings

fix regex

add author
2018-08-28 23:07:53 +10:00
Klaxon
86145dbf67 add tests 2018-08-28 23:07:48 +10:00
Klaxon
135b17186e update description 2018-08-28 23:07:40 +10:00
Klaxon
ce494339ef add parse IPv6 list 2018-08-28 23:07:32 +10:00
Klaxon
dd5af7eb10 add parse IPv4 list 2018-08-28 23:07:04 +10:00
GCHQ 77703
91133172d5 Remove subdomain from Wikipedia 2018-08-26 18:51:52 +01:00
GCHQ 77703
001f3f30cd Remove multi-line operations 2018-08-26 18:06:02 +01:00
GCHQ 77703
a1b1059ad1 Revert package-lock.json changes 2018-08-26 17:39:33 +01:00
GCHQ 77703
69a0122fea Fix "From Geohash" test 2018-08-26 17:20:50 +01:00
GCHQ 77703
3d505b4248 Add ToGeohash and FromGeohash operations 2018-08-26 14:27:15 +01:00
George J
70d4e3394c Updated XOR to include Cascade scheme 2018-08-24 22:33:24 +01:00
n1474335
3905c01a0d 8.5.0 2018-08-24 01:07:56 +01:00
n1474335
2a49af1ec3 'To Braille' and 'From Braille' operations added. Closes #255 2018-08-24 01:07:51 +01:00
n1474335
3d4f54e8bc 8.4.3 2018-08-24 00:32:57 +01:00
n1474335
61f2f2d2e3 'Show Base64 offsets' operation show supports base64 input. Closes #276 2018-08-24 00:32:52 +01:00
20 changed files with 672 additions and 17 deletions

View File

@@ -1,6 +1,13 @@
# Changelog
All notable changes to CyberChef will be documented in this file.
### [8.6.0] - 2018-08-29
- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344]
### [8.5.0] - 2018-08-23
- 'To Braille' and 'From Braille' operations added [@n1474335] | [#255]
### [8.4.0] - 2018-08-23
- 'To Base85' and 'From Base85' operations added [@PenguinGeorge] | [#340]
@@ -41,6 +48,8 @@ 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.6.0]: https://github.com/gchq/CyberChef/releases/tag/v8.6.0
[8.5.0]: https://github.com/gchq/CyberChef/releases/tag/v8.5.0
[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
@@ -53,6 +62,7 @@ All notable changes to CyberChef will be documented in this file.
[@n1474335]: https://github.com/n1474335
[@d98762625]: https://github.com/d98762625
[@GCHQ77703]: https://github.com/GCHQ77703
[@artemisbot]: https://github.com/artemisbot
[@picapi]: https://github.com/picapi
[@Dachande663]: https://github.com/Dachande663
@@ -65,6 +75,7 @@ All notable changes to CyberChef will be documented in this file.
[#224]: https://github.com/gchq/CyberChef/pull/224
[#239]: https://github.com/gchq/CyberChef/pull/239
[#248]: https://github.com/gchq/CyberChef/pull/248
[#255]: https://github.com/gchq/CyberChef/issues/255
[#281]: https://github.com/gchq/CyberChef/pull/281
[#284]: https://github.com/gchq/CyberChef/pull/284
[#294]: https://github.com/gchq/CyberChef/pull/294
@@ -74,3 +85,4 @@ All notable changes to CyberChef will be documented in this file.
[#325]: https://github.com/gchq/CyberChef/pull/325
[#338]: https://github.com/gchq/CyberChef/pull/338
[#340]: https://github.com/gchq/CyberChef/pull/340
[#344]: https://github.com/gchq/CyberChef/pull/344

View File

@@ -22,7 +22,7 @@ module.exports = function (grunt) {
// Tasks
grunt.registerTask("dev",
"A persistent task which creates a development build whenever source files are modified.",
["clean:dev", "exec:generateConfig", "concurrent:dev"]);
["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"]);
grunt.registerTask("node",
"Compiles CyberChef into a single NodeJS module.",
@@ -38,7 +38,7 @@ module.exports = function (grunt) {
grunt.registerTask("prod",
"Creates a production-ready build. Use the --msg flag to add a compile message.",
["eslint", "clean:prod", "exec:generateConfig", "webpack:web", "inline", "chmod"]);
["eslint", "clean:prod", "clean:config", "exec:generateConfig", "webpack:web", "inline", "chmod"]);
grunt.registerTask("default",
"Lints the code base",

7
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "8.4.2",
"version": "8.6.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -7265,6 +7265,11 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
"ngeohash": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/ngeohash/-/ngeohash-0.6.0.tgz",
"integrity": "sha1-MpcT6ec9HxpG2SqrC5StuUUz9oc="
},
"nice-try": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "8.4.2",
"version": "8.6.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",
@@ -106,6 +106,7 @@
"loglevel-message-prefix": "^3.0.0",
"moment": "^2.22.2",
"moment-timezone": "^0.5.21",
"ngeohash": "^0.6.0",
"node-forge": "^0.7.5",
"node-md6": "^0.1.0",
"notepack.io": "^2.1.3",

View File

@@ -51,7 +51,9 @@
"Decode text",
"Swap endianness",
"To MessagePack",
"From MessagePack"
"From MessagePack",
"To Braille",
"From Braille"
]
},
{
@@ -287,7 +289,9 @@
"Adler-32 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum"
"TCP/IP Checksum",
"To Geohash",
"From Geohash"
]
},
{

View File

@@ -81,6 +81,7 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
return returnType === "string" ? "" : [];
}
alphabet = alphabet || "A-Za-z0-9+/=";
alphabet = Utils.expandAlphRange(alphabet).join("");
const output = [];

View File

@@ -25,6 +25,7 @@ export function bitOp (input, key, func, nullPreserving, scheme) {
for (let i = 0; i < input.length; i++) {
k = key[i % key.length];
if (scheme === "Cascade") k = input[i + 1] || 0;
o = input[i];
x = nullPreserving && (o === 0 || o === k) ? o : func(o, k);
result.push(x);

15
src/core/lib/Braille.mjs Normal file
View File

@@ -0,0 +1,15 @@
/**
* Braille resources.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
/**
* Braille lookup table.
*/
export const BRAILLE_LOOKUP = {
ascii: " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)=",
dot6: "⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿"
};

View File

@@ -3,6 +3,7 @@
*
* @author picapi
* @author n1474335 [n1474335@gmail.com]
* @author Klaxon [klaxon@veyr.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
@@ -109,8 +110,8 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) {
* @returns {string}
*/
export function ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList) {
const ip1 = strToIpv4(range[1]),
ip2 = strToIpv4(range[2]);
const ip1 = strToIpv4(range[0].split("-")[0].trim()),
ip2 = strToIpv4(range[0].split("-")[1].trim());
let output = "";
@@ -162,8 +163,8 @@ Total addresses in range: ${(((ip2 - ip1) >>> 0) + 1)}
* @returns {string}
*/
export function ipv6HyphenatedRange(range, includeNetworkInfo) {
const ip1 = strToIpv6(range[1]),
ip2 = strToIpv6(range[14]),
const ip1 = strToIpv6(range[0].split("-")[0].trim()),
ip2 = strToIpv6(range[0].split("-")[1].trim()),
total = new Array(128).fill();
let output = "",
@@ -188,6 +189,93 @@ export function ipv6HyphenatedRange(range, includeNetworkInfo) {
return output;
}
/**
* Parses a list of IPv4 addresses separated by a new line (\n) and displays information
* about it.
*
* @param {RegExp} list
* @param {boolean} includeNetworkInfo
* @param {boolean} enumerateAddresses
* @param {boolean} allowLargeList
* @returns {string}
*/
export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList) {
let ipv4List = match[0].split("\n");
ipv4List = ipv4List.filter(Boolean);
const ipv4CidrList = ipv4List.filter(function(a) {
return a.includes("/");
});
for (let i = 0; i < ipv4CidrList.length; i++) {
const network = strToIpv4(ipv4CidrList[i].split("/")[0]);
const cidrRange = parseInt(ipv4CidrList[i].split("/")[1], 10);
if (cidrRange < 0 || cidrRange > 31) {
return "IPv4 CIDR must be less than 32";
}
const mask = ~(0xFFFFFFFF >>> cidrRange),
cidrIp1 = network & mask,
cidrIp2 = cidrIp1 | ~mask;
ipv4List.splice(ipv4List.indexOf(ipv4CidrList[i]), 1);
ipv4List.push(ipv4ToStr(cidrIp1), ipv4ToStr(cidrIp2));
}
ipv4List = ipv4List.sort(ipv4Compare);
const ip1 = ipv4List[0];
const ip2 = ipv4List[ipv4List.length - 1];
const range = [ip1 + " - " + ip2];
return ipv4HyphenatedRange(range, includeNetworkInfo, enumerateAddresses, allowLargeList);
}
/**
* Parses a list of IPv6 addresses separated by a new line (\n) and displays information
* about it.
*
* @param {RegExp} list
* @param {boolean} includeNetworkInfo
* @returns {string}
*/
export function ipv6ListedRange(match, includeNetworkInfo) {
let ipv6List = match[0].split("\n");
ipv6List = ipv6List.filter(function(str) {
return str.trim();
});
for (let i =0; i < ipv6List.length; i++){
ipv6List[i] = ipv6List[i].trim();
}
const ipv6CidrList = ipv6List.filter(function(a) {
return a.includes("/");
});
for (let i = 0; i < ipv6CidrList.length; i++) {
const network = strToIpv6(ipv6CidrList[i].split("/")[0]);
const cidrRange = parseInt(ipv6CidrList[i].split("/")[1], 10);
if (cidrRange < 0 || cidrRange > 127) {
return "IPv6 CIDR must be less than 128";
}
const cidrIp1 = new Array(8),
cidrIp2 = new Array(8);
const mask = genIpv6Mask(cidrRange);
for (let j = 0; j < 8; j++) {
cidrIp1[j] = network[j] & mask[j];
cidrIp2[j] = cidrIp1[j] | (~mask[j] & 0x0000FFFF);
}
ipv6List.splice(ipv6List.indexOf(ipv6CidrList[i]), 1);
ipv6List.push(ipv6ToStr(cidrIp1), ipv6ToStr(cidrIp2));
}
ipv6List = ipv6List.sort(ipv6Compare);
const ip1 = ipv6List[0];
const ip2 = ipv6List[ipv6List.length - 1];
const range = [ip1 + " - " + ip2];
return ipv6HyphenatedRange(range, includeNetworkInfo);
}
/**
* Converts an IPv4 address from string format to numerical format.
*
@@ -391,6 +479,37 @@ export function genIpv6Mask(cidr) {
return mask;
}
/**
* Comparison operation for sorting of IPv4 addresses.
*
* @param {string} a
* @param {string} b
* @returns {number}
*/
export function ipv4Compare(a, b) {
return strToIpv4(a) - strToIpv4(b);
}
/**
* Comparison operation for sorting of IPv6 addresses.
*
* @param {string} a
* @param {string} b
* @returns {number}
*/
export function ipv6Compare(a, b) {
const a_ = strToIpv6(a),
b_ = strToIpv6(b);
for (let i = 0; i < a_.length; i++){
if (a_[i] !== b_[i]){
return a_[i] - b_[i];
}
}
return 0;
}
const _LARGE_RANGE_ERROR = "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges.";
/**

View File

@@ -0,0 +1,70 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import {BRAILLE_LOOKUP} from "../lib/Braille";
/**
* From Braille operation
*/
class FromBraille extends Operation {
/**
* FromBraille constructor
*/
constructor() {
super();
this.name = "From Braille";
this.module = "Default";
this.description = "Converts six-dot braille symbols to text.";
this.infoURL = "https://wikipedia.org/wiki/Braille";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return input.split("").map(b => {
const idx = BRAILLE_LOOKUP.dot6.indexOf(b);
return idx < 0 ? b : BRAILLE_LOOKUP.ascii[idx];
}).join("");
}
/**
* Highlight From Braille
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlight(pos, args) {
return pos;
}
/**
* Highlight From Braille in reverse
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlightReverse(pos, args) {
return pos;
}
}
export default FromBraille;

View File

@@ -0,0 +1,44 @@
/**
* @author gchq77703 []
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import geohash from "ngeohash";
/**
* From Geohash operation
*/
class FromGeohash extends Operation {
/**
* FromGeohash constructor
*/
constructor() {
super();
this.name = "From Geohash";
this.module = "Hashing";
this.description = "Converts Geohash strings into Lat/Long coordinates. For example, <code>ww8p1r4t8</code> becomes <code>37.8324,112.5584</code>.";
this.infoURL = "https://wikipedia.org/wiki/Geohash";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return input.split("\n").map(line => {
const coords = geohash.decode(line);
return [coords.latitude, coords.longitude].join(",");
}).join("\n");
}
}
export default FromGeohash;

View File

@@ -1,12 +1,13 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @author Klaxon [klaxon@veyr.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import {ipv4CidrRange, ipv4HyphenatedRange, ipv6CidrRange, ipv6HyphenatedRange} from "../lib/IP";
import {ipv4CidrRange, ipv4HyphenatedRange, ipv4ListedRange, ipv6CidrRange, ipv6HyphenatedRange, ipv6ListedRange} from "../lib/IP";
/**
* Parse IP range operation
@@ -21,7 +22,7 @@ class ParseIPRange extends Operation {
this.name = "Parse IP range";
this.module = "JSBN";
this.description = "Given a CIDR range (e.g. <code>10.0.0.0/24</code>) or a hyphenated range (e.g. <code>10.0.0.0 - 10.0.1.0</code>), this operation provides network information and enumerates all IP addresses in the range.<br><br>IPv6 is supported but will not be enumerated.";
this.description = "Given a CIDR range (e.g. <code>10.0.0.0/24</code>), hyphenated range (e.g. <code>10.0.0.0 - 10.0.1.0</code>), or a list of IPs and/or CIDR ranges (separated by a new line), this operation provides network information and enumerates all IP addresses in the range.<br><br>IPv6 is supported but will not be enumerated.";
this.infoURL = "https://wikipedia.org/wiki/Subnetwork";
this.inputType = "string";
this.outputType = "string";
@@ -59,18 +60,24 @@ class ParseIPRange extends Operation {
// Check what type of input we are looking at
const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))+\s*$/,
ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i,
ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i;
ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
ipv6ListRegex = /^\s*((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))+\s*$/i;
let match;
if ((match = ipv4CidrRegex.exec(input))) {
return ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList);
} else if ((match = ipv4RangeRegex.exec(input))) {
return ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList);
} else if ((match = ipv4ListRegex.exec(input))) {
return ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList);
} else if ((match = ipv6CidrRegex.exec(input))) {
return ipv6CidrRange(match, includeNetworkInfo);
} else if ((match = ipv6RangeRegex.exec(input))) {
return ipv6HyphenatedRange(match, includeNetworkInfo);
} else if ((match = ipv6ListRegex.exec(input))) {
return ipv6ListedRange(match, includeNetworkInfo);
} else {
throw new OperationError("Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.");
}

View File

@@ -36,6 +36,11 @@ class ShowBase64Offsets extends Operation {
name: "Show variable chars and padding",
type: "boolean",
value: true
},
{
name: "Input format",
type: "option",
value: ["Raw", "Base64"]
}
];
}
@@ -46,7 +51,11 @@ class ShowBase64Offsets extends Operation {
* @returns {html}
*/
run(input, args) {
const [alphabet, showVariable] = args;
const [alphabet, showVariable, format] = args;
if (format === "Base64") {
input = fromBase64(Utils.byteArrayToUtf8(input), null, "byteArray");
}
let offset0 = toBase64(input, alphabet),
offset1 = toBase64([0].concat(input), alphabet),

View File

@@ -0,0 +1,70 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import {BRAILLE_LOOKUP} from "../lib/Braille";
/**
* To Braille operation
*/
class ToBraille extends Operation {
/**
* ToBraille constructor
*/
constructor() {
super();
this.name = "To Braille";
this.module = "Default";
this.description = "Converts text to six-dot braille symbols.";
this.infoURL = "https://wikipedia.org/wiki/Braille";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return input.split("").map(c => {
const idx = BRAILLE_LOOKUP.ascii.indexOf(c.toUpperCase());
return idx < 0 ? c : BRAILLE_LOOKUP.dot6[idx];
}).join("");
}
/**
* Highlight To Braille
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlight(pos, args) {
return pos;
}
/**
* Highlight To Braille in reverse
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlightReverse(pos, args) {
return pos;
}
}
export default ToBraille;

View File

@@ -0,0 +1,53 @@
/**
* @author gchq77703 []
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import geohash from "ngeohash";
/**
* To Geohash operation
*/
class ToGeohash extends Operation {
/**
* ToGeohash constructor
*/
constructor() {
super();
this.name = "To Geohash";
this.module = "Hashing";
this.description = "Converts Lat/Long coordinates into a Geohash string. For example, <code>37.8324,112.5584</code> becomes <code>ww8p1r4t8</code>.";
this.infoURL = "https://wikipedia.org/wiki/Geohash";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Precision",
type: "number",
value: 9
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [precision] = args;
return input.split("\n").map(line => {
line = line.replace(/ /g, "");
if (line === "") return "";
return geohash.encode(...line.split(",").map(num => parseFloat(num)), precision);
}).join("\n");
}
}
export default ToGeohash;

View File

@@ -21,7 +21,7 @@ class XOR extends Operation {
this.name = "XOR";
this.module = "Default";
this.description = "XOR the input with the given key.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li></ul>";
this.description = "XOR the input with the given key.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li><li>Cascade - key is set to the input byte shifted by one</li></ul>";
this.infoURL = "https://wikipedia.org/wiki/XOR";
this.inputType = "byteArray";
this.outputType = "byteArray";
@@ -35,7 +35,7 @@ class XOR extends Operation {
{
"name": "Scheme",
"type": "option",
"value": ["Standard", "Input differential", "Output differential"]
"value": ["Standard", "Input differential", "Output differential", "Cascade"]
},
{
"name": "Null preserving",

View File

@@ -64,6 +64,9 @@ import "./tests/operations/SetUnion";
import "./tests/operations/SymmetricDifference";
import "./tests/operations/TranslateDateTimeFormat";
import "./tests/operations/Magic";
import "./tests/operations/ToGeohash.mjs";
import "./tests/operations/FromGeohash.mjs";
import "./tests/operations/ParseIPRange";
let allTestsPassing = true;
const testStatusCounts = {
@@ -142,4 +145,3 @@ TestRegister.runTests()
process.exit(allTestsPassing ? 0 : 1);
});

View File

@@ -0,0 +1,55 @@
/**
* To Geohash tests
*
* @author gchq77703
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister";
TestRegister.addTests([
{
name: "From Geohash",
input: "ww8p1r4t8",
expectedOutput: "37.83238649368286,112.55838632583618",
recipeConfig: [
{
op: "From Geohash",
args: [],
},
],
},
{
name: "From Geohash",
input: "ww8p1r",
expectedOutput: "37.83416748046875,112.5604248046875",
recipeConfig: [
{
op: "From Geohash",
args: [],
},
],
},
{
name: "From Geohash",
input: "ww8",
expectedOutput: "37.265625,113.203125",
recipeConfig: [
{
op: "From Geohash",
args: [],
},
],
},
{
name: "From Geohash",
input: "w",
expectedOutput: "22.5,112.5",
recipeConfig: [
{
op: "From Geohash",
args: [],
},
],
},
]);

View File

@@ -0,0 +1,132 @@
/**
* Parse IP Range tests.
*
* @author Klaxon [klaxon@veyr.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister";
TestRegister.addTests([
{
name: "Parse IPv4 CIDR",
input: "10.0.0.0/30",
expectedOutput: "Network: 10.0.0.0\nCIDR: 30\nMask: 255.255.255.252\nRange: 10.0.0.0 - 10.0.0.3\nTotal addresses in range: 4\n\n10.0.0.0\n10.0.0.1\n10.0.0.2\n10.0.0.3",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "Parse IPv4 hyphenated",
input: "10.0.0.0 - 10.0.0.3",
expectedOutput: "Minimum subnet required to hold this range:\n\tNetwork: 10.0.0.0\n\tCIDR: 30\n\tMask: 255.255.255.252\n\tSubnet range: 10.0.0.0 - 10.0.0.3\n\tTotal addresses in subnet: 4\n\nRange: 10.0.0.0 - 10.0.0.3\nTotal addresses in range: 4\n\n10.0.0.0\n10.0.0.1\n10.0.0.2\n10.0.0.3",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "Parse IPv4 list",
input: "10.0.0.8\n10.0.0.5/30\n10.0.0.1\n10.0.0.3",
expectedOutput: "Minimum subnet required to hold this range:\n\tNetwork: 10.0.0.0\n\tCIDR: 28\n\tMask: 255.255.255.240\n\tSubnet range: 10.0.0.0 - 10.0.0.15\n\tTotal addresses in subnet: 16\n\nRange: 10.0.0.1 - 10.0.0.8\nTotal addresses in range: 8\n\n10.0.0.1\n10.0.0.2\n10.0.0.3\n10.0.0.4\n10.0.0.5\n10.0.0.6\n10.0.0.7\n10.0.0.8",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "Parse IPv6 CIDR - full",
input: "2404:6800:4001:0000:0000:0000:0000:0000/48",
expectedOutput: "Network: 2404:6800:4001:0000:0000:0000:0000:0000\nShorthand: 2404:6800:4001::\nCIDR: 48\nMask: ffff:ffff:ffff:0000:0000:0000:0000:0000\nRange: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "Parse IPv6 CIDR - collapsed",
input: "2404:6800:4001::/48",
expectedOutput: "Network: 2404:6800:4001:0000:0000:0000:0000:0000\nShorthand: 2404:6800:4001::\nCIDR: 48\nMask: ffff:ffff:ffff:0000:0000:0000:0000:0000\nRange: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "Parse IPv6 hyphenated",
input: "2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff",
expectedOutput: "Range: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nShorthand range: 2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "Parse IPv6 list",
input: "2404:6800:4001:ffff:ffff:ffff:ffff:ffff\n2404:6800:4001::ffff\n2404:6800:4001:ffff:ffff::1111\n2404:6800:4001::/64",
expectedOutput: "Range: 2404:6800:4001:0000:0000:0000:0000:0000 - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nShorthand range: 2404:6800:4001:: - 2404:6800:4001:ffff:ffff:ffff:ffff:ffff\nTotal addresses in range: 1.2089258196146292e+24\n\n",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "IPv4 subnet out of range error",
input: "10.1.1.1/34",
expectedOutput: "IPv4 CIDR must be less than 32",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "invalid IPv4 address error",
input: "444.1.1.1/30",
expectedOutput: "Block out of range.",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "IPv6 subnet out of range error",
input: "2404:6800:4001::/129",
expectedOutput: "IPv6 CIDR must be less than 128",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
{
name: "invalid IPv6 address error",
input: "2404:6800:4001:/12",
expectedOutput: "Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.",
recipeConfig: [
{
"op": "Parse IP range",
"args": [true, true, false]
},
],
},
]);

View File

@@ -0,0 +1,55 @@
/**
* To Geohash tests
*
* @author gchq77703
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister";
TestRegister.addTests([
{
name: "To Geohash",
input: "37.8324,112.5584",
expectedOutput: "ww8p1r4t8",
recipeConfig: [
{
op: "To Geohash",
args: [9],
},
],
},
{
name: "To Geohash",
input: "37.9324,-112.2584",
expectedOutput: "9w8pv3ruj",
recipeConfig: [
{
op: "To Geohash",
args: [9],
},
],
},
{
name: "To Geohash",
input: "37.8324,112.5584",
expectedOutput: "ww8",
recipeConfig: [
{
op: "To Geohash",
args: [3],
},
],
},
{
name: "To Geohash",
input: "37.9324,-112.2584",
expectedOutput: "9w8pv3rujxy5b99",
recipeConfig: [
{
op: "To Geohash",
args: [15],
},
],
},
]);