mirror of
https://github.com/gchq/CyberChef
synced 2025-12-27 13:43:30 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4563c86acd | ||
|
|
0a59f8068e | ||
|
|
24548e3a48 | ||
|
|
f4784d49e7 | ||
|
|
14d5069c6e | ||
|
|
9fdd55c5c6 | ||
|
|
5bc523aeff | ||
|
|
3ae2e2e2c8 | ||
|
|
83e49da7f6 | ||
|
|
fe6df8778f | ||
|
|
d5a0adea0c | ||
|
|
1bcb8e433d | ||
|
|
fa05cf1d78 | ||
|
|
63dff0d34d | ||
|
|
e228b197f9 | ||
|
|
4bbeb6caa3 | ||
|
|
139d25dff9 | ||
|
|
6984258404 | ||
|
|
ba66fd6546 | ||
|
|
47bbefd81f | ||
|
|
50f796049c | ||
|
|
887ea0cf06 | ||
|
|
3e0525ee9e |
@@ -13,10 +13,10 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
## Details
|
||||
|
||||
### [9.24.0] - 2020-02-02
|
||||
### [9.24.0] - 2021-02-02
|
||||
- 'SM3' hashing function added along with more configuration options for other hashing operations [@n1073645] [@n1474335] | [#1022]
|
||||
|
||||
### [9.23.0] - 2020-02-01
|
||||
### [9.23.0] - 2021-02-01
|
||||
- Various RSA operations added to encrypt, decrypt, sign, verify and generate keys [@mattnotmitt] [@GCHQ77703] | [#652]
|
||||
|
||||
### [9.22.0] - 2021-02-01
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.24.4",
|
||||
"version": "9.24.5",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.24.4",
|
||||
"version": "9.24.5",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
|
||||
@@ -71,12 +71,12 @@ function fuzzyMatchRecursive(
|
||||
|
||||
// Return if recursion limit is reached.
|
||||
if (++recursionCount >= recursionLimit) {
|
||||
return [false, outScore];
|
||||
return [false, outScore, []];
|
||||
}
|
||||
|
||||
// Return if we reached ends of strings.
|
||||
if (patternCurIndex === pattern.length || strCurrIndex === str.length) {
|
||||
return [false, outScore];
|
||||
return [false, outScore, []];
|
||||
}
|
||||
|
||||
// Recursion params
|
||||
@@ -92,7 +92,7 @@ function fuzzyMatchRecursive(
|
||||
pattern[patternCurIndex].toLowerCase() === str[strCurrIndex].toLowerCase()
|
||||
) {
|
||||
if (nextMatch >= maxMatches) {
|
||||
return [false, outScore];
|
||||
return [false, outScore, []];
|
||||
}
|
||||
|
||||
if (firstMatch && srcMatches) {
|
||||
@@ -100,8 +100,7 @@ function fuzzyMatchRecursive(
|
||||
firstMatch = false;
|
||||
}
|
||||
|
||||
const recursiveMatches = [];
|
||||
const [matched, recursiveScore] = fuzzyMatchRecursive(
|
||||
const [matched, recursiveScore, recursiveMatches] = fuzzyMatchRecursive(
|
||||
pattern,
|
||||
str,
|
||||
patternCurIndex,
|
||||
@@ -181,17 +180,17 @@ function fuzzyMatchRecursive(
|
||||
// Return best result
|
||||
if (recursiveMatch && (!matched || bestRecursiveScore > outScore)) {
|
||||
// Recursive score is better than "this"
|
||||
matches = [...bestRecursiveMatches];
|
||||
matches = bestRecursiveMatches;
|
||||
outScore = bestRecursiveScore;
|
||||
return [true, outScore, calcMatchRanges(matches)];
|
||||
return [true, outScore, matches];
|
||||
} else if (matched) {
|
||||
// "this" score is better than recursive
|
||||
return [true, outScore, calcMatchRanges(matches)];
|
||||
return [true, outScore, matches];
|
||||
} else {
|
||||
return [false, outScore];
|
||||
return [false, outScore, matches];
|
||||
}
|
||||
}
|
||||
return [false, outScore];
|
||||
return [false, outScore, matches];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +200,7 @@ function fuzzyMatchRecursive(
|
||||
* @param [number] matches
|
||||
* @returns [[number]]
|
||||
*/
|
||||
function calcMatchRanges(matches) {
|
||||
export function calcMatchRanges(matches) {
|
||||
const ranges = [];
|
||||
let start = matches[0],
|
||||
curr = start;
|
||||
|
||||
24
src/core/lib/JWT.mjs
Normal file
24
src/core/lib/JWT.mjs
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* JWT resources
|
||||
*
|
||||
* @author mt3571 [mt3571@protonmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* List of the JWT algorithms that can be used
|
||||
*/
|
||||
export const JWT_ALGORITHMS = [
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512",
|
||||
"None"
|
||||
];
|
||||
@@ -3,10 +3,11 @@
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import jwt from "jsonwebtoken";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import {JWT_ALGORITHMS} from "../lib/JWT.mjs";
|
||||
|
||||
|
||||
/**
|
||||
* JWT Sign operation
|
||||
@@ -34,18 +35,7 @@ class JWTSign extends Operation {
|
||||
{
|
||||
name: "Signing algorithm",
|
||||
type: "option",
|
||||
value: [
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512",
|
||||
"None"
|
||||
]
|
||||
value: JWT_ALGORITHMS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import jwt from "jsonwebtoken";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import {JWT_ALGORITHMS} from "../lib/JWT.mjs";
|
||||
|
||||
|
||||
/**
|
||||
* JWT Verify operation
|
||||
@@ -27,7 +28,7 @@ class JWTVerify extends Operation {
|
||||
this.outputType = "JSON";
|
||||
this.args = [
|
||||
{
|
||||
name: "Private/Secret Key",
|
||||
name: "Public/Secret Key",
|
||||
type: "text",
|
||||
value: "secret"
|
||||
},
|
||||
@@ -41,14 +42,11 @@ class JWTVerify extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
const [key] = args;
|
||||
const algos = JWT_ALGORITHMS;
|
||||
algos[algos.indexOf("None")] = "none";
|
||||
|
||||
try {
|
||||
const verified = jwt.verify(input, key, { algorithms: [
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"none"
|
||||
]});
|
||||
const verified = jwt.verify(input, key, { algorithms: algos });
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(verified, "name") && verified.name === "JsonWebTokenError") {
|
||||
throw new OperationError(verified.message);
|
||||
|
||||
@@ -97,12 +97,13 @@ class HTMLOperation {
|
||||
* @param {[[number]]} descIdxs - Indexes of the search strings in the operation description [[start, length]]
|
||||
*/
|
||||
highlightSearchStrings(nameIdxs, descIdxs) {
|
||||
if (nameIdxs.length) {
|
||||
if (nameIdxs.length && typeof nameIdxs[0][0] === "number") {
|
||||
let opName = "",
|
||||
pos = 0;
|
||||
|
||||
nameIdxs.forEach(idxs => {
|
||||
const [start, length] = idxs;
|
||||
if (typeof start !== "number") return;
|
||||
opName += this.name.slice(pos, start) + "<b>" +
|
||||
this.name.slice(start, start + length) + "</b>";
|
||||
pos = start + length;
|
||||
@@ -111,7 +112,7 @@ class HTMLOperation {
|
||||
this.name = opName;
|
||||
}
|
||||
|
||||
if (this.description && descIdxs.length) {
|
||||
if (this.description && descIdxs.length && descIdxs[0][0] >= 0) {
|
||||
// Find HTML tag offsets
|
||||
const re = /<[^>]+>/g;
|
||||
let match;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import HTMLOperation from "../HTMLOperation.mjs";
|
||||
import Sortable from "sortablejs";
|
||||
import {fuzzyMatch} from "../../core/lib/FuzzySearch.mjs";
|
||||
import {fuzzyMatch, calcMatchRanges} from "../../core/lib/FuzzySearch.mjs";
|
||||
|
||||
|
||||
/**
|
||||
@@ -109,8 +109,6 @@ class OperationsWaiter {
|
||||
const matchedOps = [];
|
||||
const matchedDescs = [];
|
||||
|
||||
const searchStr = inStr.toLowerCase();
|
||||
|
||||
for (const opName in this.app.operations) {
|
||||
const op = this.app.operations[opName];
|
||||
|
||||
@@ -118,12 +116,12 @@ class OperationsWaiter {
|
||||
const [nameMatch, score, idxs] = fuzzyMatch(inStr, opName);
|
||||
|
||||
// Match description based on exact match
|
||||
const descPos = op.description.toLowerCase().indexOf(searchStr);
|
||||
const descPos = op.description.toLowerCase().indexOf(inStr.toLowerCase());
|
||||
|
||||
if (nameMatch || descPos >= 0) {
|
||||
const operation = new HTMLOperation(opName, this.app.operations[opName], this.app, this.manager);
|
||||
if (highlight) {
|
||||
operation.highlightSearchStrings(idxs || [], [[descPos, searchStr.length]]);
|
||||
operation.highlightSearchStrings(calcMatchRanges(idxs) || [], [[descPos, inStr.length]]);
|
||||
}
|
||||
|
||||
if (nameMatch) {
|
||||
|
||||
@@ -218,7 +218,7 @@ module.exports = {
|
||||
.clearValue("#search")
|
||||
.setValue("#search", "md5")
|
||||
.useXpath()
|
||||
.waitForElementVisible("//ul[@id='search-results']//u[text()='MD5']", 1000);
|
||||
.waitForElementVisible("//ul[@id='search-results']//b[text()='MD5']", 1000);
|
||||
},
|
||||
|
||||
after: browser => {
|
||||
|
||||
@@ -14,10 +14,9 @@ const outputObject = JSON.stringify({
|
||||
iat: 1
|
||||
}, null, 4);
|
||||
|
||||
const invalidAlgorithm = "JsonWebTokenError: invalid algorithm";
|
||||
|
||||
const hsKey = "secret_cat";
|
||||
const rsKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
/* Retaining private key as a comment
|
||||
const rsPriv = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
|
||||
33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
|
||||
+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
|
||||
@@ -32,11 +31,24 @@ fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
|
||||
Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
|
||||
FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
|
||||
-----END RSA PRIVATE KEY-----`;
|
||||
const esKey = `-----BEGIN PRIVATE KEY-----
|
||||
*/
|
||||
const rsPub = `-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd
|
||||
UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs
|
||||
HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D
|
||||
o2kQ+X5xK9cipRgEKwIDAQAB
|
||||
-----END PUBLIC KEY-----`;
|
||||
/* Retaining private key as a comment
|
||||
const esPriv = `-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2
|
||||
OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r
|
||||
1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G
|
||||
-----END PRIVATE KEY-----`;
|
||||
*/
|
||||
const esPub = `-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9
|
||||
q9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg==
|
||||
-----END PUBLIC KEY-----`;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
@@ -53,22 +65,22 @@ TestRegister.addTests([
|
||||
{
|
||||
name: "JWT Verify: RS",
|
||||
input: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.MjEJhtZk2nXzigi24piMzANmrj3mILHJcDl0xOjl5a8EgdKVL1oaMEjTkMQp5RA8YrqeRBFaX-BGGCKOXn5zPY1DJwWsBUyN9C-wGR2Qye0eogH_3b4M9EW00TPCUPXm2rx8URFj7Wg9VlsmrGzLV2oKkPgkVxuFSxnpO3yjn1Y",
|
||||
expectedOutput: invalidAlgorithm,
|
||||
expectedOutput: outputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Verify",
|
||||
args: [rsKey],
|
||||
args: [rsPub],
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "JWT Verify: ES",
|
||||
input: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJTdHJpbmciOiJTb21lU3RyaW5nIiwiTnVtYmVyIjo0MiwiaWF0IjoxfQ.WkECT51jSfpRkcpQ4x0h5Dwe7CFBI6u6Et2gWp91HC7mpN_qCFadRpsvJLtKubm6cJTLa68xtei0YrDD8fxIUA",
|
||||
expectedOutput: invalidAlgorithm,
|
||||
expectedOutput: outputObject,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JWT Verify",
|
||||
args: [esKey],
|
||||
args: [esPub],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user