mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2325306db | ||
|
|
dfe31980b7 | ||
|
|
9734b78aeb | ||
|
|
4ee0800990 | ||
|
|
387008bd9c | ||
|
|
bf24547202 | ||
|
|
c2f6b8df66 | ||
|
|
d0e428b728 | ||
|
|
ae5128a33a | ||
|
|
ed25017e2d | ||
|
|
e5b2b84073 | ||
|
|
1953d9a4c8 | ||
|
|
b3113c109b | ||
|
|
8c3569ea63 | ||
|
|
ae28d476de | ||
|
|
01c4cfdc8d | ||
|
|
8c6c3a1c01 | ||
|
|
f367c1f78b | ||
|
|
13d87d397d | ||
|
|
ed2c886359 | ||
|
|
6337e84708 | ||
|
|
ae20a951be | ||
|
|
866dd546c8 | ||
|
|
2070e1a96b | ||
|
|
952f49e2e1 | ||
|
|
f600571c6d | ||
|
|
5d4c7244e1 | ||
|
|
b6bdcaa71f | ||
|
|
c8eab5d218 | ||
|
|
8ab56a29ac | ||
|
|
973b5f3f5c | ||
|
|
076a1f97c2 | ||
|
|
d96ef37d81 | ||
|
|
56f8302402 | ||
|
|
97e6a7cbd8 | ||
|
|
d89d79116c | ||
|
|
367d79e820 | ||
|
|
283d7f2159 | ||
|
|
dacb3ef6c3 | ||
|
|
22454ae842 | ||
|
|
79b9b63982 | ||
|
|
2f68bf30a4 | ||
|
|
50f078cc45 | ||
|
|
47a410d6ab | ||
|
|
31cbf8cccc | ||
|
|
88bd321e3e | ||
|
|
b4a586c0b9 | ||
|
|
63593f1b6c | ||
|
|
dcff8971e8 | ||
|
|
3f7059a235 | ||
|
|
71c743ff5a | ||
|
|
15fbe5a459 | ||
|
|
cd47394709 | ||
|
|
6f4ee8b7b6 | ||
|
|
8c5d05b611 | ||
|
|
3bdcf4d851 | ||
|
|
1d1c69ca51 | ||
|
|
c4c679021d | ||
|
|
c16d13e2c9 | ||
|
|
97613eb3c7 | ||
|
|
a946d04a72 | ||
|
|
cc35ec82eb | ||
|
|
d6604e0008 | ||
|
|
b9e63efc37 | ||
|
|
b458707921 | ||
|
|
6ec52c6cd2 | ||
|
|
79d7a5dd87 | ||
|
|
1653d0212a | ||
|
|
c378bcb00b | ||
|
|
215e7a5f5d | ||
|
|
6b686681d5 | ||
|
|
20ea050728 | ||
|
|
4b6132a2d7 | ||
|
|
4cf80e3ebb | ||
|
|
045747f543 | ||
|
|
b10c5e3256 | ||
|
|
69df2e4183 |
19
.babelrc
19
.babelrc
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"chrome": 40,
|
||||
"firefox": 35,
|
||||
"edge": 14,
|
||||
"node": "6.5"
|
||||
},
|
||||
"modules": false,
|
||||
"useBuiltIns": "entry"
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
["babel-plugin-transform-builtin-extend", {
|
||||
"globals": ["Error"]
|
||||
}]
|
||||
]
|
||||
}
|
||||
47
CHANGELOG.md
47
CHANGELOG.md
@@ -1,5 +1,24 @@
|
||||
# Changelog
|
||||
All notable changes to CyberChef will be documented in this file.
|
||||
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
|
||||
|
||||
|
||||
### [8.17.0] - 2018-12-25
|
||||
- 'Generate QR Code' and 'Parse QR Code' operations added [@j433866] | [#448]
|
||||
|
||||
### [8.16.0] - 2018-12-19
|
||||
- 'Play Media' operation added [@anthony-arnold] | [#446]
|
||||
|
||||
### [8.15.0] - 2018-12-18
|
||||
- 'Text Encoding Brute Force' operation added [@Cynser] | [#439]
|
||||
|
||||
### [8.14.0] - 2018-12-18
|
||||
- 'To Base62' and 'From Base62' operations added [@tcode2k16] | [#443]
|
||||
|
||||
### [8.13.0] - 2018-12-15
|
||||
- 'A1Z26 Cipher Encode' and 'A1Z26 Cipher Decode' operations added [@jarmovanlenthe] | [#441]
|
||||
|
||||
### [8.12.0] - 2018-11-21
|
||||
- 'Citrix CTX1 Encode' and 'Citrix CTX1 Decode' operations added [@bwhitn] | [#428]
|
||||
|
||||
### [8.11.0] - 2018-11-13
|
||||
- 'CSV to JSON' and 'JSON to CSV' operations added [@n1474335] | [#277]
|
||||
@@ -17,7 +36,7 @@ All notable changes to CyberChef will be documented in this file.
|
||||
- 'JWT Sign', 'JWT Verify' and 'JWT Decode' operations added [@GCHQ77703] | [#348]
|
||||
|
||||
### [8.6.0] - 2018-08-29
|
||||
- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344]
|
||||
- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344]
|
||||
|
||||
### [8.5.0] - 2018-08-23
|
||||
- 'To Braille' and 'From Braille' operations added [@n1474335] | [#255]
|
||||
@@ -52,7 +71,7 @@ All notable changes to CyberChef will be documented in this file.
|
||||
- Added support for loading, processing and downloading files up to 500MB [@n1474335] | [#224]
|
||||
|
||||
## [6.0.0] - 2017-09-19
|
||||
- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and allowing long-running operations to be cancelled [@n1474335] | [#173]
|
||||
- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and to allow long-running operations to be cancelled [@n1474335] | [#173]
|
||||
- Module system created so that operations relying on large libraries can be downloaded separately as required, reducing the initial loading time for the app [@n1474335] | [#173]
|
||||
|
||||
## [5.0.0] - 2017-03-30
|
||||
@@ -62,6 +81,16 @@ 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.17.0]: https://github.com/gchq/CyberChef/releases/tag/v8.17.0
|
||||
[8.16.0]: https://github.com/gchq/CyberChef/releases/tag/v8.16.0
|
||||
[8.15.0]: https://github.com/gchq/CyberChef/releases/tag/v8.15.0
|
||||
[8.14.0]: https://github.com/gchq/CyberChef/releases/tag/v8.14.0
|
||||
[8.13.0]: https://github.com/gchq/CyberChef/releases/tag/v8.13.0
|
||||
[8.12.0]: https://github.com/gchq/CyberChef/releases/tag/v8.12.0
|
||||
[8.11.0]: https://github.com/gchq/CyberChef/releases/tag/v8.11.0
|
||||
[8.10.0]: https://github.com/gchq/CyberChef/releases/tag/v8.10.0
|
||||
[8.9.0]: https://github.com/gchq/CyberChef/releases/tag/v8.9.0
|
||||
[8.8.0]: https://github.com/gchq/CyberChef/releases/tag/v8.8.0
|
||||
[8.7.0]: https://github.com/gchq/CyberChef/releases/tag/v8.7.0
|
||||
[8.6.0]: https://github.com/gchq/CyberChef/releases/tag/v8.6.0
|
||||
@@ -78,6 +107,7 @@ All notable changes to CyberChef will be documented in this file.
|
||||
|
||||
[@n1474335]: https://github.com/n1474335
|
||||
[@d98762625]: https://github.com/d98762625
|
||||
[@j433866]: https://github.com/j433866
|
||||
[@GCHQ77703]: https://github.com/GCHQ77703
|
||||
[@artemisbot]: https://github.com/artemisbot
|
||||
[@picapi]: https://github.com/picapi
|
||||
@@ -87,6 +117,11 @@ All notable changes to CyberChef will be documented in this file.
|
||||
[@PenguinGeorge]: https://github.com/PenguinGeorge
|
||||
[@arnydo]: https://github.com/arnydo
|
||||
[@klaxon1]: https://github.com/klaxon1
|
||||
[@bwhitn]: https://github.com/bwhitn
|
||||
[@jarmovanlenthe]: https://github.com/jarmovanlenthe
|
||||
[@tcode2k16]: https://github.com/tcode2k16
|
||||
[@Cynser]: https://github.com/Cynser
|
||||
[@anthony-arnold]: https://github.com/anthony-arnold
|
||||
|
||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||
@@ -109,3 +144,9 @@ All notable changes to CyberChef will be documented in this file.
|
||||
[#351]: https://github.com/gchq/CyberChef/pull/351
|
||||
[#387]: https://github.com/gchq/CyberChef/pull/387
|
||||
[#394]: https://github.com/gchq/CyberChef/pull/394
|
||||
[#428]: https://github.com/gchq/CyberChef/pull/428
|
||||
[#439]: https://github.com/gchq/CyberChef/pull/439
|
||||
[#441]: https://github.com/gchq/CyberChef/pull/441
|
||||
[#443]: https://github.com/gchq/CyberChef/pull/443
|
||||
[#446]: https://github.com/gchq/CyberChef/pull/446
|
||||
[#448]: https://github.com/gchq/CyberChef/pull/448
|
||||
|
||||
@@ -143,7 +143,7 @@ module.exports = function (grunt) {
|
||||
options: {
|
||||
configFile: "./.eslintrc.json"
|
||||
},
|
||||
configs: ["Gruntfile.js"],
|
||||
configs: ["*.js"],
|
||||
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
|
||||
web: ["src/web/**/*.{js,mjs}"],
|
||||
node: ["src/node/**/*.{js,mjs}"],
|
||||
|
||||
23
babel.config.js
Normal file
23
babel.config.js
Normal file
@@ -0,0 +1,23 @@
|
||||
module.exports = function(api) {
|
||||
api.cache.forever();
|
||||
|
||||
return {
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"chrome": 40,
|
||||
"firefox": 35,
|
||||
"edge": 14,
|
||||
"node": "6.5"
|
||||
},
|
||||
"modules": false,
|
||||
"useBuiltIns": "entry"
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
["babel-plugin-transform-builtin-extend", {
|
||||
"globals": ["Error"]
|
||||
}]
|
||||
]
|
||||
};
|
||||
};
|
||||
2920
package-lock.json
generated
2920
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "8.11.0",
|
||||
"version": "8.17.0",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -92,6 +92,7 @@
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^2.0.0-rc.4",
|
||||
"highlight.js": "^9.13.1",
|
||||
"jimp": "^0.6.0",
|
||||
"jquery": "^3.3.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
@@ -99,6 +100,7 @@
|
||||
"jsesc": "^2.5.1",
|
||||
"jsonpath": "^1.0.0",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"jsqr": "^1.1.1",
|
||||
"jsrsasign": "8.0.12",
|
||||
"kbpgp": "^2.0.82",
|
||||
"lodash": "^4.17.11",
|
||||
@@ -113,6 +115,7 @@
|
||||
"nwmatcher": "^1.4.4",
|
||||
"otp": "^0.1.3",
|
||||
"popper.js": "^1.14.4",
|
||||
"qr-image": "^3.2.0",
|
||||
"scryptsy": "^2.0.0",
|
||||
"snackbarjs": "^1.1.0",
|
||||
"sortablejs": "^1.7.0",
|
||||
|
||||
@@ -25,6 +25,7 @@ class Ingredient {
|
||||
this.hint = "";
|
||||
this.toggleValues = [];
|
||||
this.target = null;
|
||||
this.defaultIndex = 0;
|
||||
|
||||
if (ingredientConfig) {
|
||||
this._parseConfig(ingredientConfig);
|
||||
@@ -46,6 +47,7 @@ class Ingredient {
|
||||
this.hint = ingredientConfig.hint || false;
|
||||
this.toggleValues = ingredientConfig.toggleValues;
|
||||
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
||||
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@ class Operation {
|
||||
if (ing.hint) conf.hint = ing.hint;
|
||||
if (ing.disabled) conf.disabled = ing.disabled;
|
||||
if (ing.target) conf.target = ing.target;
|
||||
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
||||
return conf;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
"From Base32",
|
||||
"To Base58",
|
||||
"From Base58",
|
||||
"To Base62",
|
||||
"From Base62",
|
||||
"To Base85",
|
||||
"From Base85",
|
||||
"To Base",
|
||||
@@ -49,6 +51,7 @@
|
||||
"Change IP format",
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Text Encoding Brute Force",
|
||||
"Swap endianness",
|
||||
"To MessagePack",
|
||||
"From MessagePack",
|
||||
@@ -86,6 +89,8 @@
|
||||
"Bifid Cipher Decode",
|
||||
"Affine Cipher Encode",
|
||||
"Affine Cipher Decode",
|
||||
"A1Z26 Cipher Encode",
|
||||
"A1Z26 Cipher Decode",
|
||||
"Atbash Cipher",
|
||||
"Substitute",
|
||||
"Derive PBKDF2 key",
|
||||
@@ -95,6 +100,8 @@
|
||||
"JWT Sign",
|
||||
"JWT Verify",
|
||||
"JWT Decode",
|
||||
"Citrix CTX1 Encode",
|
||||
"Citrix CTX1 Decode",
|
||||
"Pseudo-Random Number Generator"
|
||||
]
|
||||
},
|
||||
@@ -334,23 +341,31 @@
|
||||
"From MessagePack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Forensics",
|
||||
"ops": [
|
||||
"Detect File Type",
|
||||
"Scan for Embedded Files",
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
"Render Image",
|
||||
"Play Media"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Other",
|
||||
"ops": [
|
||||
"Entropy",
|
||||
"Frequency distribution",
|
||||
"Chi Square",
|
||||
"Detect File Type",
|
||||
"Scan for Embedded Files",
|
||||
"Disassemble x86",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Generate UUID",
|
||||
"Generate TOTP",
|
||||
"Generate HOTP",
|
||||
"Generate QR Code",
|
||||
"Parse QR Code",
|
||||
"Haversine distance",
|
||||
"Render Image",
|
||||
"Remove EXIF",
|
||||
"Extract EXIF",
|
||||
"Numberwang",
|
||||
"XKCD Random Number"
|
||||
]
|
||||
|
||||
@@ -126,14 +126,14 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
|
||||
* Base64 alphabets.
|
||||
*/
|
||||
export const ALPHABET_OPTIONS = [
|
||||
{name: "Standard: A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
|
||||
{name: "URL safe: A-Za-z0-9-_", value: "A-Za-z0-9-_"},
|
||||
{name: "Standard (RFC 4648): A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
|
||||
{name: "URL safe (RFC 4648 \u00A75): A-Za-z0-9-_", value: "A-Za-z0-9-_"},
|
||||
{name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-="},
|
||||
{name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z="},
|
||||
{name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_."},
|
||||
{name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-"},
|
||||
{name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/="},
|
||||
{name: "Radix-64: 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
|
||||
{name: "Radix-64 (RFC 4880): 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
|
||||
{name: "Uuencoding: [space]-_", value: " -_"},
|
||||
{name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z"},
|
||||
{name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r", value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r"},
|
||||
|
||||
@@ -265,9 +265,10 @@ class Magic {
|
||||
* performance)
|
||||
* @param {Object[]} [recipeConfig=[]] - The recipe configuration up to this point
|
||||
* @param {boolean} [useful=false] - Whether the current recipe should be scored highly
|
||||
* @param {string} [crib=null] - The regex crib provided by the user, for filtering the operation output
|
||||
* @returns {Object[]} - A sorted list of the recipes most likely to result in correct decoding
|
||||
*/
|
||||
async speculativeExecution(depth=0, extLang=false, intensive=false, recipeConfig=[], useful=false) {
|
||||
async speculativeExecution(depth=0, extLang=false, intensive=false, recipeConfig=[], useful=false, crib=null) {
|
||||
if (depth < 0) return [];
|
||||
|
||||
// Find any operations that can be run on this data
|
||||
@@ -284,9 +285,9 @@ class Magic {
|
||||
isUTF8: this.isUTF8(),
|
||||
entropy: this.calcEntropy(),
|
||||
matchingOps: matchingOps,
|
||||
useful: useful
|
||||
useful: useful,
|
||||
matchesCrib: crib && crib.test(this.inputStr)
|
||||
});
|
||||
|
||||
const prevOp = recipeConfig[recipeConfig.length - 1];
|
||||
|
||||
// Execute each of the matching operations, then recursively call the speculativeExecution()
|
||||
@@ -305,7 +306,7 @@ class Magic {
|
||||
|
||||
const magic = new Magic(output, this.opPatterns),
|
||||
speculativeResults = await magic.speculativeExecution(
|
||||
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful);
|
||||
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful, crib);
|
||||
|
||||
results = results.concat(speculativeResults);
|
||||
}));
|
||||
@@ -317,7 +318,7 @@ class Magic {
|
||||
await Promise.all(bfEncodings.map(async enc => {
|
||||
const magic = new Magic(enc.data, this.opPatterns),
|
||||
bfResults = await magic.speculativeExecution(
|
||||
depth-1, extLang, false, [...recipeConfig, enc.conf]);
|
||||
depth-1, extLang, false, [...recipeConfig, enc.conf], false, crib);
|
||||
|
||||
results = results.concat(bfResults);
|
||||
}));
|
||||
|
||||
63
src/core/operations/A1Z26CipherDecode.mjs
Normal file
63
src/core/operations/A1Z26CipherDecode.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim";
|
||||
import OperationError from "../errors/OperationError";
|
||||
|
||||
/**
|
||||
* A1Z26 Cipher Decode operation
|
||||
*/
|
||||
class A1Z26CipherDecode extends Operation {
|
||||
|
||||
/**
|
||||
* A1Z26CipherDecode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "A1Z26 Cipher Decode";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Converts alphabet order numbers into their corresponding alphabet character.<br><br>e.g. <code>1</code> becomes <code>a</code> and <code>2</code> becomes <code>b</code>.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Delimiter",
|
||||
type: "option",
|
||||
value: DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space");
|
||||
|
||||
if (input.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const bites = input.split(delim);
|
||||
let latin1 = "";
|
||||
for (let i = 0; i < bites.length; i++) {
|
||||
if (bites[i] < 1 || bites[i] > 26) {
|
||||
throw new OperationError("Error: all numbers must be between 1 and 26.");
|
||||
}
|
||||
latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
|
||||
}
|
||||
return latin1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default A1Z26CipherDecode;
|
||||
61
src/core/operations/A1Z26CipherEncode.mjs
Normal file
61
src/core/operations/A1Z26CipherEncode.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim";
|
||||
|
||||
/**
|
||||
* A1Z26 Cipher Encode operation
|
||||
*/
|
||||
class A1Z26CipherEncode extends Operation {
|
||||
|
||||
/**
|
||||
* A1Z26CipherEncode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "A1Z26 Cipher Encode";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Converts alphabet characters into their corresponding alphabet order number.<br><br>e.g. <code>a</code> becomes <code>1</code> and <code>b</code> becomes <code>2</code>.<br><br>Non-alphabet characters are dropped.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Delimiter",
|
||||
type: "option",
|
||||
value: DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const delim = Utils.charRep(args[0] || "Space");
|
||||
let output = "";
|
||||
|
||||
const sanitizedinput = input.toLowerCase(),
|
||||
charcode = Utils.strToCharcode(sanitizedinput);
|
||||
|
||||
for (let i = 0; i < charcode.length; i++) {
|
||||
const ordinal = charcode[i] - 96;
|
||||
|
||||
if (ordinal > 0 && ordinal <= 26) {
|
||||
output += ordinal.toString(10) + delim;
|
||||
}
|
||||
}
|
||||
return output.slice(0, -delim.length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default A1Z26CipherEncode;
|
||||
58
src/core/operations/CitrixCTX1Decode.mjs
Normal file
58
src/core/operations/CitrixCTX1Decode.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author bwhitn [brian.m.whitney@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
|
||||
/**
|
||||
* Citrix CTX1 Decode operation
|
||||
*/
|
||||
class CitrixCTX1Decode extends Operation {
|
||||
|
||||
/**
|
||||
* CitrixCTX1Decode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Citrix CTX1 Decode";
|
||||
this.module = "Encodings";
|
||||
this.description = "Decodes strings in a Citrix CTX1 password format to plaintext.";
|
||||
this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length % 4 !== 0) {
|
||||
throw new OperationError("Incorrect hash length");
|
||||
}
|
||||
const revinput = input.reverse();
|
||||
const result = [];
|
||||
let temp = 0;
|
||||
for (let i = 0; i < revinput.length; i += 2) {
|
||||
if (i + 2 >= revinput.length) {
|
||||
temp = 0;
|
||||
} else {
|
||||
temp = ((revinput[i + 2] - 0x41) & 0xf) ^ (((revinput[i + 3]- 0x41) << 4) & 0xf0);
|
||||
}
|
||||
temp = (((revinput[i] - 0x41) & 0xf) ^ (((revinput[i + 1] - 0x41) << 4) & 0xf0)) ^ 0xa5 ^ temp;
|
||||
result.push(temp);
|
||||
}
|
||||
// Decodes a utf-16le string
|
||||
return cptable.utils.decode(1200, result.reverse());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CitrixCTX1Decode;
|
||||
50
src/core/operations/CitrixCTX1Encode.mjs
Normal file
50
src/core/operations/CitrixCTX1Encode.mjs
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @author bwhitn [brian.m.whitney@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
|
||||
/**
|
||||
* Citrix CTX1 Encode operation
|
||||
*/
|
||||
class CitrixCTX1Encode extends Operation {
|
||||
|
||||
/**
|
||||
* CitrixCTX1Encode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Citrix CTX1 Encode";
|
||||
this.module = "Encodings";
|
||||
this.description = "Encodes strings to Citrix CTX1 password format.";
|
||||
this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const utf16pass = Array.from(cptable.utils.encode(1200, input));
|
||||
const result = [];
|
||||
let temp = 0;
|
||||
for (let i = 0; i < utf16pass.length; i++) {
|
||||
temp = utf16pass[i] ^ 0xa5 ^ temp;
|
||||
result.push(((temp >>> 4) & 0xf) + 0x41);
|
||||
result.push((temp & 0xf) + 0x41);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CitrixCTX1Encode;
|
||||
58
src/core/operations/FromBase62.mjs
Normal file
58
src/core/operations/FromBase62.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import BigNumber from "bignumber.js";
|
||||
import Utils from "../Utils";
|
||||
|
||||
|
||||
/**
|
||||
* From Base62 operation
|
||||
*/
|
||||
class FromBase62 extends Operation {
|
||||
|
||||
/**
|
||||
* FromBase62 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Base62";
|
||||
this.module = "Default";
|
||||
this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: "0-9A-Za-z"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length < 1) return [];
|
||||
const ALPHABET = Utils.expandAlphRange(args[0]).join("");
|
||||
const BN = BigNumber.clone({ ALPHABET });
|
||||
|
||||
const re = new RegExp("[^" + ALPHABET.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
|
||||
const number = new BN(input, 62);
|
||||
|
||||
return Utils.convertToByteArray(number.toString(16), "Hex");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromBase62;
|
||||
@@ -38,44 +38,44 @@ class FromBase64 extends Operation {
|
||||
];
|
||||
this.patterns = [
|
||||
{
|
||||
match: "^(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9+/=", false]
|
||||
args: ["A-Za-z0-9+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d\\-_]{20,}$",
|
||||
match: "^\\s*[A-Z\\d\\-_]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9-_", false]
|
||||
args: ["A-Za-z0-9-_", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9+\\-=", false]
|
||||
args: ["A-Za-z0-9+\\-=", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["./0-9A-Za-z=", false]
|
||||
args: ["./0-9A-Za-z=", true]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d_.]{20,}$",
|
||||
match: "^\\s*[A-Z\\d_.]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9_.", false]
|
||||
args: ["A-Za-z0-9_.", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?$",
|
||||
match: "^\\s*(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["A-Za-z0-9._-", false]
|
||||
args: ["A-Za-z0-9._-", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["0-9a-zA-Z+/=", false]
|
||||
args: ["0-9a-zA-Z+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["0-9A-Za-z+/=", false]
|
||||
args: ["0-9A-Za-z+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^[ !\"#$%&'()*+,\\-./\\d:;<=>?@A-Z[\\\\\\]^_]{20,}$",
|
||||
@@ -83,24 +83,24 @@ class FromBase64 extends Operation {
|
||||
args: [" -_", false]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d+\\-]{20,}$",
|
||||
match: "^\\s*[A-Z\\d+\\-]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["+\\-0-9A-Za-z", false]
|
||||
args: ["+\\-0-9A-Za-z", true]
|
||||
},
|
||||
{
|
||||
match: "^[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}$",
|
||||
match: "^\\s*[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}\\s*$",
|
||||
flags: "",
|
||||
args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", false]
|
||||
args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", true]
|
||||
},
|
||||
{
|
||||
match: "^(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?$",
|
||||
match: "^\\s*(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
args: ["N-ZA-Mn-za-m0-9+/=", false]
|
||||
args: ["N-ZA-Mn-za-m0-9+/=", true]
|
||||
},
|
||||
{
|
||||
match: "^[A-Z\\d./]{20,}$",
|
||||
match: "^\\s*[A-Z\\d./]{20,}\\s*$",
|
||||
flags: "i",
|
||||
args: ["./0-9A-Za-z", false]
|
||||
args: ["./0-9A-Za-z", true]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class FromQuotedPrintable extends Operation {
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
{
|
||||
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]*(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
|
||||
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]{0,76}(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
|
||||
flags: "i",
|
||||
args: []
|
||||
},
|
||||
|
||||
119
src/core/operations/GenerateQRCode.mjs
Normal file
119
src/core/operations/GenerateQRCode.mjs
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @author j433866 [j433866@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import qr from "qr-image";
|
||||
import { toBase64 } from "../lib/Base64";
|
||||
import Magic from "../lib/Magic";
|
||||
import Utils from "../Utils";
|
||||
|
||||
/**
|
||||
* Generate QR Code operation
|
||||
*/
|
||||
class GenerateQRCode extends Operation {
|
||||
|
||||
/**
|
||||
* GenerateQRCode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Generate QR Code";
|
||||
this.module = "Image";
|
||||
this.description = "Generates a Quick Response (QR) code from the input text.<br><br>A QR code is a type of matrix barcode (or two-dimensional barcode) first designed in 1994 for the automotive industry in Japan. A barcode is a machine-readable optical label that contains information about the item to which it is attached.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/QR_code";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Image Format",
|
||||
"type": "option",
|
||||
"value": ["PNG", "SVG", "EPS", "PDF"]
|
||||
},
|
||||
{
|
||||
"name": "Module size (px)",
|
||||
"type": "number",
|
||||
"value": 5
|
||||
},
|
||||
{
|
||||
"name": "Margin (num modules)",
|
||||
"type": "number",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"name": "Error correction",
|
||||
"type": "option",
|
||||
"value": ["Low", "Medium", "Quartile", "High"],
|
||||
"defaultIndex": 1
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [format, size, margin, errorCorrection] = args;
|
||||
|
||||
// Create new QR image from the input data, and convert it to a buffer
|
||||
const qrImage = qr.imageSync(input, {
|
||||
type: format,
|
||||
size: size,
|
||||
margin: margin,
|
||||
"ec_level": errorCorrection.charAt(0).toUpperCase()
|
||||
});
|
||||
|
||||
if (qrImage == null) {
|
||||
throw new OperationError("Error generating QR code.");
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case "SVG":
|
||||
case "EPS":
|
||||
case "PDF":
|
||||
return [...Buffer.from(qrImage)];
|
||||
case "PNG":
|
||||
// Return the QR image buffer as a byte array
|
||||
return [...qrImage];
|
||||
default:
|
||||
throw new OperationError("Unsupported QR code format.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the QR image using HTML for web apps
|
||||
*
|
||||
* @param {byteArray} data
|
||||
* @returns {html}
|
||||
*/
|
||||
present(data, args) {
|
||||
if (!data.length) return "";
|
||||
|
||||
const [format] = args;
|
||||
|
||||
if (format === "PNG") {
|
||||
let dataURI = "data:";
|
||||
const type = Magic.magicFileType(data);
|
||||
if (type && type.mime.indexOf("image") === 0){
|
||||
dataURI += type.mime + ";";
|
||||
} else {
|
||||
throw new OperationError("Invalid PNG file generated by QR image");
|
||||
}
|
||||
dataURI += "base64," + toBase64(data);
|
||||
|
||||
return `<img src="${dataURI}">`;
|
||||
}
|
||||
|
||||
return Utils.byteArrayToChars(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GenerateQRCode;
|
||||
@@ -72,7 +72,7 @@ class HMAC extends Operation {
|
||||
msg = Utils.arrayBufferToStr(input, false),
|
||||
hasher = CryptoApi.getHasher(hashFunc);
|
||||
|
||||
const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
|
||||
const mac = CryptoApi.getHmac(key, hasher);
|
||||
mac.update(msg);
|
||||
return CryptoApi.encoder.toHex(mac.finalize());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
@@ -27,7 +28,12 @@ class JSONBeautify extends Operation {
|
||||
{
|
||||
"name": "Indent string",
|
||||
"type": "binaryShortString",
|
||||
"value": "\\t"
|
||||
"value": " "
|
||||
},
|
||||
{
|
||||
"name": "Sort Object Keys",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -38,11 +44,35 @@ class JSONBeautify extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const indentStr = args[0];
|
||||
const [indentStr, sortBool] = args;
|
||||
|
||||
if (!input) return "";
|
||||
if (sortBool) {
|
||||
input = JSON.stringify(JSONBeautify._sort(JSON.parse(input)));
|
||||
}
|
||||
return vkbeautify.json(input, indentStr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort JSON representation of an object
|
||||
*
|
||||
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
||||
* @private
|
||||
* @param {object} o
|
||||
* @returns {object}
|
||||
*/
|
||||
static _sort(o) {
|
||||
if (Array.isArray(o)) {
|
||||
return o.map(JSONBeautify._sort);
|
||||
} else if ("[object Object]" === Object.prototype.toString.call(o)) {
|
||||
return Object.keys(o).sort().reduce(function(a, k) {
|
||||
a[k] = JSONBeautify._sort(o[k]);
|
||||
return a;
|
||||
}, {});
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
export default JSONBeautify;
|
||||
|
||||
@@ -46,12 +46,11 @@ class JSONToCSV extends Operation {
|
||||
run(input, args) {
|
||||
const [cellDelim, rowDelim] = args;
|
||||
|
||||
// Record values so they don't have to be passed to other functions explicitly
|
||||
this.cellDelim = cellDelim;
|
||||
this.rowDelim = rowDelim;
|
||||
const self = this;
|
||||
|
||||
// TODO: Escape cells correctly.
|
||||
|
||||
try {
|
||||
// If the JSON is an array of arrays, this is easy
|
||||
if (input[0] instanceof Array) {
|
||||
|
||||
@@ -23,7 +23,7 @@ class Magic extends Operation {
|
||||
this.name = "Magic";
|
||||
this.flowControl = true;
|
||||
this.module = "Default";
|
||||
this.description = "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it.<br><br><b>Options</b><br><u>Depth:</u> If an operation appears to match the data, it will be run and the result will be analysed further. This argument controls the maximum number of levels of recursion.<br><br><u>Intensive mode:</u> When this is turned on, various operations like XOR, bit rotates, and character encodings are brute-forced to attempt to detect valid data underneath. To improve performance, only the first 100 bytes of the data is brute-forced.<br><br><u>Extensive language support:</u> At each stage, the relative byte frequencies of the data will be compared to average frequencies for a number of languages. The default set consists of ~40 of the most commonly used languages on the Internet. The extensive list consists of 284 languages and can result in many languages matching the data if their byte frequencies are similar.";
|
||||
this.description = "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it.<br><br><b>Options</b><br><u>Depth:</u> If an operation appears to match the data, it will be run and the result will be analysed further. This argument controls the maximum number of levels of recursion.<br><br><u>Intensive mode:</u> When this is turned on, various operations like XOR, bit rotates, and character encodings are brute-forced to attempt to detect valid data underneath. To improve performance, only the first 100 bytes of the data is brute-forced.<br><br><u>Extensive language support:</u> At each stage, the relative byte frequencies of the data will be compared to average frequencies for a number of languages. The default set consists of ~40 of the most commonly used languages on the Internet. The extensive list consists of 284 languages and can result in many languages matching the data if their byte frequencies are similar.<br><br>Optionally enter a regular expression to match a string you expect to find to filter results (crib).";
|
||||
this.infoURL = "https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "JSON";
|
||||
@@ -43,6 +43,11 @@ class Magic extends Operation {
|
||||
"name": "Extensive language support",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "Crib (known plaintext string or regex)",
|
||||
"type": "string",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -56,10 +61,16 @@ class Magic extends Operation {
|
||||
*/
|
||||
async run(state) {
|
||||
const ings = state.opList[state.progress].ingValues,
|
||||
[depth, intensive, extLang] = ings,
|
||||
[depth, intensive, extLang, crib] = ings,
|
||||
dish = state.dish,
|
||||
magic = new MagicLib(await dish.get(Dish.ARRAY_BUFFER)),
|
||||
options = await magic.speculativeExecution(depth, extLang, intensive);
|
||||
cribRegex = (crib && crib.length) ? new RegExp(crib, "i") : null;
|
||||
let options = await magic.speculativeExecution(depth, extLang, intensive, [], false, cribRegex);
|
||||
|
||||
// Filter down to results which matched the crib
|
||||
if (cribRegex) {
|
||||
options = options.filter(option => option.matchesCrib);
|
||||
}
|
||||
|
||||
// Record the current state for use when presenting
|
||||
this.state = state;
|
||||
|
||||
107
src/core/operations/ParseQRCode.mjs
Normal file
107
src/core/operations/ParseQRCode.mjs
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @author j433866 [j433866@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Magic from "../lib/Magic";
|
||||
import jsqr from "jsqr";
|
||||
import jimp from "jimp";
|
||||
|
||||
/**
|
||||
* Parse QR Code operation
|
||||
*/
|
||||
class ParseQRCode extends Operation {
|
||||
|
||||
/**
|
||||
* ParseQRCode constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Parse QR Code";
|
||||
this.module = "Image";
|
||||
this.description = "Reads an image file and attempts to detect and read a Quick Response (QR) code from the image.<br><br><u>Normalise Image</u><br>Attempts to normalise the image before parsing it to improve detection of a QR code.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/QR_code";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Normalise image",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const type = Magic.magicFileType(input);
|
||||
const [normalise] = args;
|
||||
|
||||
// Make sure that the input is an image
|
||||
if (type && type.mime.indexOf("image") === 0) {
|
||||
let image = input;
|
||||
|
||||
if (normalise) {
|
||||
// Process the image to be easier to read by jsqr
|
||||
// Disables the alpha channel
|
||||
// Sets the image default background to white
|
||||
// Normalises the image colours
|
||||
// Makes the image greyscale
|
||||
// Converts image to a JPEG
|
||||
image = await new Promise((resolve, reject) => {
|
||||
jimp.read(Buffer.from(input))
|
||||
.then(image => {
|
||||
image
|
||||
.rgba(false)
|
||||
.background(0xFFFFFFFF)
|
||||
.normalize()
|
||||
.greyscale()
|
||||
.getBuffer(jimp.MIME_JPEG, (error, result) => {
|
||||
resolve(result);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
reject(new OperationError("Error reading the image file."));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (image instanceof OperationError) {
|
||||
throw image;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
jimp.read(Buffer.from(image))
|
||||
.then(image => {
|
||||
if (image.bitmap != null) {
|
||||
const qrData = jsqr(image.bitmap.data, image.getWidth(), image.getHeight());
|
||||
if (qrData != null) {
|
||||
resolve(qrData.data);
|
||||
} else {
|
||||
reject(new OperationError("Couldn't read a QR code from the image."));
|
||||
}
|
||||
} else {
|
||||
reject(new OperationError("Error reading the image file."));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
reject(new OperationError("Error reading the image file."));
|
||||
});
|
||||
});
|
||||
} else {
|
||||
throw new OperationError("Invalid file type.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ParseQRCode;
|
||||
102
src/core/operations/PlayMedia.mjs
Normal file
102
src/core/operations/PlayMedia.mjs
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @author anthony-arnold [anthony.arnold@uqconnect.edu.au]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import { fromBase64, toBase64 } from "../lib/Base64";
|
||||
import { fromHex } from "../lib/Hex";
|
||||
import Operation from "../Operation";
|
||||
import OperationError from "../errors/OperationError";
|
||||
import Utils from "../Utils";
|
||||
import Magic from "../lib/Magic";
|
||||
|
||||
/**
|
||||
* PlayMedia operation
|
||||
*/
|
||||
class PlayMedia extends Operation {
|
||||
|
||||
/**
|
||||
* PlayMedia constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Play Media";
|
||||
this.module = "Default";
|
||||
this.description = "Plays the input as audio or video depending on the type.<br><br>Tags: sound, movie, mp3, mp4, mov, webm, wav, ogg";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Input format",
|
||||
"type": "option",
|
||||
"value": ["Raw", "Base64", "Hex"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray} The multimedia data as bytes.
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat] = args;
|
||||
|
||||
if (!input.length) return [];
|
||||
|
||||
// Convert input to raw bytes
|
||||
switch (inputFormat) {
|
||||
case "Hex":
|
||||
input = fromHex(input);
|
||||
break;
|
||||
case "Base64":
|
||||
// Don't trust the Base64 entered by the user.
|
||||
// Unwrap it first, then re-encode later.
|
||||
input = fromBase64(input, undefined, "byteArray");
|
||||
break;
|
||||
case "Raw":
|
||||
default:
|
||||
input = Utils.strToByteArray(input);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Determine file type
|
||||
const type = Magic.magicFileType(input);
|
||||
if (!(type && /^audio|video/.test(type.mime))) {
|
||||
throw new OperationError("Invalid or unrecognised file type");
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an audio or video element that may be able to play the media
|
||||
* file.
|
||||
*
|
||||
* @param data {byteArray} Data containing an audio or video file.
|
||||
* @returns {string} Markup to display a media player.
|
||||
*/
|
||||
async present(data) {
|
||||
if (!data.length) return "";
|
||||
|
||||
const type = Magic.magicFileType(data);
|
||||
const matches = /^audio|video/.exec(type.mime);
|
||||
if (!matches) {
|
||||
throw new OperationError("Invalid file type");
|
||||
}
|
||||
const dataURI = `data:${type.mime};base64,${toBase64(data)}`;
|
||||
const element = matches[0];
|
||||
|
||||
let html = `<${element} src='${dataURI}' type='${type.mime}' controls>`;
|
||||
html += "<p>Unsupported media type.</p>";
|
||||
html += `</${element}>`;
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
export default PlayMedia;
|
||||
@@ -20,7 +20,7 @@ class Substitute extends Operation {
|
||||
|
||||
this.name = "Substitute";
|
||||
this.module = "Default";
|
||||
this.description = "A substitution cipher allowing you to specify bytes to replace with other byte values. This can be used to create Caesar ciphers but is more powerful as any byte value can be substituted, not just letters, and the substitution values need not be in order.<br><br>Enter the bytes you want to replace in the Plaintext field and the bytes to replace them with in the Ciphertext field.<br><br>Non-printable bytes can be specified using string escape notation. For example, a line feed character can be written as either <code>\n</code> or <code>\x0a</code>.<br><br>Byte ranges can be specified using a hyphen. For example, the sequence <code>0123456789</code> can be written as <code>0-9</code>.";
|
||||
this.description = "A substitution cipher allowing you to specify bytes to replace with other byte values. This can be used to create Caesar ciphers but is more powerful as any byte value can be substituted, not just letters, and the substitution values need not be in order.<br><br>Enter the bytes you want to replace in the Plaintext field and the bytes to replace them with in the Ciphertext field.<br><br>Non-printable bytes can be specified using string escape notation. For example, a line feed character can be written as either <code>\\n</code> or <code>\\x0a</code>.<br><br>Byte ranges can be specified using a hyphen. For example, the sequence <code>0123456789</code> can be written as <code>0-9</code>.<br><br>Note that blackslash characters are used to escape special characters, so will need to be escaped themselves if you want to use them on their own (e.g.<code>\\\\</code>).";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Substitution_cipher";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
|
||||
92
src/core/operations/TextEncodingBruteForce.mjs
Normal file
92
src/core/operations/TextEncodingBruteForce.mjs
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @author Cynser
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import Utils from "../Utils";
|
||||
import cptable from "../vendor/js-codepage/cptable.js";
|
||||
import {IO_FORMAT} from "../lib/ChrEnc";
|
||||
|
||||
/**
|
||||
* Text Encoding Brute Force operation
|
||||
*/
|
||||
class TextEncodingBruteForce extends Operation {
|
||||
|
||||
/**
|
||||
* TextEncodingBruteForce constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Text Encoding Brute Force";
|
||||
this.module = "CharEnc";
|
||||
this.description = [
|
||||
"Enumerates all supported text encodings for the input, allowing you to quickly spot the correct one.",
|
||||
"<br><br>",
|
||||
"Supported charsets are:",
|
||||
"<ul>",
|
||||
Object.keys(IO_FORMAT).map(e => `<li>${e}</li>`).join("\n"),
|
||||
"</ul>"
|
||||
].join("\n");
|
||||
this.infoURL = "https://wikipedia.org/wiki/Character_encoding";
|
||||
this.inputType = "string";
|
||||
this.outputType = "json";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
name: "Mode",
|
||||
type: "option",
|
||||
value: ["Encode", "Decode"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {json}
|
||||
*/
|
||||
run(input, args) {
|
||||
const output = {},
|
||||
charsets = Object.keys(IO_FORMAT),
|
||||
mode = args[0];
|
||||
|
||||
charsets.forEach(charset => {
|
||||
try {
|
||||
if (mode === "Decode") {
|
||||
output[charset] = cptable.utils.decode(IO_FORMAT[charset], input);
|
||||
} else {
|
||||
output[charset] = Utils.arrayBufferToStr(cptable.utils.encode(IO_FORMAT[charset], input));
|
||||
}
|
||||
} catch (err) {
|
||||
output[charset] = "Could not decode.";
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the encodings in an HTML table for web apps.
|
||||
*
|
||||
* @param {Object[]} encodings
|
||||
* @returns {html}
|
||||
*/
|
||||
present(encodings) {
|
||||
let table = "<table class='table table-hover table-sm table-bordered table-nonfluid'><tr><th>Encoding</th><th>Value</th></tr>";
|
||||
|
||||
for (const enc in encodings) {
|
||||
const value = Utils.printable(encodings[enc], true);
|
||||
table += `<tr><td>${enc}</td><td>${value}</td></tr>`;
|
||||
}
|
||||
|
||||
table += "<table>";
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TextEncodingBruteForce;
|
||||
58
src/core/operations/ToBase62.mjs
Normal file
58
src/core/operations/ToBase62.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation";
|
||||
import BigNumber from "bignumber.js";
|
||||
import Utils from "../Utils";
|
||||
import {toHexFast} from "../lib/Hex";
|
||||
|
||||
/**
|
||||
* To Base62 operation
|
||||
*/
|
||||
class ToBase62 extends Operation {
|
||||
|
||||
/**
|
||||
* ToBase62 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Base62";
|
||||
this.module = "Default";
|
||||
this.description = "Base62 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. The high number base results in shorter strings than with the decimal or hexadecimal system.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: "0-9A-Za-z"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length < 1) return "";
|
||||
|
||||
const ALPHABET = Utils.expandAlphRange(args[0]).join("");
|
||||
const BN = BigNumber.clone({ ALPHABET });
|
||||
|
||||
input = toHexFast(input).toUpperCase();
|
||||
|
||||
const number = new BN(input, 16);
|
||||
|
||||
return number.toString(62);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToBase62;
|
||||
@@ -26,6 +26,7 @@ class HTMLIngredient {
|
||||
this.disabled = config.disabled || false;
|
||||
this.hint = config.hint || false;
|
||||
this.target = config.target;
|
||||
this.defaultIndex = config.defaultIndex || 0;
|
||||
this.toggleValues = config.toggleValues;
|
||||
this.id = "ing-" + this.app.nextIngId();
|
||||
}
|
||||
@@ -133,7 +134,7 @@ class HTMLIngredient {
|
||||
} else if ((m = this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
||||
html += "</optgroup>";
|
||||
} else {
|
||||
html += `<option>${this.value[i]}</option>`;
|
||||
html += `<option ${this.defaultIndex === i ? "selected" : ""}>${this.value[i]}</option>`;
|
||||
}
|
||||
}
|
||||
html += `</select>
|
||||
@@ -154,7 +155,7 @@ class HTMLIngredient {
|
||||
} else if ((m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
|
||||
html += "</optgroup>";
|
||||
} else {
|
||||
html += `<option populate-value='${this.value[i].value}'>${this.value[i].name}</option>`;
|
||||
html += `<option populate-value="${this.value[i].value}">${this.value[i].name}</option>`;
|
||||
}
|
||||
}
|
||||
html += `</select>
|
||||
@@ -170,7 +171,7 @@ class HTMLIngredient {
|
||||
class="form-control arg inline"
|
||||
id="${this.id}"
|
||||
arg-name="${this.name}"
|
||||
value="${this.value[0].value}"
|
||||
value="${this.value[this.defaultIndex].value}"
|
||||
${this.disabled ? "disabled" : ""}>
|
||||
${this.hint ? "<span class='bmd-help'>" + this.hint + "</span>" : ""}
|
||||
<div class="input-group-append inline">
|
||||
|
||||
@@ -28,6 +28,7 @@ import "./tests/operations/BCD";
|
||||
import "./tests/operations/BSON";
|
||||
import "./tests/operations/Base58";
|
||||
import "./tests/operations/Base64";
|
||||
import "./tests/operations/Base62";
|
||||
import "./tests/operations/BitwiseOp";
|
||||
import "./tests/operations/ByteRepr";
|
||||
import "./tests/operations/CartesianProduct";
|
||||
@@ -50,6 +51,8 @@ import "./tests/operations/HaversineDistance";
|
||||
import "./tests/operations/Hexdump";
|
||||
import "./tests/operations/Image";
|
||||
import "./tests/operations/Jump";
|
||||
import "./tests/operations/JSONBeautify";
|
||||
import "./tests/operations/JSONMinify";
|
||||
import "./tests/operations/JWTDecode";
|
||||
import "./tests/operations/JWTSign";
|
||||
import "./tests/operations/JWTVerify";
|
||||
@@ -61,6 +64,7 @@ import "./tests/operations/OTP";
|
||||
import "./tests/operations/PGP";
|
||||
import "./tests/operations/PHP";
|
||||
import "./tests/operations/ParseIPRange";
|
||||
import "./tests/operations/ParseQRCode";
|
||||
import "./tests/operations/PowerSet";
|
||||
import "./tests/operations/Regex";
|
||||
import "./tests/operations/Register";
|
||||
@@ -72,10 +76,12 @@ import "./tests/operations/SetIntersection";
|
||||
import "./tests/operations/SetUnion";
|
||||
import "./tests/operations/StrUtils";
|
||||
import "./tests/operations/SymmetricDifference";
|
||||
import "./tests/operations/TextEncodingBruteForce";
|
||||
import "./tests/operations/ToGeohash.mjs";
|
||||
import "./tests/operations/TranslateDateTimeFormat";
|
||||
import "./tests/operations/Magic";
|
||||
import "./tests/operations/ParseTLV";
|
||||
import "./tests/operations/Media";
|
||||
|
||||
let allTestsPassing = true;
|
||||
const testStatusCounts = {
|
||||
|
||||
79
test/tests/operations/Base62.mjs
Normal file
79
test/tests/operations/Base62.mjs
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Base62 tests.
|
||||
*
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Base62: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base62: Hello, World!",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "1wJfrzvdbtXUOlUjUf",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base62: UTF-8",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "BPDNbjoGvDCDzHbKT77eWg0vGQrJuWRXltuRVZ",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base62: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base62: Hello, World!",
|
||||
input: "1wJfrzvdbtXUOlUjUf",
|
||||
expectedOutput: "Hello, World!",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base62: UTF-8",
|
||||
input: "BPDNbjoGvDCDzHbKT77eWg0vGQrJuWRXltuRVZ",
|
||||
expectedOutput: "ნუ პანიკას",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base62",
|
||||
args: ["0-9A-Za-z"],
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
@@ -110,6 +110,39 @@ TestRegister.addTests([
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "A1Z26 Encode: normal",
|
||||
input: "This is the test sentence.",
|
||||
expectedOutput: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "A1Z26 Cipher Encode",
|
||||
args: ["Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "A1Z26 Decode: normal",
|
||||
input: "20 8 9 19 9 19 20 8 5 20 5 19 20 19 5 14 20 5 14 3 5",
|
||||
expectedOutput: "thisisthetestsentence",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "A1Z26 Cipher Decode",
|
||||
args: ["Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "A1Z26 Decode: error",
|
||||
input: "20 8 9 27",
|
||||
expectedOutput: "Error: all numbers must be between 1 and 26.",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "A1Z26 Cipher Decode",
|
||||
args: ["Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Atbash: no input",
|
||||
input: "",
|
||||
@@ -220,6 +253,39 @@ TestRegister.addTests([
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Citrix CTX1 Encode",
|
||||
input: "Password1",
|
||||
expectedOutput: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLAO",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Citrix CTX1 Encode",
|
||||
"args": []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Citrix CTX1 Decode: normal",
|
||||
input: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLAO",
|
||||
expectedOutput: "Password1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Citrix CTX1 Decode",
|
||||
"args": []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Citrix CTX1 Decode: invalid length",
|
||||
input: "PFFAJEDBOHECJEDBODEGIMCJPOFLJKDPKLA",
|
||||
expectedOutput: "Incorrect hash length",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Citrix CTX1 Decode",
|
||||
"args": []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Vigenère Encode: no input",
|
||||
input: "",
|
||||
|
||||
@@ -405,7 +405,7 @@ TestRegister.addTests([
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC SHA256",
|
||||
name: "HMAC: SHA256",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac",
|
||||
recipeConfig: [
|
||||
@@ -415,6 +415,302 @@ TestRegister.addTests([
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-224",
|
||||
input: "Hi There",
|
||||
expectedOutput: "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-256",
|
||||
input: "Hi There",
|
||||
expectedOutput: "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-384",
|
||||
input: "Hi There",
|
||||
expectedOutput: "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 1 SHA-512",
|
||||
input: "Hi There",
|
||||
expectedOutput: "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-224",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-256",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-384",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 2 SHA-512",
|
||||
input: "what do ya want for nothing?",
|
||||
expectedOutput: "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "4a656665"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-224",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-256",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-384",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 3 SHA-512",
|
||||
input: "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
||||
expectedOutput: "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-224",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-256",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-384",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 4 SHA-512",
|
||||
input: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
|
||||
expectedOutput: "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["None"]
|
||||
},
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "0102030405060708090a0b0c0d0e0f10111213141516171819"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-224",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-256",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-384",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 6 SHA-512",
|
||||
input: "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
expectedOutput: "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-224",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA224"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-256",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-384",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA384"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: RFC4231 Test Case 7 SHA-512",
|
||||
input: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
|
||||
expectedOutput: "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Hex", "string": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "SHA512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "MD5: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
|
||||
122
test/tests/operations/JSONBeautify.mjs
Normal file
122
test/tests/operations/JSONBeautify.mjs
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* JSONBeautify tests.
|
||||
*
|
||||
* @author Phillip Nordwall [Phillip.Nordwall@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JSON Beautify: space, ''",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, number",
|
||||
input: "42",
|
||||
expectedOutput: "42",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, string",
|
||||
input: "\"string\"",
|
||||
expectedOutput: "\"string\"",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, boolean",
|
||||
input: "false",
|
||||
expectedOutput: "false",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, emptyList",
|
||||
input: "[]",
|
||||
expectedOutput: "[]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, list",
|
||||
input: "[2,1]",
|
||||
expectedOutput: "[\n 2,\n 1\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: tab, list",
|
||||
input: "[2,1]",
|
||||
expectedOutput: "[\n\t2,\n\t1\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: space, object",
|
||||
input: "{\"second\":2,\"first\":3}",
|
||||
expectedOutput: "{\n \"second\": 2,\n \"first\": 3\n}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: tab, nested",
|
||||
input: "[2,{\"second\":2,\"first\":3,\"beginning\":{\"j\":\"3\",\"i\":[2,3,false]}},1,2,3]",
|
||||
expectedOutput: "[\n\t2,\n\t{\n\t\t\"second\": 2,\n\t\t\"first\": 3,\n\t\t\"beginning\": {\n\t\t\t\"j\": \"3\",\n\t\t\t\"i\": [\n\t\t\t\t2,\n\t\t\t\t3,\n\t\t\t\tfalse\n\t\t\t]\n\t\t}\n\t},\n\t1,\n\t2,\n\t3\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Beautify: tab, nested, sorted",
|
||||
input: "[2,{\"second\":2,\"first\":3,\"beginning\":{\"j\":\"3\",\"i\":[2,3,false]}},1,2,3]",
|
||||
expectedOutput: "[\n\t2,\n\t{\n\t\t\"beginning\": {\n\t\t\t\"i\": [\n\t\t\t\t2,\n\t\t\t\t3,\n\t\t\t\tfalse\n\t\t\t],\n\t\t\t\"j\": \"3\"\n\t\t},\n\t\t\"first\": 3,\n\t\t\"second\": 2\n\t},\n\t1,\n\t2,\n\t3\n]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", true],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
111
test/tests/operations/JSONMinify.mjs
Normal file
111
test/tests/operations/JSONMinify.mjs
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* JSONMinify tests.
|
||||
*
|
||||
* @author Phillip Nordwall [Phillip.Nordwall@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "JSON Minify: ''",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: number",
|
||||
input: "42",
|
||||
expectedOutput: "42",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: number",
|
||||
input: "4.2",
|
||||
expectedOutput: "4.2",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: string",
|
||||
input: "\"string\"",
|
||||
expectedOutput: "\"string\"",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: boolean",
|
||||
input: "false",
|
||||
expectedOutput: "false",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: emptyList",
|
||||
input: "[\n \n \t]",
|
||||
expectedOutput: "[]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: list",
|
||||
input: "[2,\n \t1]",
|
||||
expectedOutput: "[2,1]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: object",
|
||||
input: "{\n \"second\": 2,\n \"first\": 3\n}",
|
||||
expectedOutput: "{\"second\":2,\"first\":3}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JSON Minify: tab, nested",
|
||||
input: "[\n\t2,\n\t{\n\t\t\"second\": 2,\n\t\t\"first\": 3,\n\t\t\"beginning\": {\n\t\t\t\"j\": \"3\",\n\t\t\t\"i\": [\n\t\t\t\t2,\n\t\t\t\t3,\n\t\t\t\tfalse\n\t\t\t]\n\t\t}\n\t},\n\t1,\n\t2,\n\t3\n]",
|
||||
expectedOutput: "[2,{\"second\":2,\"first\":3,\"beginning\":{\"j\":\"3\",\"i\":[2,3,false]}},1,2,3]",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Minify",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
43
test/tests/operations/Media.mjs
Normal file
43
test/tests/operations/Media.mjs
Normal file
File diff suppressed because one or more lines are too long
71
test/tests/operations/ParseQRCode.mjs
Normal file
71
test/tests/operations/ParseQRCode.mjs
Normal file
File diff suppressed because one or more lines are too long
35
test/tests/operations/TextEncodingBruteForce.mjs
Normal file
35
test/tests/operations/TextEncodingBruteForce.mjs
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Text Encoding Brute Force tests.
|
||||
*
|
||||
* @author Cynser
|
||||
*
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Text Encoding Brute Force - Encode",
|
||||
input: "Булкі праз ляніва сабаку.",
|
||||
expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text Encoding Brute Force",
|
||||
args: ["Encode"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Text Encoding Brute Force - Decode",
|
||||
input: "Áóëê³ ïðàç ëÿí³âà ñàáàêó.",
|
||||
expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Text Encoding Brute Force",
|
||||
args: ["Decode"],
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const webpack = require("webpack");
|
||||
const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
const path = require("path");
|
||||
|
||||
/**
|
||||
* Webpack configuration details for use with Grunt.
|
||||
@@ -45,6 +46,9 @@ module.exports = {
|
||||
raw: true,
|
||||
entryOnly: true
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
"process.browser": "true"
|
||||
}),
|
||||
vendorCSS,
|
||||
projectCSS
|
||||
],
|
||||
@@ -58,8 +62,13 @@ module.exports = {
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
exclude: /node_modules\/(?!jsesc|crypto-api)/,
|
||||
options: {
|
||||
configFile: path.resolve(__dirname, "babel.config.js"),
|
||||
cacheDirectory: true,
|
||||
compact: false
|
||||
},
|
||||
type: "javascript/auto",
|
||||
loader: "babel-loader?compact=false"
|
||||
loader: "babel-loader"
|
||||
},
|
||||
{
|
||||
test: /forge.min.js$/,
|
||||
|
||||
Reference in New Issue
Block a user