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

Compare commits

...

99 Commits

Author SHA1 Message Date
n1474335
89ca2cc631 6.0.2 2017-09-20 22:26:54 +01:00
n1474335
e2cae035f2 Accessibility checks are now made before trying to access local storage. Fixes #174. 2017-09-20 22:26:47 +01:00
n1474335
c60ec7c170 6.0.1 2017-09-20 01:18:46 +01:00
n1474335
e42b19d324 Removed excess auto-baking 2017-09-20 01:16:15 +01:00
n1474335
3be370aefa 6.0.0 2017-09-20 00:56:32 +01:00
n1474335
b13917fbdc Merge branch 'feature-threading' 2017-09-20 00:55:37 +01:00
n1474335
9028761821 Loading message fade and cancelBake bugfix 2017-09-20 00:48:37 +01:00
n1474335
f6b52b7c82 Operations can now set options from within the worker 2017-09-20 00:37:57 +01:00
n1474335
13f07abb8a Highlighting now works with the web worker 2017-09-19 23:34:03 +01:00
n1474335
8c960f0661 Moved worker handling code from App.js to WorkerWaiter.js 2017-09-17 19:27:02 +01:00
n1474335
77203a4363 Excluded MetaConfig from JSDoc 2017-09-17 14:59:11 +01:00
n1474335
d3246b7c8b Merged upstream master 2017-09-17 14:53:17 +01:00
n1474335
c93edec55b Switched to val-loader and compiling MetaConfig 2017-09-17 13:47:33 +01:00
n1474335
83d258c396 5.20.0 2017-09-14 15:06:11 +00:00
n1474335
81acb5bdab Merge branch 'feature-hashing' 2017-09-14 15:01:29 +00:00
n1474335
0b79019e0f Added test file. 2017-09-14 14:59:28 +00:00
n1474335
be07298741 Added tests for all hashing operations 2017-09-14 14:54:56 +00:00
n1474335
2d779fdcd0 Added SHA2 512/224 and 512/256 variants as well as RIPEMD 128, 160, 256 and 320. 2017-09-14 14:53:46 +00:00
n1474335
35382faf28 Updated all dependencies and set node version to 8.4 to fix docstrap bug in travis builds (until it is fixed) 2017-09-14 10:20:16 +00:00
n1474335
dba0b104ab Added docs to GH Pages 2017-09-13 15:21:31 +00:00
n1474335
174cabdc74 Added 'CRC-16 Checksum' operation 2017-09-12 15:50:46 +00:00
n1474335
3c52a9faab Added Keccak and Shake to 'Generate all hashes' operation 2017-09-12 15:39:48 +00:00
n1474335
73561993a7 Added SHA3, Keccak and Shake hashing algorithms 2017-09-12 15:31:51 +00:00
n1474335
6e875393d9 Merged all SHA-2 operations into one with a size argument 2017-09-12 14:48:56 +00:00
n1474335
bbd85a491b Added MD6 to 'Generate all hashes' operation 2017-09-12 14:23:36 +00:00
n1474335
a736be7ca8 Added MD6 operation. Closes #53 2017-09-12 14:20:05 +00:00
n1474335
f1fe0b944f 5.19.3 2017-09-07 10:01:31 +00:00
n1474335
c1e40dd109 Fixed typo in .travis.yml 2017-09-07 10:01:12 +00:00
n1474335
73823e3eb9 Improved domain name regex 2017-09-06 16:43:30 +00:00
n1474335
bf833991bf 5.19.2 2017-09-06 16:09:36 +00:00
n1474335
615357c977 Corrected travis config logic 2017-09-06 16:06:37 +00:00
n1474335
19f23127b9 Updated travis config to create a new branch when building a tagged release 2017-09-06 16:04:11 +00:00
n1474335
2ea6d9437f 5.19.1 2017-09-06 10:28:41 +00:00
n1474335
833b6d67a6 Updated package-lock.json to fix tagged builds 2017-09-06 10:28:35 +00:00
n1474335
04c1adc5f0 5.19.0 2017-09-05 17:59:16 +00:00
n1474335
8e8f6a0284 Merge branch 'feature-otp' 2017-09-05 17:59:02 +00:00
n1474335
68bf1d123e Added 'Generate HOTP' and 'Generate TOTP' operations 2017-09-05 17:53:54 +00:00
n1474335
2c03689195 5.18.1 2017-09-05 17:26:29 +00:00
n1474335
45f41b1140 Merge branch 'bug-number-input-change' 2017-09-05 17:21:49 +00:00
n1474335
8fa6f3f45c Fixed bug where clicking up and down arrows on numeric inputs would not trigger an auto-bake 2017-09-05 16:51:57 +00:00
n1474335
78a842deb7 5.18.0 2017-09-05 15:37:18 +00:00
n1474335
3657ff4f79 Merge branch 'feature-bitshift' 2017-09-05 15:37:10 +00:00
n1474335
d4d12c3db0 Whitespace is now removed from hex and binary even when the delimiter is set to 'None' 2017-09-05 14:30:06 +00:00
n1474335
1b628ac213 Added 'Bit shift left' and 'Bit shift right' operations 2017-09-05 14:26:09 +00:00
n1474335
5fcc259efb Merge branch 'Synchro-master' 2017-09-04 15:22:17 +00:00
Marcus Bointon
9545205f19 Optimise PNGs 2017-09-04 12:22:12 +02:00
n1474335
cb6708c02e XOR Brute Force operation now has a variable key length 2017-08-31 00:24:24 +01:00
n1474335
4f403d4450 5.17.0 2017-08-30 15:57:58 +00:00
n1474335
f2d8f930fb Merge branch 'bwhitn-vbe' 2017-08-30 15:57:18 +00:00
n1474335
4a86340d50 Tidied up 'Microsoft Script Decoder' operation 2017-08-30 15:56:51 +00:00
bwhitn
f8e9e9ba85 added sample to description 2017-08-29 12:04:15 -07:00
bwhitn
934ed1af09 Fixed spelling errors, syntax errors, and improved the test for script decoding 2017-08-29 10:46:34 -07:00
bwhitn
0fc2a219a7 Changed the name. Small logic change. Changed from split join to regex replace. 2017-08-28 17:55:54 -04:00
bwhitn
aa5939c051 Took out logging call. My bad. 2017-08-27 20:53:53 -04:00
bwhitn
9c5f06101e Fixed the replace statements 2017-08-27 18:45:42 -04:00
bwhitn
2a7c0252a0 Fixed regex issue 2017-08-27 11:49:28 -04:00
bwhitn
414726ecd4 Fixed small syntax error 2017-08-27 09:44:26 -04:00
bwhitn
fdc8a15595 Added Decode VBE 2017-08-27 09:29:26 -04:00
n1474335
d012fd3a65 5.16.3 2017-08-25 11:53:08 +00:00
n1474335
a5ed824674 Merge branch 'bug-substitute' 2017-08-25 11:50:07 +00:00
n1474335
d6705c682f Fixed bug in Substitute where commas would not encode correctly 2017-08-25 11:44:31 +00:00
n1474335
d68523a54e Added status message mechanism for the Worker to report to the app 2017-08-25 01:24:12 +01:00
n1474335
6af82680f1 Fixed tests and Node version to work with modules 2017-08-25 00:44:22 +01:00
n1474335
a4aee761c2 Added module and threading support for the inline version. 2017-08-25 00:25:49 +01:00
n1474335
33b606d48f 5.16.2 2017-08-21 15:25:41 +00:00
n1474335
cc44be7ef9 Fixed recipe saving 2017-08-21 15:25:35 +00:00
n1474335
e0eb972a54 Operations with no arguments can now be added to the recipe without causing errors 2017-08-18 16:12:49 +00:00
n1474335
19c54a99cd Improved web app title construction 2017-08-18 16:01:55 +00:00
n1474335
9d60ec22ee Updated links in index.html 2017-08-18 15:55:04 +01:00
n1474335
cb4eeccfd3 Updated links in README 2017-08-18 15:47:38 +01:00
n1474335
62e50caa99 5.16.1 2017-08-16 14:11:55 +00:00
n1474335
0192566d19 Improved recipe config generation for complex objects. Fixes #180 2017-08-16 14:11:50 +00:00
n1474335
8a8b70f2ab 5.16.0 2017-08-16 13:01:50 +00:00
n1474335
af311001cf Merge branch 'feature-pretty-recipe-format' 2017-08-16 13:01:08 +00:00
n1474335
040229418e 5.15.0 2017-08-15 17:32:31 +00:00
n1474335
c259963542 Fixed string escape test configs 2017-08-15 17:32:21 +00:00
n1474335
ca75f7fa0b Merge branch 'artemisbot-features/string_escape_unescape' 2017-08-15 17:30:12 +00:00
n1474335
4b22a409e7 Tidied up string escape operations 2017-08-15 17:29:48 +00:00
n1474335
55806db00f Merge branch 'features/string_escape_unescape' of https://github.com/artemisbot/CyberChef into artemisbot-features/string_escape_unescape 2017-08-15 17:16:39 +00:00
n1474335
83c757ebd4 Lint 2017-08-15 17:12:09 +00:00
n1474335
a19b02aa8c Updated URL regexes to match more unescaped special characters 2017-08-15 16:44:45 +00:00
n1474335
cf1ba60a10 Added new 'pretty' recipe format to make URLs more readable 2017-08-15 16:26:42 +00:00
n1474335
2a4c9afdf2 5.14.0 2017-08-10 12:42:00 +00:00
n1474335
ab76933158 Merge branch 'feature-themes' 2017-08-10 12:41:18 +00:00
n1474335
d4d7bcab7a Added GeoCities theme 2017-08-10 12:35:30 +00:00
n1474335
a61cf6a68a Added module framework 2017-08-09 20:09:23 +01:00
Matt C
6698a2ac13 Added tests + fixes for PR
- actually removed prev func
- shuffled some stuff around
2017-08-07 16:08:50 +01:00
Matt C
9161cc693d Removes need for runParseEscapedString
- Fixes examples
- Actually makes it work
2017-08-04 15:54:00 +01:00
Matt C
3186335f47 Merge Vel0z/string_escaping_unescaping
Updated to new project format
2017-08-04 11:50:45 +01:00
n1474335
9f19afc943 Removed auto-bake threshold as long bakes can now be cancelled manually 2017-07-30 12:51:21 +01:00
n1474335
6742bef289 Separated out Diff and Windows Filetime operations into their own namespaces as they rely on libraries not used by the rest of the operations in their group 2017-07-30 12:36:50 +01:00
n1474335
e977a1006c Merge branch 'master' into feature-threading 2017-07-28 16:55:07 +01:00
n1474335
f1ebab0c2d Added the ability to cancel bakes 2017-07-28 16:38:53 +01:00
n1474335
98884d851a Added staleness indicator to the output 2017-07-28 15:43:23 +01:00
n1474335
78d0369e71 Added loader for long bakes and improved initial loading sequence 2017-07-28 14:43:44 +01:00
n1474335
cc3aad17e1 OperationConfig now loaded into App via value-loader so that operation code is only included in the worker 2017-07-16 23:33:47 +01:00
n1474335
760ab688b2 Create ChefWorker and move bake process into it 2017-07-05 00:14:47 +01:00
n1474335
ff78c72d54 Configured webpack-dev-server 2017-07-03 23:15:57 +01:00
Dale Myers
fadd7158ed Add string escape/unescape operations
These operations are useful for taking the contents of a string, and making it
suitable for use as a stand alone string. For example, in an IDE you might see
a string which is represented as: "Say \"Hello\"". The escaped double quotes
are shown to make it clear that they do not end the string, despite the fact
that they are not truly part of the string. In order to get the raw string, you
would need to copy this, then manually remove the backslashes. The new
String_.run_unescape operation does this automatically.

The String_.run_escape is the inverse. It allows you to take a string like the
one above, and paste it between two quotes without having to manually escape
it.
2017-01-23 21:39:08 +00:00
111 changed files with 5875 additions and 2887 deletions

View File

@@ -1 +1,2 @@
src/core/lib/**
src/core/config/MetaConfig.js

View File

@@ -97,6 +97,9 @@
"COMPILE_TIME": false,
"COMPILE_MSG": false,
"PKG_VERSION": false
"PKG_VERSION": false,
"ENVIRONMENT_IS_WORKER": false,
"ENVIRONMENT_IS_NODE": false,
"ENVIRONMENT_IS_WEB": false
}
}

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ docs/*
!docs/*.conf.json
!docs/*.ico
.vscode
src/core/config/MetaConfig.js

View File

@@ -1,6 +1,6 @@
language: node_js
node_js:
- node
- "8.4"
install: npm install
before_script:
- npm install -g grunt
@@ -22,7 +22,7 @@ deploy:
repo: gchq/CyberChef
branch: master
- provider: releases
skip_cleaup: true
skip_cleanup: true
api_key:
secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA="
file:

View File

@@ -1,8 +1,16 @@
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const NodeExternals = require("webpack-node-externals");
const Inliner = require("web-resource-inliner");
const fs = require("fs");
/**
* Grunt configuration for building the app in various formats.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
module.exports = function (grunt) {
grunt.file.defaultEncoding = "utf8";
@@ -11,15 +19,15 @@ module.exports = function (grunt) {
// Tasks
grunt.registerTask("dev",
"A persistent task which creates a development build whenever source files are modified.",
["clean:dev", "webpack:webDev"]);
["clean:dev", "concurrent:dev"]);
grunt.registerTask("node",
"Compiles CyberChef into a single NodeJS module.",
["clean:node", "webpack:node", "chmod:build"]);
["clean:node", "webpack:metaConf", "webpack:node", "chmod:build"]);
grunt.registerTask("test",
"A task which runs all the tests in test/tests.",
["clean:test", "webpack:tests", "execute:test"]);
["clean:test", "webpack:metaConf", "webpack:tests", "execute:test"]);
grunt.registerTask("docs",
"Compiles documentation in the /docs directory.",
@@ -27,7 +35,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", "webpack:webProd", "inline", "chmod"]);
["eslint", "clean:prod", "webpack:metaConf", "webpack:web", "inline", "chmod"]);
grunt.registerTask("default",
"Lints the code base",
@@ -35,8 +43,10 @@ module.exports = function (grunt) {
grunt.registerTask("inline",
"Compiles a production build of CyberChef into a single, portable web page.",
runInliner);
["webpack:webInline", "runInliner", "clean:inlineScripts"]);
grunt.registerTask("runInliner", runInliner);
grunt.registerTask("doc", "docs");
grunt.registerTask("tests", "test");
grunt.registerTask("lint", "eslint");
@@ -52,31 +62,28 @@ module.exports = function (grunt) {
grunt.loadNpmTasks("grunt-exec");
grunt.loadNpmTasks("grunt-execute");
grunt.loadNpmTasks("grunt-accessibility");
grunt.loadNpmTasks("grunt-concurrent");
// Project configuration
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
banner = "/**\n" +
"* CyberChef - The Cyber Swiss Army Knife\n" +
"*\n" +
"* @copyright Crown Copyright 2016\n" +
"* @license Apache-2.0\n" +
"*\n" +
"* Copyright 2016 Crown Copyright\n" +
"*\n" +
'* Licensed under the Apache License, Version 2.0 (the "License");\n' +
"* you may not use this file except in compliance with the License.\n" +
"* You may obtain a copy of the License at\n" +
"*\n" +
"* http://www.apache.org/licenses/LICENSE-2.0\n" +
"*\n" +
"* Unless required by applicable law or agreed to in writing, software\n" +
'* distributed under the License is distributed on an "AS IS" BASIS,\n' +
"* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
"* See the License for the specific language governing permissions and\n" +
"* limitations under the License.\n" +
"*/\n",
pkg = grunt.file.readJSON("package.json");
pkg = grunt.file.readJSON("package.json"),
webpackConfig = require("./webpack.config.js"),
BUILD_CONSTANTS = {
COMPILE_TIME: JSON.stringify(compileTime),
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
PKG_VERSION: JSON.stringify(pkg.version),
ENVIRONMENT_IS_WORKER: function() {
return typeof importScripts === "function";
},
ENVIRONMENT_IS_NODE: function() {
return typeof process === "object" && typeof require === "function";
},
ENVIRONMENT_IS_WEB: function() {
return typeof window === "object";
}
},
moduleEntryPoints = listEntryModules();
/**
* Compiles a production build of CyberChef into a single, portable web page.
@@ -105,20 +112,36 @@ module.exports = function (grunt) {
});
}
/**
* Generates an entry list for all the modules.
*/
function listEntryModules() {
const path = "./src/core/config/modules/";
let entryModules = {};
fs.readdirSync(path).forEach(file => {
if (file !== "Default.js" && file !== "OpModules.js")
entryModules[file.split(".js")[0]] = path + file;
});
return entryModules;
}
grunt.initConfig({
clean: {
dev: ["build/dev/*"],
prod: ["build/prod/*"],
test: ["build/test/*"],
node: ["build/node/*"],
docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico"],
dev: ["build/dev/*", "src/core/config/MetaConfig.js"],
prod: ["build/prod/*", "src/core/config/MetaConfig.js"],
test: ["build/test/*", "src/core/config/MetaConfig.js"],
node: ["build/node/*", "src/core/config/MetaConfig.js"],
docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico", "!docs/*.png"],
inlineScripts: ["build/prod/scripts.js"],
},
eslint: {
options: {
configFile: "./.eslintrc.json"
},
configs: ["Gruntfile.js"],
core: ["src/core/**/*.js", "!src/core/lib/**/*"],
core: ["src/core/**/*.js", "!src/core/lib/**/*", "!src/core/config/MetaConfig.js"],
web: ["src/web/**/*.js"],
node: ["src/node/**/*.js"],
tests: ["test/**/*.js"],
@@ -135,9 +158,16 @@ module.exports = function (grunt) {
src: [
"src/**/*.js",
"!src/core/lib/**/*",
"!src/core/config/MetaConfig.js"
],
}
},
concurrent: {
options: {
logConcurrentOutput: true
},
dev: ["webpack:metaConfDev", "webpack-dev-server:start"]
},
accessibility: {
options: {
accessibilityLevel: "WCAG2A",
@@ -151,114 +181,47 @@ module.exports = function (grunt) {
}
},
webpack: {
options: {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
moment: "moment-timezone"
}),
new webpack.BannerPlugin({
banner: banner,
raw: true,
entryOnly: true
}),
new webpack.DefinePlugin({
COMPILE_TIME: JSON.stringify(compileTime),
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
PKG_VERSION: JSON.stringify(pkg.version)
}),
new ExtractTextPlugin("styles.css"),
],
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader?compact=false"
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: [
{ loader: "css-loader?minimize" },
{ loader: "postcss-loader" },
]
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
use: [
{ loader: "css-loader?minimize" },
{ loader: "postcss-loader" },
{ loader: "less-loader" }
]
})
},
{
test: /\.(ico|eot|ttf|woff|woff2)$/,
loader: "url-loader",
options: {
limit: 10000
}
},
{ // First party images are saved as files to be cached
test: /\.(png|jpg|gif|svg)$/,
exclude: /node_modules/,
loader: "file-loader",
options: {
name: "images/[name].[ext]"
}
},
{ // Third party images are inlined
test: /\.(png|jpg|gif|svg)$/,
exclude: /web\/static/,
loader: "url-loader",
options: {
limit: 10000
}
},
]
},
stats: {
children: false,
warningsFilter: /source-map/
},
node: {
fs: "empty"
}
},
webDev: {
target: "web",
entry: "./src/web/index.js",
options: webpackConfig,
metaConf: {
target: "node",
entry: "./src/core/config/OperationConfig.js",
output: {
filename: "scripts.js",
path: __dirname + "/build/dev"
filename: "MetaConfig.js",
path: __dirname + "/src/core/config/",
library: "MetaConfig",
libraryTarget: "commonjs2",
libraryExport: "default"
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/web/html/index.html",
compileTime: compileTime,
version: pkg.version,
})
],
externals: [NodeExternals()],
},
metaConfDev: {
target: "node",
entry: "./src/core/config/OperationConfig.js",
output: {
filename: "MetaConfig.js",
path: __dirname + "/src/core/config/",
library: "MetaConfig",
libraryTarget: "commonjs2",
libraryExport: "default"
},
externals: [NodeExternals()],
watch: true
},
webProd: {
web: {
target: "web",
entry: "./src/web/index.js",
entry: Object.assign({
main: "./src/web/index.js"
}, moduleEntryPoints),
output: {
filename: "scripts.js",
path: __dirname + "/build/prod"
},
resolve: {
alias: {
"./config/modules/OpModules.js": "./config/modules/Default.js"
}
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.UglifyJsPlugin({
compress: {
"screw_ie8": true,
@@ -268,9 +231,10 @@ module.exports = function (grunt) {
},
comments: false,
}),
new HtmlWebpackPlugin({ // Main version
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/web/html/index.html",
chunks: ["main"],
compileTime: compileTime,
version: pkg.version,
minify: {
@@ -280,7 +244,27 @@ module.exports = function (grunt) {
minifyCSS: true
}
}),
new HtmlWebpackPlugin({ // Inline version
]
},
webInline: {
target: "web",
entry: "./src/web/index.js",
output: {
filename: "scripts.js",
path: __dirname + "/build/prod"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.UglifyJsPlugin({
compress: {
"screw_ie8": true,
"dead_code": true,
"unused": true,
"warnings": false
},
comments: false,
}),
new HtmlWebpackPlugin({
filename: "cyberchef.htm",
template: "./src/web/html/index.html",
compileTime: compileTime,
@@ -302,7 +286,10 @@ module.exports = function (grunt) {
output: {
filename: "index.js",
path: __dirname + "/build/test"
}
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS)
]
},
node: {
target: "node",
@@ -313,21 +300,74 @@ module.exports = function (grunt) {
path: __dirname + "/build/node",
library: "CyberChef",
libraryTarget: "commonjs2"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS)
]
}
},
"webpack-dev-server": {
options: {
webpack: webpackConfig,
overlay: true,
clientLogLevel: "error",
stats: {
children: false,
chunks: false,
modules: false,
warningsFilter: /source-map/,
}
},
start: {
webpack: {
target: "web",
entry: Object.assign({
main: "./src/web/index.js"
}, moduleEntryPoints),
resolve: {
alias: {
"./config/modules/OpModules.js": "./config/modules/Default.js"
}
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/web/html/index.html",
chunks: ["main"],
compileTime: compileTime,
version: pkg.version,
})
]
}
}
},
copy: {
ghPages: {
options: {
process: function (content) {
process: function (content, srcpath) {
// Add Google Analytics code to index.html
content = content.replace("</body></html>",
grunt.file.read("src/web/static/ga.html") + "</body></html>");
return grunt.template.process(content);
}
if (srcpath.indexOf("index.html") >= 0) {
content = content.replace("</body></html>",
grunt.file.read("src/web/static/ga.html") + "</body></html>");
return grunt.template.process(content, srcpath);
} else {
return content;
}
},
noProcess: ["**", "!**/*.html"]
},
src: "build/prod/index.html",
dest: "build/prod/index.html"
files: [
{
src: "build/prod/index.html",
dest: "build/prod/index.html"
},
{
expand: true,
src: "docs/**",
dest: "build/prod/"
}
]
}
},
chmod: {

View File

@@ -88,10 +88,10 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
[1]: https://gchq.github.io/CyberChef
[2]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
[3]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA
[4]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
[5]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
[6]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
[7]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
[8]: https://gchq.github.io/CyberChef/#recipe=%5B%7B%22op%22%3A%22XOR%22%2C%22args%22%3A%5B%7B%22option%22%3A%22Hex%22%2C%22string%22%3A%223a%22%7D%2Cfalse%2Cfalse%5D%7D%2C%7B%22op%22%3A%22To%20Hexdump%22%2C%22args%22%3A%5B%2216%22%2Cfalse%2Cfalse%5D%7D%5D&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
[2]: https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1
[3]: https://gchq.github.io/CyberChef/#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA
[4]: https://gchq.github.io/CyberChef/#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
[5]: https://gchq.github.io/CyberChef/#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
[6]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
[8]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -19,7 +19,7 @@
"outputSourcePath": true,
"dateFormat": "ddd MMM Do YYYY",
"sort": false,
"logoFile": "../build/prod/images/cyberchef-32x32.png",
"logoFile": "cyberchef-32x32.png",
"cleverLinks": false,
"monospaceLinks": false,
"protocol": "html://",

3234
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "5.13.1",
"version": "6.0.2",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -30,67 +30,76 @@
"main": "build/node/CyberChef.js",
"bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^7.1.1",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"css-loader": "^0.28.4",
"css-loader": "^0.28.7",
"exports-loader": "^0.6.4",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.2",
"grunt": ">=0.4.5",
"grunt": ">=1.0.1",
"grunt-accessibility": "~5.0.0",
"grunt-chmod": "~1.1.1",
"grunt-concurrent": "^2.3.1",
"grunt-contrib-clean": "~1.1.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-eslint": "^20.0.0",
"grunt-eslint": "^20.1.0",
"grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.1.0",
"grunt-jsdoc": "^2.1.1",
"grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"imports-loader": "^0.7.1",
"ink-docstrap": "^1.1.4",
"ink-docstrap": "^1.3.0",
"jsdoc-babel": "^0.3.0",
"less": "^2.7.2",
"less-loader": "^4.0.5",
"postcss-css-variables": "^0.7.0",
"postcss-css-variables": "^0.8.0",
"postcss-import": "^10.0.0",
"postcss-loader": "^2.0.5",
"postcss-loader": "^2.0.6",
"style-loader": "^0.18.2",
"url-loader": "^0.5.8",
"web-resource-inliner": "^4.1.0",
"webpack": "^3.4.1",
"webpack-node-externals": "^1.6.0"
"url-loader": "^0.5.9",
"val-loader": "^1.0.2",
"web-resource-inliner": "^4.1.1",
"webpack": "^3.5.6",
"webpack-dev-server": "^2.5.0",
"webpack-node-externals": "^1.6.0",
"worker-loader": "^0.8.0"
},
"dependencies": {
"babel-polyfill": "^6.23.0",
"babel-polyfill": "^6.26.0",
"bootstrap": "^3.3.7",
"bootstrap-colorpicker": "^2.5.1",
"bootstrap-switch": "^3.3.4",
"crypto-api": "^0.6.2",
"crypto-api": "^0.7.3",
"crypto-js": "^3.1.9-1",
"diff": "^3.3.0",
"escodegen": "^1.8.1",
"diff": "^3.3.1",
"escodegen": "^1.9.0",
"esmangle": "^1.0.1",
"esprima": "^4.0.0",
"exif-parser": "^0.1.12",
"google-code-prettify": "^1.0.5",
"jquery": "^3.1.1",
"jquery": "^3.2.1",
"js-crc": "^0.2.0",
"js-sha3": "^0.6.1",
"jsbn": "^1.1.0",
"jsonpath": "^0.2.12",
"jsrsasign": "8.0.3",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
"moment": "^2.18.1",
"moment-timezone": "^0.5.13",
"node-md6": "^0.1.0",
"otp": "^0.1.3",
"sladex-blowfish": "^0.8.1",
"sortablejs": "^1.5.1",
"split.js": "^1.2.0",
"sortablejs": "^1.6.1",
"split.js": "^1.3.5",
"vkbeautify": "^0.99.3",
"xmldom": "^0.1.27",
"xpath": "0.0.24",
"zlibjs": "^0.3.1"
},
"scripts": {
"start": "grunt dev",
"build": "grunt prod",
"test": "grunt test",
"docs": "grunt docs"

View File

@@ -30,7 +30,6 @@ const Chef = function() {
* @returns {string} response.result - The output of the recipe
* @returns {string} response.type - The data type of the result
* @returns {number} response.progress - The position that we have got to in the recipe
* @returns {number} response.options - The app options object (which may have been changed)
* @returns {number} response.duration - The number of ms it took to execute the recipe
* @returns {number} response.error - The error object thrown by a failed operation (false if no error)
*/
@@ -40,12 +39,7 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress,
containsFc = recipe.containsFlowControl(),
error = false;
// Reset attemptHighlight flag
if (options.hasOwnProperty("attemptHighlight")) {
options.attemptHighlight = true;
}
if (containsFc) options.attemptHighlight = false;
if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
// Clean up progress
if (progress >= recipeConfig.length) {
@@ -86,7 +80,6 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress,
this.dish.get(Dish.STRING),
type: Dish.enumLookup(this.dish.type),
progress: progress,
options: options,
duration: new Date().getTime() - startTime,
error: error
};
@@ -123,4 +116,38 @@ Chef.prototype.silentBake = function(recipeConfig) {
return new Date().getTime() - startTime;
};
/**
* Calculates highlight offsets if possible.
*
* @param {Object[]} recipeConfig
* @param {string} direction
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
* @returns {Object}
*/
Chef.prototype.calculateHighlights = function(recipeConfig, direction, pos) {
const recipe = new Recipe(recipeConfig);
const highlights = recipe.generateHighlightList();
if (!highlights) return false;
for (let i = 0; i < highlights.length; i++) {
// Remove multiple highlights before processing again
pos = [pos[0]];
const func = direction === "forward" ? highlights[i].f : highlights[i].b;
if (typeof func == "function") {
pos = func(pos, highlights[i].args);
}
}
return {
pos: pos,
direction: direction
};
};
export default Chef;

178
src/core/ChefWorker.js Normal file
View File

@@ -0,0 +1,178 @@
/**
* Web Worker to handle communications between the front-end and the core.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import "babel-polyfill";
import Chef from "./Chef.js";
import OperationConfig from "./config/MetaConfig.js";
import OpModules from "./config/modules/Default.js";
// Set up Chef instance
self.chef = new Chef();
self.OpModules = OpModules;
self.OperationConfig = OperationConfig;
// Tell the app that the worker has loaded and is ready to operate
self.postMessage({
action: "workerLoaded",
data: {}
});
/**
* Respond to message from parent thread.
*
* Messages should have the following format:
* {
* action: "bake" | "silentBake",
* data: {
* input: {string},
* recipeConfig: {[Object]},
* options: {Object},
* progress: {number},
* step: {boolean}
* } | undefined
* }
*/
self.addEventListener("message", function(e) {
// Handle message
const r = e.data;
switch (r.action) {
case "bake":
bake(r.data);
break;
case "silentBake":
silentBake(r.data);
break;
case "docURL":
// Used to set the URL of the current document so that scripts can be
// imported into an inline worker.
self.docURL = r.data;
break;
case "highlight":
calculateHighlights(
r.data.recipeConfig,
r.data.direction,
r.data.pos
);
break;
default:
break;
}
});
/**
* Baking handler
*
* @param {Object} data
*/
async function bake(data) {
// Ensure the relevant modules are loaded
loadRequiredModules(data.recipeConfig);
try {
const response = await self.chef.bake(
data.input, // The user's input
data.recipeConfig, // The configuration of the recipe
data.options, // Options set by the user
data.progress, // The current position in the recipe
data.step // Whether or not to take one step or execute the whole recipe
);
self.postMessage({
action: "bakeSuccess",
data: response
});
} catch (err) {
self.postMessage({
action: "bakeError",
data: err.message
});
}
}
/**
* Silent baking handler
*/
function silentBake(data) {
const duration = self.chef.silentBake(data.recipeConfig);
self.postMessage({
action: "silentBakeComplete",
data: duration
});
}
/**
* Checks that all required modules are loaded and loads them if not.
*
* @param {Object} recipeConfig
*/
function loadRequiredModules(recipeConfig) {
recipeConfig.forEach(op => {
let module = self.OperationConfig[op.op].module;
if (!OpModules.hasOwnProperty(module)) {
console.log("Loading module " + module);
self.sendStatusMessage("Loading module " + module);
self.importScripts(self.docURL + "/" + module + ".js");
}
});
}
/**
* Calculates highlight offsets if possible.
*
* @param {Object[]} recipeConfig
* @param {string} direction
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
*/
function calculateHighlights(recipeConfig, direction, pos) {
pos = self.chef.calculateHighlights(recipeConfig, direction, pos);
self.postMessage({
action: "highlightsCalculated",
data: pos
});
}
/**
* Send status update to the app.
*
* @param {string} msg
*/
self.sendStatusMessage = function(msg) {
self.postMessage({
action: "statusMessage",
data: msg
});
};
/**
* Send an option value update to the app.
*
* @param {string} option
* @param {*} value
*/
self.setOption = function(option, value) {
self.postMessage({
action: "optionUpdate",
data: {
option: option,
value: value
}
});
};

View File

@@ -13,22 +13,6 @@ import Dish from "./Dish.js";
*/
const FlowControl = {
/**
* @constant
* @default
*/
FORK_DELIM: "\\n",
/**
* @constant
* @default
*/
MERGE_DELIM: "\\n",
/**
* @constant
* @default
*/
FORK_IGNORE_ERRORS: false,
/**
* Fork operation.
*
@@ -106,17 +90,6 @@ const FlowControl = {
},
/**
* @constant
* @default
*/
JUMP_NUM: 0,
/**
* @constant
* @default
*/
MAX_JUMPS: 10,
/**
* Jump operation.
*

View File

@@ -1,5 +1,7 @@
import Dish from "./Dish.js";
import Ingredient from "./Ingredient.js";
import OperationConfig from "./config/MetaConfig.js";
import OpModules from "./config/modules/OpModules.js";
/**
@@ -11,10 +13,10 @@ import Ingredient from "./Ingredient.js";
*
* @class
* @param {string} operationName
* @param {Object} operationConfig
*/
const Operation = function(operationName, operationConfig) {
const Operation = function(operationName) {
this.name = operationName;
this.module = "";
this.description = "";
this.inputType = -1;
this.outputType = -1;
@@ -25,8 +27,8 @@ const Operation = function(operationName, operationConfig) {
this.disabled = false;
this.ingList = [];
if (operationConfig) {
this._parseConfig(operationConfig);
if (OperationConfig.hasOwnProperty(this.name)) {
this._parseConfig(OperationConfig[this.name]);
}
};
@@ -38,19 +40,28 @@ const Operation = function(operationName, operationConfig) {
* @param {Object} operationConfig
*/
Operation.prototype._parseConfig = function(operationConfig) {
this.module = operationConfig.module;
this.description = operationConfig.description;
this.inputType = Dish.typeEnum(operationConfig.inputType);
this.outputType = Dish.typeEnum(operationConfig.outputType);
this.run = operationConfig.run;
this.highlight = operationConfig.highlight;
this.highlightReverse = operationConfig.highlightReverse;
this.flowControl = operationConfig.flowControl;
this.run = OpModules[this.module][this.name];
for (let a = 0; a < operationConfig.args.length; a++) {
const ingredientConfig = operationConfig.args[a];
const ingredient = new Ingredient(ingredientConfig);
this.addIngredient(ingredient);
}
if (this.highlight === "func") {
this.highlight = OpModules[this.module][`${this.name}-highlight`];
}
if (this.highlightReverse === "func") {
this.highlightReverse = OpModules[this.module][`${this.name}-highlightReverse`];
}
};

View File

@@ -1,5 +1,4 @@
import Operation from "./Operation.js";
import OperationConfig from "./config/OperationConfig.js";
/**
@@ -30,8 +29,7 @@ const Recipe = function(recipeConfig) {
Recipe.prototype._parseConfig = function(recipeConfig) {
for (let c = 0; c < recipeConfig.length; c++) {
const operationName = recipeConfig[c].op;
const operationConfig = OperationConfig[operationName];
const operation = new Operation(operationName, operationConfig);
const operation = new Operation(operationName);
operation.setIngValues(recipeConfig[c].args);
operation.setBreakpoint(recipeConfig[c].breakpoint);
operation.setDisabled(recipeConfig[c].disabled);
@@ -217,4 +215,37 @@ Recipe.prototype.fromString = function(recipeStr) {
this._parseConfig(recipeConfig);
};
/**
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
* entire recipe supports highlighting.
*
* @returns {Object[]} highlights
* @returns {function} highlights[].f
* @returns {function} highlights[].b
* @returns {Object[]} highlights[].args
*/
Recipe.prototype.generateHighlightList = function() {
const highlights = [];
for (let i = 0; i < this.opList.length; i++) {
let op = this.opList[i];
if (op.isDisabled()) continue;
// If any breakpoints are set, do not attempt to highlight
if (op.isBreakpoint()) return false;
// If any of the operations do not support highlighting, fail immediately.
if (op.highlight === false || op.highlight === undefined) return false;
highlights.push({
f: op.highlight,
b: op.highlightReverse,
args: op.getIngValues()
});
}
return highlights;
};
export default Recipe;

View File

@@ -234,7 +234,7 @@ const Utils = {
* @returns {string}
*/
printable: function(str, preserveWs) {
if (typeof window !== "undefined" && window.app && !window.app.options.treatAsUtf8) {
if (ENVIRONMENT_IS_WEB() && window.app && !window.app.options.treatAsUtf8) {
str = Utils.byteArrayToChars(Utils.strToByteArray(str));
}
@@ -384,8 +384,12 @@ const Utils = {
let wordArray = CryptoJS.enc.Utf8.parse(str),
byteArray = Utils.wordArrayToByteArray(wordArray);
if (typeof window !== "undefined" && str.length !== wordArray.sigBytes) {
window.app.options.attemptHighlight = false;
if (str.length !== wordArray.sigBytes) {
if (ENVIRONMENT_IS_WORKER()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
window.app.options.attemptHighlight = false;
}
}
return byteArray;
},
@@ -448,8 +452,13 @@ const Utils = {
let wordArray = new CryptoJS.lib.WordArray.init(words, byteArray.length),
str = CryptoJS.enc.Utf8.stringify(wordArray);
if (typeof window !== "undefined" && str.length !== wordArray.sigBytes)
window.app.options.attemptHighlight = false;
if (str.length !== wordArray.sigBytes) {
if (ENVIRONMENT_IS_WORKER()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
window.app.options.attemptHighlight = false;
}
}
return str;
} catch (err) {
// If it fails, treat it as ANSI
@@ -843,6 +852,139 @@ const Utils = {
},
/**
* Encodes a URI fragment (#) or query (?) using a minimal amount of percent-encoding.
*
* RFC 3986 defines legal characters for the fragment and query parts of a URL to be as follows:
*
* fragment = *( pchar / "/" / "?" )
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*
* Meaning that the list of characters that need not be percent-encoded are alphanumeric plus:
* -._~!$&'()*+,;=:@/?
*
* & and = are still escaped as they are used to serialise the key-value pairs in CyberChef
* fragments. + is also escaped so as to prevent it being decoded to a space.
*
* @param {string} str
* @returns {string}
*/
encodeURIFragment: function(str) {
const LEGAL_CHARS = {
"%2D": "-",
"%2E": ".",
"%5F": "_",
"%7E": "~",
"%21": "!",
"%24": "$",
//"%26": "&",
"%27": "'",
"%28": "(",
"%29": ")",
"%2A": "*",
//"%2B": "+",
"%2C": ",",
"%3B": ";",
//"%3D": "=",
"%3A": ":",
"%40": "@",
"%2F": "/",
"%3F": "?"
};
str = encodeURIComponent(str);
return str.replace(/%[0-9A-F]{2}/g, function (match) {
return LEGAL_CHARS[match] || match;
});
},
/**
* Generates a "pretty" recipe format from a recipeConfig object.
*
* "Pretty" CyberChef recipe formats are designed to be included in the fragment (#) or query (?)
* parts of the URL. They can also be loaded into CyberChef through the 'Load' interface. In order
* to make this format as readable as possible, various special characters are used unescaped. This
* reduces the amount of percent-encoding included in the URL which is typically difficult to read,
* as well as substantially increasing the overall length. These characteristics can be quite
* offputting for users.
*
* @param {Object[]} recipeConfig
* @param {boolean} newline - whether to add a newline after each operation
* @returns {string}
*/
generatePrettyRecipe: function(recipeConfig, newline) {
let prettyConfig = "",
name = "",
args = "",
disabled = "",
bp = "";
recipeConfig.forEach(op => {
name = op.op.replace(/ /g, "_");
args = JSON.stringify(op.args)
.slice(1, -1) // Remove [ and ] as they are implied
// We now need to switch double-quoted (") strings to single-quotes (') as these do not
// need to be percent-encoded.
.replace(/'/g, "\\'") // Escape single quotes
.replace(/\\"/g, '"') // Unescape double quotes
.replace(/(^|,|{|:)"/g, "$1'") // Replace opening " with '
.replace(/"(,|:|}|$)/g, "'$1"); // Replace closing " with '
disabled = op.disabled ? "/disabled": "";
bp = op.breakpoint ? "/breakpoint" : "";
prettyConfig += `${name}(${args}${disabled}${bp})`;
if (newline) prettyConfig += "\n";
});
return prettyConfig;
},
/**
* Converts a recipe string to the JSON representation of the recipe.
* Accepts either stringified JSON or bespoke "pretty" recipe format.
*
* @param {string} recipe
* @returns {Object[]}
*/
parseRecipeConfig: function(recipe) {
recipe = recipe.trim();
if (recipe.length === 0) return [];
if (recipe[0] === "[") return JSON.parse(recipe);
// Parse bespoke recipe format
recipe = recipe.replace(/\n/g, "");
let m,
recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/])*)(\/[^)]+)?\)/g,
recipeConfig = [],
args;
while ((m = recipeRegex.exec(recipe))) {
// Translate strings in args back to double-quotes
args = m[2]
.replace(/"/g, '\\"') // Escape double quotes
.replace(/(^|,|{|:)'/g, '$1"') // Replace opening ' with "
.replace(/([^\\])'(,|:|}|$)/g, '$1"$2') // Replace closing ' with "
.replace(/\\'/g, "'"); // Unescape single quotes
args = "[" + args + "]";
let op = {
op: m[1].replace(/_/g, " "),
args: JSON.parse(args)
};
if (m[3] && m[3].indexOf("disabled") > 0) op.disabled = true;
if (m[3] && m[3].indexOf("breakpoint") > 0) op.breakpoint = true;
recipeConfig.push(op);
}
return recipeConfig;
},
/**
* Expresses a number of milliseconds in a human readable format.
*
@@ -1102,7 +1244,8 @@ const Utils = {
"Forward slash": /\//g,
"Backslash": /\\/g,
"0x": /0x/g,
"\\x": /\\x/g
"\\x": /\\x/g,
"None": /\s+/g // Included here to remove whitespace when there shouldn't be any
},

View File

@@ -122,6 +122,8 @@ const Categories = [
"AND",
"ADD",
"SUB",
"Bit shift left",
"Bit shift right",
"Rotate left",
"Rotate right",
"ROT13",
@@ -173,7 +175,6 @@ const Categories = [
"Tail",
"Count occurrences",
"Expand alphabet range",
"Parse escaped string",
"Drop bytes",
"Take bytes",
"Pad lines",
@@ -188,6 +189,8 @@ const Categories = [
"Parse UNIX file permissions",
"Swap endianness",
"Parse colour code",
"Escape string",
"Unescape string",
]
},
{
@@ -244,20 +247,21 @@ const Categories = [
"MD2",
"MD4",
"MD5",
"MD6",
"SHA0",
"SHA1",
"SHA224",
"SHA256",
"SHA384",
"SHA512",
"SHA2",
"SHA3",
"RIPEMD-160",
"Keccak",
"Shake",
"RIPEMD",
"HMAC",
"Fletcher-8 Checksum",
"Fletcher-16 Checksum",
"Fletcher-32 Checksum",
"Fletcher-64 Checksum",
"Adler-32 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum",
]
@@ -281,6 +285,7 @@ const Categories = [
"XPath expression",
"JPath expression",
"CSS selector",
"Microsoft Script Decoder",
"Strip HTML tags",
"Diff",
"To Snake case",
@@ -296,6 +301,8 @@ const Categories = [
"Detect File Type",
"Scan for Embedded Files",
"Generate UUID",
"Generate TOTP",
"Generate HOTP",
"Render Image",
"Remove EXIF",
"Extract EXIF",

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
import CharEnc from "../../operations/CharEnc.js";
/**
* CharEnc module.
*
* Libraries:
* - cptable
* - CryptoJS
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.CharEnc = {
"Encode text": CharEnc.runEncode,
"Decode text": CharEnc.runDecode,
};
export default OpModules;

View File

@@ -0,0 +1,42 @@
import Cipher from "../../operations/Cipher.js";
/**
* Ciphers module.
*
* Libraries:
* - CryptoJS
* - Blowfish
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Ciphers = {
"AES Encrypt": Cipher.runAesEnc,
"AES Decrypt": Cipher.runAesDec,
"Blowfish Encrypt": Cipher.runBlowfishEnc,
"Blowfish Decrypt": Cipher.runBlowfishDec,
"DES Encrypt": Cipher.runDesEnc,
"DES Decrypt": Cipher.runDesDec,
"Triple DES Encrypt": Cipher.runTripleDesEnc,
"Triple DES Decrypt": Cipher.runTripleDesDec,
"Rabbit Encrypt": Cipher.runRabbitEnc,
"Rabbit Decrypt": Cipher.runRabbitDec,
"Derive PBKDF2 key": Cipher.runPbkdf2,
"Derive EVP key": Cipher.runEvpkdf,
"RC4": Cipher.runRc4,
"RC4 Drop": Cipher.runRc4drop,
"Vigenère Encode": Cipher.runVigenereEnc,
"Vigenère Decode": Cipher.runVigenereDec,
"Bifid Cipher Encode": Cipher.runBifidEnc,
"Bifid Cipher Decode": Cipher.runBifidDec,
"Affine Cipher Encode": Cipher.runAffineEnc,
"Affine Cipher Decode": Cipher.runAffineDec,
"Atbash Cipher": Cipher.runAtbash,
"Substitute": Cipher.runSubstitute,
};
export default OpModules;

View File

@@ -0,0 +1,44 @@
import JS from "../../operations/JS.js";
import Code from "../../operations/Code.js";
/**
* Code module.
*
* Libraries:
* - lodash
* - vkbeautify
* - xmldom
* - xpath
* - jpath
* - googlecodeprettify
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Code = {
"JavaScript Parser": JS.runParse,
"JavaScript Beautify": JS.runBeautify,
"JavaScript Minify": JS.runMinify,
"Syntax highlighter": Code.runSyntaxHighlight,
"Generic Code Beautify": Code.runGenericBeautify,
"JSON Beautify": Code.runJsonBeautify,
"JSON Minify": Code.runJsonMinify,
"XML Beautify": Code.runXmlBeautify,
"XML Minify": Code.runXmlMinify,
"SQL Beautify": Code.runSqlBeautify,
"SQL Minify": Code.runSqlMinify,
"CSS Beautify": Code.runCssBeautify,
"CSS Minify": Code.runCssMinify,
"XPath expression": Code.runXpath,
"CSS selector": Code.runCSSQuery,
"To Snake case": Code.runToSnakeCase,
"To Camel case": Code.runToCamelCase,
"To Kebab case": Code.runToKebabCase,
"JPath expression": Code.runJpath,
};
export default OpModules;

View File

@@ -0,0 +1,32 @@
import Compress from "../../operations/Compress.js";
/**
* Compression module.
*
* Libraries:
* - zlib.js
* - bzip2.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Compression = {
"Raw Deflate": Compress.runRawDeflate,
"Raw Inflate": Compress.runRawInflate,
"Zlib Deflate": Compress.runZlibDeflate,
"Zlib Inflate": Compress.runZlibInflate,
"Gzip": Compress.runGzip,
"Gunzip": Compress.runGunzip,
"Zip": Compress.runPkzip,
"Unzip": Compress.runPkunzip,
"Bzip2 Decompress": Compress.runBzip2Decompress,
"Tar": Compress.runTar,
"Untar": Compress.runUntar,
};
export default OpModules;

View File

@@ -0,0 +1,191 @@
import FlowControl from "../../FlowControl.js";
import Base from "../../operations/Base.js";
import Base58 from "../../operations/Base58.js";
import Base64 from "../../operations/Base64.js";
import BCD from "../../operations/BCD.js";
import BitwiseOp from "../../operations/BitwiseOp.js";
import ByteRepr from "../../operations/ByteRepr.js";
import Convert from "../../operations/Convert.js";
import DateTime from "../../operations/DateTime.js";
import Endian from "../../operations/Endian.js";
import Entropy from "../../operations/Entropy.js";
import Extract from "../../operations/Extract.js";
import FileType from "../../operations/FileType.js";
import Hexdump from "../../operations/Hexdump.js";
import HTML from "../../operations/HTML.js";
import MAC from "../../operations/MAC.js";
import MorseCode from "../../operations/MorseCode.js";
import MS from "../../operations/MS.js";
import NetBIOS from "../../operations/NetBIOS.js";
import Numberwang from "../../operations/Numberwang.js";
import OS from "../../operations/OS.js";
import OTP from "../../operations/OTP.js";
import QuotedPrintable from "../../operations/QuotedPrintable.js";
import Rotate from "../../operations/Rotate.js";
import SeqUtils from "../../operations/SeqUtils.js";
import StrUtils from "../../operations/StrUtils.js";
import Tidy from "../../operations/Tidy.js";
import Unicode from "../../operations/Unicode.js";
import URL_ from "../../operations/URL.js";
import UUID from "../../operations/UUID.js";
/**
* Default module.
*
* The Default module is for operations that are expected to be very commonly used or
* do not require any libraries. This module is loaded into the app at compile time.
*
* Libraries:
* - Utils.js
* - CryptoJS
* - otp
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Default = {
"To Hexdump": Hexdump.runTo,
"From Hexdump": Hexdump.runFrom,
"To Hex": ByteRepr.runToHex,
"From Hex": ByteRepr.runFromHex,
"To Octal": ByteRepr.runToOct,
"From Octal": ByteRepr.runFromOct,
"To Charcode": ByteRepr.runToCharcode,
"From Charcode": ByteRepr.runFromCharcode,
"To Decimal": ByteRepr.runToDecimal,
"From Decimal": ByteRepr.runFromDecimal,
"To Binary": ByteRepr.runToBinary,
"From Binary": ByteRepr.runFromBinary,
"To Hex Content": ByteRepr.runToHexContent,
"From Hex Content": ByteRepr.runFromHexContent,
"To Base64": Base64.runTo,
"From Base64": Base64.runFrom,
"Show Base64 offsets": Base64.runOffsets,
"To Base32": Base64.runTo32,
"From Base32": Base64.runFrom32,
"To Base58": Base58.runTo,
"From Base58": Base58.runFrom,
"To Base": Base.runTo,
"From Base": Base.runFrom,
"To BCD": BCD.runToBCD,
"From BCD": BCD.runFromBCD,
"To HTML Entity": HTML.runToEntity,
"From HTML Entity": HTML.runFromEntity,
"Strip HTML tags": HTML.runStripTags,
"Parse colour code": HTML.runParseColourCode,
"URL Encode": URL_.runTo,
"URL Decode": URL_.runFrom,
"Parse URI": URL_.runParse,
"Unescape Unicode Characters": Unicode.runUnescape,
"To Quoted Printable": QuotedPrintable.runTo,
"From Quoted Printable": QuotedPrintable.runFrom,
"Swap endianness": Endian.runSwapEndianness,
"ROT13": Rotate.runRot13,
"ROT47": Rotate.runRot47,
"Rotate left": Rotate.runRotl,
"Rotate right": Rotate.runRotr,
"Bit shift left": BitwiseOp.runBitShiftLeft,
"Bit shift right": BitwiseOp.runBitShiftRight,
"XOR": BitwiseOp.runXor,
"XOR Brute Force": BitwiseOp.runXorBrute,
"OR": BitwiseOp.runXor,
"NOT": BitwiseOp.runNot,
"AND": BitwiseOp.runAnd,
"ADD": BitwiseOp.runAdd,
"SUB": BitwiseOp.runSub,
"To Morse Code": MorseCode.runTo,
"From Morse Code": MorseCode.runFrom,
"Format MAC addresses": MAC.runFormat,
"Encode NetBIOS Name": NetBIOS.runEncodeName,
"Decode NetBIOS Name": NetBIOS.runDecodeName,
"Regular expression": StrUtils.runRegex,
"Offset checker": StrUtils.runOffsetChecker,
"To Upper case": StrUtils.runUpper,
"To Lower case": StrUtils.runLower,
"Find / Replace": StrUtils.runFindReplace,
"Split": StrUtils.runSplit,
"Filter": StrUtils.runFilter,
"Escape string": StrUtils.runEscape,
"Unescape string": StrUtils.runUnescape,
"Head": StrUtils.runHead,
"Tail": StrUtils.runTail,
"Remove whitespace": Tidy.runRemoveWhitespace,
"Remove null bytes": Tidy.runRemoveNulls,
"Drop bytes": Tidy.runDropBytes,
"Take bytes": Tidy.runTakeBytes,
"Pad lines": Tidy.runPad,
"Reverse": SeqUtils.runReverse,
"Sort": SeqUtils.runSort,
"Unique": SeqUtils.runUnique,
"Count occurrences": SeqUtils.runCount,
"Add line numbers": SeqUtils.runAddLineNumbers,
"Remove line numbers": SeqUtils.runRemoveLineNumbers,
"Expand alphabet range": SeqUtils.runExpandAlphRange,
"Convert distance": Convert.runDistance,
"Convert area": Convert.runArea,
"Convert mass": Convert.runMass,
"Convert speed": Convert.runSpeed,
"Convert data units": Convert.runDataSize,
"Parse UNIX file permissions": OS.runParseUnixPerms,
"Parse DateTime": DateTime.runParse,
"Translate DateTime Format": DateTime.runTranslateFormat,
"From UNIX Timestamp": DateTime.runFromUnixTimestamp,
"To UNIX Timestamp": DateTime.runToUnixTimestamp,
"Strings": Extract.runStrings,
"Extract IP addresses": Extract.runIp,
"Extract email addresses": Extract.runEmail,
"Extract MAC addresses": Extract.runMac,
"Extract URLs": Extract.runUrls,
"Extract domains": Extract.runDomains,
"Extract file paths": Extract.runFilePaths,
"Extract dates": Extract.runDates,
"Microsoft Script Decoder": MS.runDecodeScript,
"Entropy": Entropy.runEntropy,
"Frequency distribution": Entropy.runFreqDistrib,
"Detect File Type": FileType.runDetect,
"Scan for Embedded Files": FileType.runScanForEmbeddedFiles,
"Generate UUID": UUID.runGenerateV4,
"Numberwang": Numberwang.run,
"Generate TOTP": OTP.runTOTP,
"Generate HOTP": OTP.runHOTP,
"Fork": FlowControl.runFork,
"Merge": FlowControl.runMerge,
"Jump": FlowControl.runJump,
"Conditional Jump": FlowControl.runCondJump,
"Return": FlowControl.runReturn,
"Comment": FlowControl.runComment,
/*
Highlighting functions.
This is a temporary solution as highlighting should be entirely
overhauled at some point.
*/
"From Base64-highlight": Base64.highlightFrom,
"From Base64-highlightReverse": Base64.highlightTo,
"To Base64-highlight": Base64.highlightTo,
"To Base64-highlightReverse": Base64.highlightFrom,
"From Hex-highlight": ByteRepr.highlightFrom,
"From Hex-highlightReverse": ByteRepr.highlightTo,
"To Hex-highlight": ByteRepr.highlightTo,
"To Hex-highlightReverse": ByteRepr.highlightFrom,
"From Charcode-highlight": ByteRepr.highlightFrom,
"From Charcode-highlightReverse": ByteRepr.highlightTo,
"To Charcode-highlight": ByteRepr.highlightTo,
"To Charcode-highlightReverse": ByteRepr.highlightFrom,
"From Binary-highlight": ByteRepr.highlightFromBinary,
"From Binary-highlightReverse": ByteRepr.highlightToBinary,
"To Binary-highlight": ByteRepr.highlightToBinary,
"To Binary-highlightReverse": ByteRepr.highlightFromBinary,
"From Hexdump-highlight": Hexdump.highlightFrom,
"From Hexdump-highlightReverse": Hexdump.highlightTo,
"To Hexdump-highlight": Hexdump.highlightTo,
"To Hexdump-highlightReverse": Hexdump.highlightFrom,
};
export default OpModules;

View File

@@ -0,0 +1,20 @@
import Diff from "../../operations/Diff.js";
/**
* Diff module.
*
* Libraries:
* - JsDIff
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Diff = {
"Diff": Diff.runDiff,
};
export default OpModules;

View File

@@ -0,0 +1,21 @@
import Punycode from "../../operations/Punycode.js";
/**
* Encodings module.
*
* Libraries:
* - punycode
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Encodings = {
"To Punycode": Punycode.runToAscii,
"From Punycode": Punycode.runToUnicode,
};
export default OpModules;

View File

@@ -0,0 +1,22 @@
import HTTP from "../../operations/HTTP.js";
/**
* HTTP module.
*
* Libraries:
* - UAS_parser
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.HTTP = {
"HTTP request": HTTP.runHTTPRequest,
"Strip HTTP headers": HTTP.runStripHeaders,
"Parse User Agent": HTTP.runParseUserAgent,
};
export default OpModules;

View File

@@ -0,0 +1,45 @@
import Checksum from "../../operations/Checksum.js";
import Hash from "../../operations/Hash.js";
/**
* Hashing module.
*
* Libraries:
* - CryptoApi
* - node-md6
* - js-sha3
* - ./Checksum.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Hashing = {
"Analyse hash": Hash.runAnalyse,
"Generate all hashes": Hash.runAll,
"MD2": Hash.runMD2,
"MD4": Hash.runMD4,
"MD5": Hash.runMD5,
"MD6": Hash.runMD6,
"SHA0": Hash.runSHA0,
"SHA1": Hash.runSHA1,
"SHA2": Hash.runSHA2,
"SHA3": Hash.runSHA3,
"Keccak": Hash.runKeccak,
"Shake": Hash.runShake,
"RIPEMD": Hash.runRIPEMD,
"HMAC": Hash.runHMAC,
"Fletcher-8 Checksum": Checksum.runFletcher8,
"Fletcher-16 Checksum": Checksum.runFletcher16,
"Fletcher-32 Checksum": Checksum.runFletcher32,
"Fletcher-64 Checksum": Checksum.runFletcher64,
"Adler-32 Checksum": Checksum.runAdler32,
"CRC-16 Checksum": Checksum.runCRC16,
"CRC-32 Checksum": Checksum.runCRC32,
"TCP/IP Checksum": Checksum.runTCPIP,
};
export default OpModules;

View File

@@ -0,0 +1,25 @@
import Image from "../../operations/Image.js";
/**
* Image module.
*
* Libraries:
* - exif-parser
* - remove-exif
* - ./FileType.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Image = {
"Extract EXIF": Image.runExtractEXIF,
"Remove EXIF": Image.runRemoveEXIF,
"Render Image": Image.runRenderImage,
};
export default OpModules;

View File

@@ -0,0 +1,28 @@
import IP from "../../operations/IP.js";
import Filetime from "../../operations/Filetime.js";
/**
* JSBN module.
*
* Libraries:
* - jsbn
* - ./Checksum.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.JSBN = {
"Parse IP range": IP.runParseIpRange,
"Parse IPv6 address": IP.runParseIPv6,
"Parse IPv4 header": IP.runParseIPv4Header,
"Change IP format": IP.runChangeIpFormat,
"Group IP addresses": IP.runGroupIps,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
};
export default OpModules;

View File

@@ -0,0 +1,37 @@
/**
* Imports all modules for builds which do not load modules separately.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import OpModules from "./Default.js";
import CharEncModule from "./CharEnc.js";
import CipherModule from "./Ciphers.js";
import CodeModule from "./Code.js";
import CompressionModule from "./Compression.js";
import DiffModule from "./Diff.js";
import EncodingModule from "./Encodings.js";
import HashingModule from "./Hashing.js";
import HTTPModule from "./HTTP.js";
import ImageModule from "./Image.js";
import JSBNModule from "./JSBN.js";
import PublicKeyModule from "./PublicKey.js";
Object.assign(
OpModules,
CharEncModule,
CipherModule,
CodeModule,
CompressionModule,
DiffModule,
EncodingModule,
HashingModule,
HTTPModule,
ImageModule,
JSBNModule,
PublicKeyModule
);
export default OpModules;

View File

@@ -0,0 +1,25 @@
import PublicKey from "../../operations/PublicKey.js";
/**
* PublicKey module.
*
* Libraries:
* - jsrsasign
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.PublicKey = {
"Parse X.509 certificate": PublicKey.runParseX509,
"Parse ASN.1 hex string": PublicKey.runParseAsn1HexString,
"PEM to Hex": PublicKey.runPemToHex,
"Hex to PEM": PublicKey.runHexToPem,
"Hex to Object Identifier": PublicKey.runHexToObjectIdentifier,
"Object Identifier to Hex": PublicKey.runObjectIdentifierToHex,
};
export default OpModules;

View File

@@ -1,5 +1,4 @@
import Utils from "../Utils.js";
import CryptoJS from "crypto-js";
/**
@@ -92,7 +91,7 @@ const BitwiseOp = {
* @constant
* @default
*/
XOR_BRUTE_KEY_LENGTH: ["1", "2"],
XOR_BRUTE_KEY_LENGTH: 1,
/**
* @constant
* @default
@@ -122,37 +121,62 @@ const BitwiseOp = {
* @returns {string}
*/
runXorBrute: function (input, args) {
const keyLength = parseInt(args[0], 10),
const keyLength = args[0],
sampleLength = args[1],
sampleOffset = args[2],
scheme = args[3],
nullPreserving = args[4],
printKey = args[5],
outputHex = args[6],
crib = args[7];
crib = args[7].toLowerCase();
let output = "",
let output = [],
result,
resultUtf8,
regex;
record = "";
input = input.slice(sampleOffset, sampleOffset + sampleLength);
if (crib !== "") {
regex = new RegExp(crib, "im");
}
if (ENVIRONMENT_IS_WORKER())
self.sendStatusMessage("Calculating " + Math.pow(256, keyLength) + " values...");
/**
* Converts an integer to an array of bytes expressing that number.
*
* @param {number} int
* @param {number} len - Length of the resulting array
* @returns {array}
*/
const intToByteArray = (int, len) => {
let res = Array(len).fill(0);
for (let i = len - 1; i >= 0; i--) {
res[i] = int & 0xff;
int = int >>> 8;
}
return res;
};
for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) {
result = BitwiseOp._bitOp(input, Utils.fromHex(key.toString(16)), BitwiseOp._xor, nullPreserving, scheme);
if (key % 10000 === 0 && ENVIRONMENT_IS_WORKER()) {
self.sendStatusMessage("Calculating " + l + " values... " + Math.floor(key / l * 100) + "%");
}
result = BitwiseOp._bitOp(input, intToByteArray(key, keyLength), BitwiseOp._xor, nullPreserving, scheme);
resultUtf8 = Utils.byteArrayToUtf8(result);
if (crib !== "" && resultUtf8.search(regex) === -1) continue;
if (printKey) output += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
if (outputHex) output += Utils.toHex(result) + "\n";
else output += Utils.printable(resultUtf8, false) + "\n";
if (printKey) output += "\n";
record = "";
if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue;
if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
if (outputHex) {
record += Utils.toHex(result);
} else {
record += Utils.printable(resultUtf8, false);
}
output.push(record);
}
return output;
return output.join("\n");
},
@@ -228,6 +252,46 @@ const BitwiseOp = {
},
/**
* Bit shift left operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
runBitShiftLeft: function(input, args) {
const amount = args[0];
return input.map(b => {
return (b << amount) & 0xff;
});
},
/**
* @constant
* @default
*/
BIT_SHIFT_TYPE: ["Logical shift", "Arithmetic shift"],
/**
* Bit shift right operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
runBitShiftRight: function(input, args) {
const amount = args[0],
type = args[1],
mask = type === "Logical shift" ? 0 : 0x80;
return input.map(b => {
return (b >>> amount) ^ (b & mask);
});
},
/**
* XOR bitwise calculation.
*

View File

@@ -119,11 +119,11 @@ const ByteRepr = {
else if (ordinal < 4294967296) padding = 8;
else padding = 2;
if (padding > 2 && app) app.options.attemptHighlight = false;
if (padding > 2 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
output += Utils.hex(ordinal, padding) + delim;
} else {
if (app) app.options.attemptHighlight = false;
if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
output += ordinal.toString(base) + delim;
}
}
@@ -149,9 +149,7 @@ const ByteRepr = {
throw "Error: Base argument must be between 2 and 36";
}
if (base !== 16 && app) {
app.options.attemptHighlight = false;
}
if (base !== 16 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
// Split into groups of 2 if the whole string is concatenated and
// too long to be a single character
@@ -196,7 +194,7 @@ const ByteRepr = {
/**
* Highlight to hex
* Highlight from hex
*
* @param {Object[]} pos
* @param {number} pos[].start
@@ -288,10 +286,8 @@ const ByteRepr = {
* @returns {byteArray}
*/
runFromBinary: function(input, args) {
if (args[0] !== "None") {
const delimRegex = Utils.regexRep[args[0] || "Space"];
input = input.replace(delimRegex, "");
}
const delimRegex = Utils.regexRep[args[0] || "Space"];
input = input.replace(delimRegex, "");
const output = [];
const byteLen = 8;

View File

@@ -1,3 +1,4 @@
import * as CRC from "js-crc";
import Utils from "../Utils.js";
@@ -119,19 +120,24 @@ const Checksum = {
/**
* CRC-32 Checksum operation.
*
* @param {byteArray} input
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runCRC32: function(input, args) {
let crcTable = global.crcTable || (global.crcTable = Checksum._genCRCTable()),
crc = 0 ^ (-1);
return CRC.crc32(input);
},
for (let i = 0; i < input.length; i++) {
crc = (crc >>> 8) ^ crcTable[(crc ^ input[i]) & 0xff];
}
return Utils.hex((crc ^ (-1)) >>> 0);
/**
* CRC-16 Checksum operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runCRC16: function(input, args) {
return CRC.crc16(input);
},
@@ -168,28 +174,6 @@ const Checksum = {
return Utils.hex(0xffff - csum);
},
/**
* Generates a CRC table for use with CRC checksums.
*
* @private
* @returns {array}
*/
_genCRCTable: function() {
let c,
crcTable = [];
for (let n = 0; n < 256; n++) {
c = n;
for (let k = 0; k < 8; k++) {
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
crcTable[n] = c;
}
return crcTable;
},
};
export default Checksum;

View File

@@ -766,8 +766,8 @@ const Cipher = {
* @returns {string}
*/
runSubstitute: function (input, args) {
let plaintext = Utils.expandAlphRange(args[0]).join(),
ciphertext = Utils.expandAlphRange(args[1]).join(),
let plaintext = Utils.expandAlphRange(args[0]).join(""),
ciphertext = Utils.expandAlphRange(args[1]).join(""),
output = "",
index = -1;

View File

@@ -1,5 +1,3 @@
import {BigInteger} from "jsbn";
/**
* Date and time operations.
*
@@ -80,85 +78,6 @@ const DateTime = {
},
/**
* Windows Filetime to Unix Timestamp operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFromFiletimeToUnix: function(input, args) {
let units = args[0],
format = args[1];
if (format === "Hex") {
input = new BigInteger(input, 16);
} else {
input = new BigInteger(input);
}
input = input.subtract(new BigInteger("116444736000000000"));
if (units === "Seconds (s)"){
input = input.divide(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.divide(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.divide(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.multiply(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
return input.toString();
},
/**
* Unix Timestamp to Windows Filetime operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runToFiletimeFromUnix: function(input, args) {
let units = args[0],
format = args[1];
input = new BigInteger(input);
if (units === "Seconds (s)"){
input = input.multiply(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.multiply(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.multiply(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.divide(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
input = input.add(new BigInteger("116444736000000000"));
if (format === "Hex"){
return input.toString(16);
} else {
return input.toString();
}
},
/**
* @constant
* @default
*/
FILETIME_FORMATS: ["Decimal", "Hex"],
/**
* @constant
* @default

View File

@@ -0,0 +1,94 @@
import Utils from "../Utils.js";
import * as JsDiff from "diff";
/**
* Diff operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*
* @namespace
*/
const Diff = {
/**
* @constant
* @default
*/
DIFF_SAMPLE_DELIMITER: "\\n\\n",
/**
* @constant
* @default
*/
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
/**
* Diff operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runDiff: function(input, args) {
let sampleDelim = args[0],
diffBy = args[1],
showAdded = args[2],
showRemoved = args[3],
ignoreWhitespace = args[4],
samples = input.split(sampleDelim),
output = "",
diff;
if (!samples || samples.length !== 2) {
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
}
switch (diffBy) {
case "Character":
diff = JsDiff.diffChars(samples[0], samples[1]);
break;
case "Word":
if (ignoreWhitespace) {
diff = JsDiff.diffWords(samples[0], samples[1]);
} else {
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
}
break;
case "Line":
if (ignoreWhitespace) {
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
} else {
diff = JsDiff.diffLines(samples[0], samples[1]);
}
break;
case "Sentence":
diff = JsDiff.diffSentences(samples[0], samples[1]);
break;
case "CSS":
diff = JsDiff.diffCss(samples[0], samples[1]);
break;
case "JSON":
diff = JsDiff.diffJson(samples[0], samples[1]);
break;
default:
return "Invalid 'Diff by' option.";
}
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else {
output += Utils.escapeHtml(diff[i].value);
}
}
return output;
},
};
export default Diff;

View File

@@ -170,9 +170,9 @@ const Extract = {
protocol = "[A-Z]+://",
hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
port = ":\\d+",
path = "/[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]*";
path = "/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*";
path += "(?:[.!,?]+[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]+)*";
path += "(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*";
const regex = new RegExp(protocol + hostname + "(?:" + port +
")?(?:" + path + ")?", "ig");
return Extract._search(input, regex, null, displayTotal);
@@ -187,11 +187,8 @@ const Extract = {
* @returns {string}
*/
runDomains: function(input, args) {
let displayTotal = args[0],
protocol = "https?://",
hostname = "[-\\w\\.]+",
tld = "\\.(?:com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+",
regex = new RegExp("(?:" + protocol + ")?" + hostname + tld, "ig");
const displayTotal = args[0],
regex = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
return Extract._search(input, regex, null, displayTotal);
},
@@ -261,39 +258,6 @@ const Extract = {
return Extract._search(input, regex, null, displayTotal);
},
/**
* Extract all identifiers operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runAllIdents: function(input, args) {
let output = "";
output += "IP addresses\n";
output += Extract.runIp(input, [true, true, false]);
output += "\nEmail addresses\n";
output += Extract.runEmail(input, []);
output += "\nMAC addresses\n";
output += Extract.runMac(input, []);
output += "\nURLs\n";
output += Extract.runUrls(input, []);
output += "\nDomain names\n";
output += Extract.runDomains(input, []);
output += "\nFile paths\n";
output += Extract.runFilePaths(input, [true, true]);
output += "\nDates\n";
output += Extract.runDates(input, []);
return output;
},
};
export default Extract;

View File

@@ -0,0 +1,99 @@
import {BigInteger} from "jsbn";
/**
* Windows Filetime operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const Filetime = {
/**
* @constant
* @default
*/
UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
/**
* @constant
* @default
*/
FILETIME_FORMATS: ["Decimal", "Hex"],
/**
* Windows Filetime to Unix Timestamp operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFromFiletimeToUnix: function(input, args) {
let units = args[0],
format = args[1];
if (format === "Hex") {
input = new BigInteger(input, 16);
} else {
input = new BigInteger(input);
}
input = input.subtract(new BigInteger("116444736000000000"));
if (units === "Seconds (s)"){
input = input.divide(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.divide(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.divide(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.multiply(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
return input.toString();
},
/**
* Unix Timestamp to Windows Filetime operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runToFiletimeFromUnix: function(input, args) {
let units = args[0],
format = args[1];
input = new BigInteger(input);
if (units === "Seconds (s)"){
input = input.multiply(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.multiply(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.multiply(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.divide(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
input = input.add(new BigInteger("116444736000000000"));
if (format === "Hex"){
return input.toString(16);
} else {
return input.toString();
}
},
};
export default Filetime;

View File

@@ -1,6 +1,7 @@
import Utils from "../Utils.js";
import CryptoJS from "crypto-js";
import CryptoApi from "crypto-api";
import MD6 from "node-md6";
import * as SHA3 from "js-sha3";
import Checksum from "./Checksum.js";
@@ -23,7 +24,7 @@ const Hash = {
* @returns {string}
*/
runMD2: function (input, args) {
return Utils.toHexFast(CryptoApi.hash("md2", input, {}));
return CryptoApi.hash("md2", input, {}).stringify("hex");
},
@@ -35,7 +36,7 @@ const Hash = {
* @returns {string}
*/
runMD4: function (input, args) {
return Utils.toHexFast(CryptoApi.hash("md4", input, {}));
return CryptoApi.hash("md4", input, {}).stringify("hex");
},
@@ -47,8 +48,39 @@ const Hash = {
* @returns {string}
*/
runMD5: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray
return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex);
return CryptoApi.hash("md5", input, {}).stringify("hex");
},
/**
* @constant
* @default
*/
MD6_SIZE: 256,
/**
* @constant
* @default
*/
MD6_LEVELS: 64,
/**
* MD6 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runMD6: function (input, args) {
const size = args[0],
levels = args[1],
key = args[2];
if (size < 0 || size > 512)
return "Size must be between 0 and 512";
if (levels < 0)
return "Levels must be greater than 0";
return MD6.getHashOfText(input, size, key, levels);
},
@@ -60,7 +92,7 @@ const Hash = {
* @returns {string}
*/
runSHA0: function (input, args) {
return Utils.toHexFast(CryptoApi.hash("sha0", input, {}));
return CryptoApi.hash("sha0", input, {}).stringify("hex");
},
@@ -72,60 +104,7 @@ const Hash = {
* @returns {string}
*/
runSHA1: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA1(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA224 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA224: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA224(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA256 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA256: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA256(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA384 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA384: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA384(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA512 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA512: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA512(input).toString(CryptoJS.enc.Hex);
return CryptoApi.hash("sha1", input, {}).stringify("hex");
},
@@ -133,7 +112,26 @@ const Hash = {
* @constant
* @default
*/
SHA3_LENGTH: ["512", "384", "256", "224"],
SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
/**
* SHA2 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA2: function (input, args) {
const size = args[0];
return CryptoApi.hash("sha" + size, input, {}).stringify("hex");
},
/**
* @constant
* @default
*/
SHA3_SIZE: ["512", "384", "256", "224"],
/**
* SHA3 operation.
@@ -143,25 +141,27 @@ const Hash = {
* @returns {string}
*/
runSHA3: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
let sha3Length = args[0],
options = {
outputLength: parseInt(sha3Length, 10)
};
return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
},
const size = parseInt(args[0], 10);
let algo;
switch (size) {
case 224:
algo = SHA3.sha3_224;
break;
case 384:
algo = SHA3.sha3_384;
break;
case 256:
algo = SHA3.sha3_256;
break;
case 512:
algo = SHA3.sha3_512;
break;
default:
return "Invalid size";
}
/**
* RIPEMD-160 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runRIPEMD160: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.RIPEMD160(input).toString(CryptoJS.enc.Hex);
return algo(input);
},
@@ -169,7 +169,121 @@ const Hash = {
* @constant
* @default
*/
HMAC_FUNCTIONS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD-160"],
KECCAK_SIZE: ["512", "384", "256", "224"],
/**
* Keccak operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runKeccak: function (input, args) {
const size = parseInt(args[0], 10);
let algo;
switch (size) {
case 224:
algo = SHA3.keccak224;
break;
case 384:
algo = SHA3.keccak384;
break;
case 256:
algo = SHA3.keccak256;
break;
case 512:
algo = SHA3.keccak512;
break;
default:
return "Invalid size";
}
return algo(input);
},
/**
* @constant
* @default
*/
SHAKE_CAPACITY: ["256", "128"],
/**
* @constant
* @default
*/
SHAKE_SIZE: 512,
/**
* Shake operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runShake: function (input, args) {
const capacity = parseInt(args[0], 10),
size = args[1];
let algo;
if (size < 0)
return "Size must be greater than 0";
switch (capacity) {
case 128:
algo = SHA3.shake128;
break;
case 256:
algo = SHA3.shake256;
break;
default:
return "Invalid size";
}
return algo(input, size);
},
/**
* @constant
* @default
*/
RIPEMD_SIZE: ["320", "256", "160", "128"],
/**
* RIPEMD operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runRIPEMD: function (input, args) {
const size = args[0];
return CryptoApi.hash("ripemd" + size, input, {}).stringify("hex");
},
/**
* @constant
* @default
*/
HMAC_FUNCTIONS: [
"MD2",
"MD4",
"MD5",
"SHA0",
"SHA1",
"SHA224",
"SHA256",
"SHA384",
"SHA512",
"SHA512/224",
"SHA512/256",
"RIPEMD128",
"RIPEMD160",
"RIPEMD256",
"RIPEMD320",
],
/**
* HMAC operation.
@@ -179,19 +293,12 @@ const Hash = {
* @returns {string}
*/
runHMAC: function (input, args) {
const hashFunc = args[1];
input = CryptoJS.enc.Latin1.parse(input);
const execute = {
"MD5": CryptoJS.HmacMD5(input, args[0]),
"SHA1": CryptoJS.HmacSHA1(input, args[0]),
"SHA224": CryptoJS.HmacSHA224(input, args[0]),
"SHA256": CryptoJS.HmacSHA256(input, args[0]),
"SHA384": CryptoJS.HmacSHA384(input, args[0]),
"SHA512": CryptoJS.HmacSHA512(input, args[0]),
"SHA3": CryptoJS.HmacSHA3(input, args[0]),
"RIPEMD-160": CryptoJS.HmacRIPEMD160(input, args[0]),
};
return execute[hashFunc].toString(CryptoJS.enc.Hex);
const password = args[0],
hashFunc = args[1].toLowerCase(),
hmac = CryptoApi.mac("hmac", password, hashFunc, {});
hmac.update(input);
return hmac.finalize().stringify("hex");
},
@@ -207,24 +314,35 @@ const Hash = {
output = "MD2: " + Hash.runMD2(input, []) +
"\nMD4: " + Hash.runMD4(input, []) +
"\nMD5: " + Hash.runMD5(input, []) +
"\nMD6: " + Hash.runMD6(input, []) +
"\nSHA0: " + Hash.runSHA0(input, []) +
"\nSHA1: " + Hash.runSHA1(input, []) +
"\nSHA2 224: " + Hash.runSHA224(input, []) +
"\nSHA2 256: " + Hash.runSHA256(input, []) +
"\nSHA2 384: " + Hash.runSHA384(input, []) +
"\nSHA2 512: " + Hash.runSHA512(input, []) +
"\nSHA2 224: " + Hash.runSHA2(input, ["224"]) +
"\nSHA2 256: " + Hash.runSHA2(input, ["256"]) +
"\nSHA2 384: " + Hash.runSHA2(input, ["384"]) +
"\nSHA2 512: " + Hash.runSHA2(input, ["512"]) +
"\nSHA3 224: " + Hash.runSHA3(input, ["224"]) +
"\nSHA3 256: " + Hash.runSHA3(input, ["256"]) +
"\nSHA3 384: " + Hash.runSHA3(input, ["384"]) +
"\nSHA3 512: " + Hash.runSHA3(input, ["512"]) +
"\nRIPEMD-160: " + Hash.runRIPEMD160(input, []) +
"\nKeccak 224: " + Hash.runKeccak(input, ["224"]) +
"\nKeccak 256: " + Hash.runKeccak(input, ["256"]) +
"\nKeccak 384: " + Hash.runKeccak(input, ["384"]) +
"\nKeccak 512: " + Hash.runKeccak(input, ["512"]) +
"\nShake 128: " + Hash.runShake(input, ["128", 256]) +
"\nShake 256: " + Hash.runShake(input, ["256", 512]) +
"\nRIPEMD-128: " + Hash.runRIPEMD(input, ["128"]) +
"\nRIPEMD-160: " + Hash.runRIPEMD(input, ["160"]) +
"\nRIPEMD-256: " + Hash.runRIPEMD(input, ["256"]) +
"\nRIPEMD-320: " + Hash.runRIPEMD(input, ["320"]) +
"\n\nChecksums:" +
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
"\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
"\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
"\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
"\nCRC-32: " + Checksum.runCRC32(byteArray, []);
"\nCRC-16: " + Checksum.runCRC16(input, []) +
"\nCRC-32: " + Checksum.runCRC32(input, []);
return output;
},

View File

@@ -92,7 +92,7 @@ const Hexdump = {
const w = (width - 13) / 4;
// w should be the specified width of the hexdump and therefore a round number
if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) {
if (app) app.options.attemptHighlight = false;
if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
}
return output;
},

213
src/core/operations/MS.js Normal file
View File

@@ -0,0 +1,213 @@
/**
* Microsoft operations.
*
* @author bmwhitn [brian.m.whitney@outlook.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const MS = {
/**
* @constant
* @default
*/
D_DECODE: [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"\x57\x6E\x7B",
"\x4A\x4C\x41",
"\x0B\x0B\x0B",
"\x0C\x0C\x0C",
"\x4A\x4C\x41",
"\x0E\x0E\x0E",
"\x0F\x0F\x0F",
"\x10\x10\x10",
"\x11\x11\x11",
"\x12\x12\x12",
"\x13\x13\x13",
"\x14\x14\x14",
"\x15\x15\x15",
"\x16\x16\x16",
"\x17\x17\x17",
"\x18\x18\x18",
"\x19\x19\x19",
"\x1A\x1A\x1A",
"\x1B\x1B\x1B",
"\x1C\x1C\x1C",
"\x1D\x1D\x1D",
"\x1E\x1E\x1E",
"\x1F\x1F\x1F",
"\x2E\x2D\x32",
"\x47\x75\x30",
"\x7A\x52\x21",
"\x56\x60\x29",
"\x42\x71\x5B",
"\x6A\x5E\x38",
"\x2F\x49\x33",
"\x26\x5C\x3D",
"\x49\x62\x58",
"\x41\x7D\x3A",
"\x34\x29\x35",
"\x32\x36\x65",
"\x5B\x20\x39",
"\x76\x7C\x5C",
"\x72\x7A\x56",
"\x43\x7F\x73",
"\x38\x6B\x66",
"\x39\x63\x4E",
"\x70\x33\x45",
"\x45\x2B\x6B",
"\x68\x68\x62",
"\x71\x51\x59",
"\x4F\x66\x78",
"\x09\x76\x5E",
"\x62\x31\x7D",
"\x44\x64\x4A",
"\x23\x54\x6D",
"\x75\x43\x71",
"\x4A\x4C\x41",
"\x7E\x3A\x60",
"\x4A\x4C\x41",
"\x5E\x7E\x53",
"\x40\x4C\x40",
"\x77\x45\x42",
"\x4A\x2C\x27",
"\x61\x2A\x48",
"\x5D\x74\x72",
"\x22\x27\x75",
"\x4B\x37\x31",
"\x6F\x44\x37",
"\x4E\x79\x4D",
"\x3B\x59\x52",
"\x4C\x2F\x22",
"\x50\x6F\x54",
"\x67\x26\x6A",
"\x2A\x72\x47",
"\x7D\x6A\x64",
"\x74\x39\x2D",
"\x54\x7B\x20",
"\x2B\x3F\x7F",
"\x2D\x38\x2E",
"\x2C\x77\x4C",
"\x30\x67\x5D",
"\x6E\x53\x7E",
"\x6B\x47\x6C",
"\x66\x34\x6F",
"\x35\x78\x79",
"\x25\x5D\x74",
"\x21\x30\x43",
"\x64\x23\x26",
"\x4D\x5A\x76",
"\x52\x5B\x25",
"\x63\x6C\x24",
"\x3F\x48\x2B",
"\x7B\x55\x28",
"\x78\x70\x23",
"\x29\x69\x41",
"\x28\x2E\x34",
"\x73\x4C\x09",
"\x59\x21\x2A",
"\x33\x24\x44",
"\x7F\x4E\x3F",
"\x6D\x50\x77",
"\x55\x09\x3B",
"\x53\x56\x55",
"\x7C\x73\x69",
"\x3A\x35\x61",
"\x5F\x61\x63",
"\x65\x4B\x50",
"\x46\x58\x67",
"\x58\x3B\x51",
"\x31\x57\x49",
"\x69\x22\x4F",
"\x6C\x6D\x46",
"\x5A\x4D\x68",
"\x48\x25\x7C",
"\x27\x28\x36",
"\x5C\x46\x70",
"\x3D\x4A\x6E",
"\x24\x32\x7A",
"\x79\x41\x2F",
"\x37\x3D\x5F",
"\x60\x5F\x4B",
"\x51\x4F\x5A",
"\x20\x42\x2C",
"\x36\x65\x57"
],
/**
* @constant
* @default
*/
D_COMBINATION: [
0, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 2, 0, 0, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1,
0, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 2, 1
],
/**
* Decodes Microsoft Encoded Script files that can be read and executed by cscript.exe/wscript.exe.
* This is a conversion of a Python script that was originally created by Didier Stevens
* (https://DidierStevens.com).
*
* @private
* @param {string} data
* @returns {string}
*/
_decode: function (data) {
let result = [];
let index = -1;
data = data.replace(/@&/g, String.fromCharCode(10))
.replace(/@#/g, String.fromCharCode(13))
.replace(/@\*/g, ">")
.replace(/@!/g, "<")
.replace(/@\$/g, "@");
for (let i = 0; i < data.length; i++) {
let byte = data.charCodeAt(i);
let char = data.charAt(i);
if (byte < 128) {
index++;
}
if ((byte === 9 || byte > 31 && byte < 128) &&
byte !== 60 &&
byte !== 62 &&
byte !== 64) {
char = MS.D_DECODE[byte].charAt(MS.D_COMBINATION[index % 64]);
}
result.push(char);
}
return result.join("");
},
/**
* Microsoft Script Decoder operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runDecodeScript: function (input, args) {
let matcher = /#@~\^.{6}==(.+).{6}==\^#~@/;
let encodedData = matcher.exec(input);
if (encodedData){
return MS._decode(encodedData[1]);
} else {
return "";
}
}
};
export default MS;

55
src/core/operations/OTP.js Executable file
View File

@@ -0,0 +1,55 @@
import otp from "otp";
import Base64 from "./Base64.js";
/**
* One-Time Password operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const OTP = {
/**
* Generate TOTP operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runTOTP: function(input, args) {
const otpObj = otp({
name: args[0],
keySize: args[1],
codeLength: args[2],
secret: Base64.runTo32(input, []),
epoch: args[3],
timeSlice: args[4]
});
return `URI: ${otpObj.totpURL}\n\nPassword: ${otpObj.totp()}`;
},
/**
* Generate HOTP operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runHOTP: function(input, args) {
const otpObj = otp({
name: args[0],
keySize: args[1],
codeLength: args[2],
secret: Base64.runTo32(input, []),
});
const counter = args[3];
return `URI: ${otpObj.hotpURL}\n\nPassword: ${otpObj.hotp(counter)}`;
},
};
export default OTP;

View File

@@ -341,702 +341,3 @@ ${extensions}`;
};
export default PublicKey;
/**
* Overwrite DN attribute lookup in jsrasign library with a much more complete version from
* https://github.com/nfephp-org/nfephp/blob/master/libs/Common/Certificate/Oids.php
*
* Various duplicates commented out.
*
* @constant
*/
r.X509.DN_ATTRHEX = {
"0603550403": "commonName",
"0603550404": "surname",
"0603550406": "countryName",
"0603550407": "localityName",
"0603550408": "stateOrProvinceName",
"0603550409": "streetAddress",
"060355040a": "organizationName",
"060355040b": "organizationalUnitName",
"060355040c": "title",
"0603550414": "telephoneNumber",
"060355042a": "givenName",
// "0603551d0e" : "id-ce-subjectKeyIdentifier",
// "0603551d0f" : "id-ce-keyUsage",
// "0603551d11" : "id-ce-subjectAltName",
// "0603551d13" : "id-ce-basicConstraints",
// "0603551d14" : "id-ce-cRLNumber",
// "0603551d1f" : "id-ce-CRLDistributionPoints",
// "0603551d20" : "id-ce-certificatePolicies",
// "0603551d23" : "id-ce-authorityKeyIdentifier",
// "0603551d25" : "id-ce-extKeyUsage",
// "06032a864886f70d010901" : "Email",
// "06032a864886f70d010101" : "RSAEncryption",
// "06032a864886f70d010102" : "md2WithRSAEncryption",
// "06032a864886f70d010104" : "md5withRSAEncryption",
// "06032a864886f70d010105" : "SHA-1WithRSAEncryption",
// "06032a8648ce380403" : "id-dsa-with-sha-1",
// "06032b06010505070302" : "idKpClientAuth",
// "06032b06010505070304" : "idKpSecurityemail",
"06032b06010505070201": "idCertificatePolicies",
"06036086480186f8420101": "netscape-cert-type",
"06036086480186f8420102": "netscape-base-url",
"06036086480186f8420103": "netscape-revocation-url",
"06036086480186f8420104": "netscape-ca-revocation-url",
"06036086480186f8420107": "netscape-cert-renewal-url",
"06036086480186f8420108": "netscape-ca-policy-url",
"06036086480186f842010c": "netscape-ssl-server-name",
"06036086480186f842010d": "netscape-comment",
"0603604c010201": "A1",
"0603604c010203": "A3",
"0603604c01020110": "Certification Practice Statement pointer",
"0603604c010301": "Dados do cert parte 1",
"0603604c010305": "Dados do cert parte 2",
"0603604c010306": "Dados do cert parte 3",
"06030992268993f22c640119": "domainComponent",
"06032a24a0f2a07d01010a": "Signet pilot",
"06032a24a0f2a07d01010b": "Signet intraNet",
"06032a24a0f2a07d010102": "Signet personal",
"06032a24a0f2a07d010114": "Signet securityPolicy",
"06032a24a0f2a07d010103": "Signet business",
"06032a24a0f2a07d010104": "Signet legal",
"06032a24a497a35301640101": "Certificates Australia policyIdentifier",
"06032a85702201": "seis-cp",
"06032a8570220101": "SEIS certificatePolicy-s10",
"06032a85702202": "SEIS pe",
"06032a85702203": "SEIS at",
"06032a8570220301": "SEIS at-personalIdentifier",
"06032a8648ce380201": "holdinstruction-none",
"06032a8648ce380202": "holdinstruction-callissuer",
"06032a8648ce380203": "holdinstruction-reject",
"06032a8648ce380401": "dsa",
"06032a8648ce380403": "dsaWithSha1",
"06032a8648ce3d01": "fieldType",
"06032a8648ce3d0101": "prime-field",
"06032a8648ce3d0102": "characteristic-two-field",
"06032a8648ce3d010201": "ecPublicKey",
"06032a8648ce3d010203": "characteristic-two-basis",
"06032a8648ce3d01020301": "onBasis",
"06032a8648ce3d01020302": "tpBasis",
"06032a8648ce3d01020303": "ppBasis",
"06032a8648ce3d02": "publicKeyType",
"06032a8648ce3d0201": "ecPublicKey",
"06032a8648ce3e0201": "dhPublicNumber",
"06032a864886f67d07": "nsn",
"06032a864886f67d0741": "nsn-ce",
"06032a864886f67d074100": "entrustVersInfo",
"06032a864886f67d0742": "nsn-alg",
"06032a864886f67d07420a": "cast5CBC",
"06032a864886f67d07420b": "cast5MAC",
"06032a864886f67d07420c": "pbeWithMD5AndCAST5-CBC",
"06032a864886f67d07420d": "passwordBasedMac",
"06032a864886f67d074203": "cast3CBC",
"06032a864886f67d0743": "nsn-oc",
"06032a864886f67d074300": "entrustUser",
"06032a864886f67d0744": "nsn-at",
"06032a864886f67d074400": "entrustCAInfo",
"06032a864886f67d07440a": "attributeCertificate",
"06032a864886f70d0101": "pkcs-1",
"06032a864886f70d010101": "rsaEncryption",
"06032a864886f70d010102": "md2withRSAEncryption",
"06032a864886f70d010103": "md4withRSAEncryption",
"06032a864886f70d010104": "md5withRSAEncryption",
"06032a864886f70d010105": "sha1withRSAEncryption",
"06032a864886f70d010106": "rsaOAEPEncryptionSET",
"06032a864886f70d010910020b": "SMIMEEncryptionKeyPreference",
"06032a864886f70d010c": "pkcs-12",
"06032a864886f70d010c01": "pkcs-12-PbeIds",
"06032a864886f70d010c0101": "pbeWithSHAAnd128BitRC4",
"06032a864886f70d010c0102": "pbeWithSHAAnd40BitRC4",
"06032a864886f70d010c0103": "pbeWithSHAAnd3-KeyTripleDES-CBC",
"06032a864886f70d010c0104": "pbeWithSHAAnd2-KeyTripleDES-CBC",
"06032a864886f70d010c0105": "pbeWithSHAAnd128BitRC2-CBC",
"06032a864886f70d010c0106": "pbeWithSHAAnd40BitRC2-CBC",
"06032a864886f70d010c0a": "pkcs-12Version1",
"06032a864886f70d010c0a01": "pkcs-12BadIds",
"06032a864886f70d010c0a0101": "pkcs-12-keyBag",
"06032a864886f70d010c0a0102": "pkcs-12-pkcs-8ShroudedKeyBag",
"06032a864886f70d010c0a0103": "pkcs-12-certBag",
"06032a864886f70d010c0a0104": "pkcs-12-crlBag",
"06032a864886f70d010c0a0105": "pkcs-12-secretBag",
"06032a864886f70d010c0a0106": "pkcs-12-safeContentsBag",
"06032a864886f70d010c02": "pkcs-12-ESPVKID",
"06032a864886f70d010c0201": "pkcs-12-PKCS8KeyShrouding",
"06032a864886f70d010c03": "pkcs-12-BagIds",
"06032a864886f70d010c0301": "pkcs-12-keyBagId",
"06032a864886f70d010c0302": "pkcs-12-certAndCRLBagId",
"06032a864886f70d010c0303": "pkcs-12-secretBagId",
"06032a864886f70d010c0304": "pkcs-12-safeContentsId",
"06032a864886f70d010c0305": "pkcs-12-pkcs-8ShroudedKeyBagId",
"06032a864886f70d010c04": "pkcs-12-CertBagID",
"06032a864886f70d010c0401": "pkcs-12-X509CertCRLBagID",
"06032a864886f70d010c0402": "pkcs-12-SDSICertBagID",
"06032a864886f70d010c05": "pkcs-12-OID",
"06032a864886f70d010c0501": "pkcs-12-PBEID",
"06032a864886f70d010c050101": "pkcs-12-PBEWithSha1And128BitRC4",
"06032a864886f70d010c050102": "pkcs-12-PBEWithSha1And40BitRC4",
"06032a864886f70d010c050103": "pkcs-12-PBEWithSha1AndTripleDESCBC",
"06032a864886f70d010c050104": "pkcs-12-PBEWithSha1And128BitRC2CBC",
"06032a864886f70d010c050105": "pkcs-12-PBEWithSha1And40BitRC2CBC",
"06032a864886f70d010c050106": "pkcs-12-PBEWithSha1AndRC4",
"06032a864886f70d010c050107": "pkcs-12-PBEWithSha1AndRC2CBC",
"06032a864886f70d010c0502": "pkcs-12-EnvelopingID",
"06032a864886f70d010c050201": "pkcs-12-RSAEncryptionWith128BitRC4",
"06032a864886f70d010c050202": "pkcs-12-RSAEncryptionWith40BitRC4",
"06032a864886f70d010c050203": "pkcs-12-RSAEncryptionWithTripleDES",
"06032a864886f70d010c0503": "pkcs-12-SignatureID",
"06032a864886f70d010c050301": "pkcs-12-RSASignatureWithSHA1Digest",
"06032a864886f70d0103": "pkcs-3",
"06032a864886f70d010301": "dhKeyAgreement",
"06032a864886f70d0105": "pkcs-5",
"06032a864886f70d010501": "pbeWithMD2AndDES-CBC",
"06032a864886f70d01050a": "pbeWithSHAAndDES-CBC",
"06032a864886f70d010503": "pbeWithMD5AndDES-CBC",
"06032a864886f70d010504": "pbeWithMD2AndRC2-CBC",
"06032a864886f70d010506": "pbeWithMD5AndRC2-CBC",
"06032a864886f70d010509": "pbeWithMD5AndXOR",
"06032a864886f70d0107": "pkcs-7",
"06032a864886f70d010701": "data",
"06032a864886f70d010702": "signedData",
"06032a864886f70d010703": "envelopedData",
"06032a864886f70d010704": "signedAndEnvelopedData",
"06032a864886f70d010705": "digestData",
"06032a864886f70d010706": "encryptedData",
"06032a864886f70d010707": "dataWithAttributes",
"06032a864886f70d010708": "encryptedPrivateKeyInfo",
"06032a864886f70d0109": "pkcs-9",
"06032a864886f70d010901": "emailAddress",
"06032a864886f70d01090a": "issuerAndSerialNumber",
"06032a864886f70d01090b": "passwordCheck",
"06032a864886f70d01090c": "publicKey",
"06032a864886f70d01090d": "signingDescription",
"06032a864886f70d01090e": "extensionReq",
"06032a864886f70d01090f": "sMIMECapabilities",
"06032a864886f70d01090f01": "preferSignedData",
"06032a864886f70d01090f02": "canNotDecryptAny",
"06032a864886f70d01090f03": "receiptRequest",
"06032a864886f70d01090f04": "receipt",
"06032a864886f70d01090f05": "contentHints",
"06032a864886f70d01090f06": "mlExpansionHistory",
"06032a864886f70d010910": "id-sMIME",
"06032a864886f70d01091000": "id-mod",
"06032a864886f70d0109100001": "id-mod-cms",
"06032a864886f70d0109100002": "id-mod-ess",
"06032a864886f70d01091001": "id-ct",
"06032a864886f70d0109100101": "id-ct-receipt",
"06032a864886f70d01091002": "id-aa",
"06032a864886f70d0109100201": "id-aa-receiptRequest",
"06032a864886f70d0109100202": "id-aa-securityLabel",
"06032a864886f70d0109100203": "id-aa-mlExpandHistory",
"06032a864886f70d0109100204": "id-aa-contentHint",
"06032a864886f70d010902": "unstructuredName",
"06032a864886f70d010914": "friendlyName",
"06032a864886f70d010915": "localKeyID",
"06032a864886f70d010916": "certTypes",
"06032a864886f70d01091601": "x509Certificate",
"06032a864886f70d01091602": "sdsiCertificate",
"06032a864886f70d010917": "crlTypes",
"06032a864886f70d01091701": "x509Crl",
"06032a864886f70d010903": "contentType",
"06032a864886f70d010904": "messageDigest",
"06032a864886f70d010905": "signingTime",
"06032a864886f70d010906": "countersignature",
"06032a864886f70d010907": "challengePassword",
"06032a864886f70d010908": "unstructuredAddress",
"06032a864886f70d010909": "extendedCertificateAttributes",
"06032a864886f70d02": "digestAlgorithm",
"06032a864886f70d0202": "md2",
"06032a864886f70d0204": "md4",
"06032a864886f70d0205": "md5",
"06032a864886f70d03": "encryptionAlgorithm",
"06032a864886f70d030a": "desCDMF",
"06032a864886f70d0302": "rc2CBC",
"06032a864886f70d0303": "rc2ECB",
"06032a864886f70d0304": "rc4",
"06032a864886f70d0305": "rc4WithMAC",
"06032a864886f70d0306": "DESX-CBC",
"06032a864886f70d0307": "DES-EDE3-CBC",
"06032a864886f70d0308": "RC5CBC",
"06032a864886f70d0309": "RC5-CBCPad",
"06032a864886f7140403": "microsoftExcel",
"06032a864886f7140404": "titledWithOID",
"06032a864886f7140405": "microsoftPowerPoint",
"06032b81051086480954": "x9-84",
"06032b8105108648095400": "x9-84-Module",
"06032b810510864809540001": "x9-84-Biometrics",
"06032b810510864809540002": "x9-84-CMS",
"06032b810510864809540003": "x9-84-Identifiers",
"06032b8105108648095401": "biometric",
"06032b810510864809540100": "id-unknown-Type",
"06032b810510864809540101": "id-body-Odor",
"06032b81051086480954010a": "id-palm",
"06032b81051086480954010b": "id-retina",
"06032b81051086480954010c": "id-signature",
"06032b81051086480954010d": "id-speech-Pattern",
"06032b81051086480954010e": "id-thermal-Image",
"06032b81051086480954010f": "id-vein-Pattern",
"06032b810510864809540110": "id-thermal-Face-Image",
"06032b810510864809540111": "id-thermal-Hand-Image",
"06032b810510864809540112": "id-lip-Movement",
"06032b810510864809540113": "id-gait",
"06032b810510864809540102": "id-dna",
"06032b810510864809540103": "id-ear-Shape",
"06032b810510864809540104": "id-facial-Features",
"06032b810510864809540105": "id-finger-Image",
"06032b810510864809540106": "id-finger-Geometry",
"06032b810510864809540107": "id-hand-Geometry",
"06032b810510864809540108": "id-iris-Features",
"06032b810510864809540109": "id-keystroke-Dynamics",
"06032b8105108648095402": "processing-algorithm",
"06032b8105108648095403": "matching-method",
"06032b8105108648095404": "format-Owner",
"06032b810510864809540400": "cbeff-Owner",
"06032b810510864809540401": "ibia-Owner",
"06032b81051086480954040101": "id-ibia-SAFLINK",
"06032b8105108648095404010a": "id-ibia-SecuGen",
"06032b8105108648095404010b": "id-ibia-PreciseBiometric",
"06032b8105108648095404010c": "id-ibia-Identix",
"06032b8105108648095404010d": "id-ibia-DERMALOG",
"06032b8105108648095404010e": "id-ibia-LOGICO",
"06032b8105108648095404010f": "id-ibia-NIST",
"06032b81051086480954040110": "id-ibia-A3Vision",
"06032b81051086480954040111": "id-ibia-NEC",
"06032b81051086480954040112": "id-ibia-STMicroelectronics",
"06032b81051086480954040102": "id-ibia-Bioscrypt",
"06032b81051086480954040103": "id-ibia-Visionics",
"06032b81051086480954040104": "id-ibia-InfineonTechnologiesAG",
"06032b81051086480954040105": "id-ibia-IridianTechnologies",
"06032b81051086480954040106": "id-ibia-Veridicom",
"06032b81051086480954040107": "id-ibia-CyberSIGN",
"06032b81051086480954040108": "id-ibia-eCryp.",
"06032b81051086480954040109": "id-ibia-FingerprintCardsAB",
"06032b810510864809540402": "x9-Owner",
"06032b0e021a05": "sha",
"06032b0e03020101": "rsa",
"06032b0e03020a": "desMAC",
"06032b0e03020b": "rsaSignature",
"06032b0e03020c": "dsa",
"06032b0e03020d": "dsaWithSHA",
"06032b0e03020e": "mdc2WithRSASignature",
"06032b0e03020f": "shaWithRSASignature",
"06032b0e030210": "dhWithCommonModulus",
"06032b0e030211": "desEDE",
"06032b0e030212": "sha",
"06032b0e030213": "mdc-2",
"06032b0e030202": "md4WitRSA",
"06032b0e03020201": "sqmod-N",
"06032b0e030214": "dsaCommon",
"06032b0e030215": "dsaCommonWithSHA",
"06032b0e030216": "rsaKeyTransport",
"06032b0e030217": "keyed-hash-seal",
"06032b0e030218": "md2WithRSASignature",
"06032b0e030219": "md5WithRSASignature",
"06032b0e03021a": "sha1",
"06032b0e03021b": "dsaWithSHA1",
"06032b0e03021c": "dsaWithCommonSHA1",
"06032b0e03021d": "sha-1WithRSAEncryption",
"06032b0e030203": "md5WithRSA",
"06032b0e03020301": "sqmod-NwithRSA",
"06032b0e030204": "md4WithRSAEncryption",
"06032b0e030206": "desECB",
"06032b0e030207": "desCBC",
"06032b0e030208": "desOFB",
"06032b0e030209": "desCFB",
"06032b0e030301": "simple-strong-auth-mechanism",
"06032b0e07020101": "ElGamal",
"06032b0e07020301": "md2WithRSA",
"06032b0e07020302": "md2WithElGamal",
"06032b2403": "algorithm",
"06032b240301": "encryptionAlgorithm",
"06032b24030101": "des",
"06032b240301010101": "desECBPad",
"06032b24030101010101": "desECBPadISO",
"06032b240301010201": "desCBCPad",
"06032b24030101020101": "desCBCPadISO",
"06032b24030102": "idea",
"06032b2403010201": "ideaECB",
"06032b240301020101": "ideaECBPad",
"06032b24030102010101": "ideaECBPadISO",
"06032b2403010202": "ideaCBC",
"06032b240301020201": "ideaCBCPad",
"06032b24030102020101": "ideaCBCPadISO",
"06032b2403010203": "ideaOFB",
"06032b2403010204": "ideaCFB",
"06032b24030103": "des-3",
"06032b240301030101": "des-3ECBPad",
"06032b24030103010101": "des-3ECBPadISO",
"06032b240301030201": "des-3CBCPad",
"06032b24030103020101": "des-3CBCPadISO",
"06032b240302": "hashAlgorithm",
"06032b24030201": "ripemd160",
"06032b24030202": "ripemd128",
"06032b24030203": "ripemd256",
"06032b24030204": "mdc2singleLength",
"06032b24030205": "mdc2doubleLength",
"06032b240303": "signatureAlgorithm",
"06032b24030301": "rsa",
"06032b2403030101": "rsaMitSHA-1",
"06032b2403030102": "rsaMitRIPEMD160",
"06032b24030302": "ellipticCurve",
"06032b240304": "signatureScheme",
"06032b24030401": "iso9796-1",
"06032b2403040201": "iso9796-2",
"06032b2403040202": "iso9796-2rsa",
"06032b2404": "attribute",
"06032b2405": "policy",
"06032b2406": "api",
"06032b240601": "manufacturerSpecific",
"06032b240602": "functionalitySpecific",
"06032b2407": "api",
"06032b240701": "keyAgreement",
"06032b240702": "keyTransport",
"06032b06010401927c0a0101": "UNINETT policyIdentifier",
"06032b0601040195180a": "ICE-TEL policyIdentifier",
"06032b0601040197552001": "cryptlibEnvelope",
"06032b0601040197552002": "cryptlibPrivateKey",
"060a2b060104018237": "Microsoft OID",
"060a2b0601040182370a": "Crypto 2.0",
"060a2b0601040182370a01": "certTrustList",
"060a2b0601040182370a0101": "szOID_SORTED_CTL",
"060a2b0601040182370a0a": "Microsoft CMC OIDs",
"060a2b0601040182370a0a01": "szOID_CMC_ADD_ATTRIBUTES",
"060a2b0601040182370a0b": "Microsoft certificate property OIDs",
"060a2b0601040182370a0b01": "szOID_CERT_PROP_ID_PREFIX",
"060a2b0601040182370a0c": "CryptUI",
"060a2b0601040182370a0c01": "szOID_ANY_APPLICATION_POLICY",
"060a2b0601040182370a02": "nextUpdateLocation",
"060a2b0601040182370a0301": "certTrustListSigning",
"060a2b0601040182370a030a": "szOID_KP_QUALIFIED_SUBORDINATION",
"060a2b0601040182370a030b": "szOID_KP_KEY_RECOVERY",
"060a2b0601040182370a030c": "szOID_KP_DOCUMENT_SIGNING",
"060a2b0601040182370a0302": "timeStampSigning",
"060a2b0601040182370a0303": "serverGatedCrypto",
"060a2b0601040182370a030301": "szOID_SERIALIZED",
"060a2b0601040182370a0304": "encryptedFileSystem",
"060a2b0601040182370a030401": "szOID_EFS_RECOVERY",
"060a2b0601040182370a0305": "szOID_WHQL_CRYPTO",
"060a2b0601040182370a0306": "szOID_NT5_CRYPTO",
"060a2b0601040182370a0307": "szOID_OEM_WHQL_CRYPTO",
"060a2b0601040182370a0308": "szOID_EMBEDDED_NT_CRYPTO",
"060a2b0601040182370a0309": "szOID_ROOT_LIST_SIGNER",
"060a2b0601040182370a0401": "yesnoTrustAttr",
"060a2b0601040182370a0501": "szOID_DRM",
"060a2b0601040182370a0502": "szOID_DRM_INDIVIDUALIZATION",
"060a2b0601040182370a0601": "szOID_LICENSES",
"060a2b0601040182370a0602": "szOID_LICENSE_SERVER",
"060a2b0601040182370a07": "szOID_MICROSOFT_RDN_PREFIX",
"060a2b0601040182370a0701": "szOID_KEYID_RDN",
"060a2b0601040182370a0801": "szOID_REMOVE_CERTIFICATE",
"060a2b0601040182370a0901": "szOID_CROSS_CERT_DIST_POINTS",
"060a2b0601040182370c": "Catalog",
"060a2b0601040182370c0101": "szOID_CATALOG_LIST",
"060a2b0601040182370c0102": "szOID_CATALOG_LIST_MEMBER",
"060a2b0601040182370c0201": "CAT_NAMEVALUE_OBJID",
"060a2b0601040182370c0202": "CAT_MEMBERINFO_OBJID",
"060a2b0601040182370d": "Microsoft PKCS10 OIDs",
"060a2b0601040182370d01": "szOID_RENEWAL_CERTIFICATE",
"060a2b0601040182370d0201": "szOID_ENROLLMENT_NAME_VALUE_PAIR",
"060a2b0601040182370d0202": "szOID_ENROLLMENT_CSP_PROVIDER",
"060a2b0601040182370d0203": "OS Version",
"060a2b0601040182370f": "Microsoft Java",
"060a2b06010401823710": "Microsoft Outlook/Exchange",
"060a2b0601040182371004": "Outlook Express",
"060a2b06010401823711": "Microsoft PKCS12 attributes",
"060a2b0601040182371101": "szOID_LOCAL_MACHINE_KEYSET",
"060a2b06010401823712": "Microsoft Hydra",
"060a2b06010401823713": "Microsoft ISPU Test",
"060a2b06010401823702": "Authenticode",
"060a2b06010401823702010a": "spcAgencyInfo",
"060a2b06010401823702010b": "spcStatementType",
"060a2b06010401823702010c": "spcSpOpusInfo",
"060a2b06010401823702010e": "certExtensions",
"060a2b06010401823702010f": "spcPelmageData",
"060a2b060104018237020112": "SPC_RAW_FILE_DATA_OBJID",
"060a2b060104018237020113": "SPC_STRUCTURED_STORAGE_DATA_OBJID",
"060a2b060104018237020114": "spcLink",
"060a2b060104018237020115": "individualCodeSigning",
"060a2b060104018237020116": "commercialCodeSigning",
"060a2b060104018237020119": "spcLink",
"060a2b06010401823702011a": "spcMinimalCriteriaInfo",
"060a2b06010401823702011b": "spcFinancialCriteriaInfo",
"060a2b06010401823702011c": "spcLink",
"060a2b06010401823702011d": "SPC_HASH_INFO_OBJID",
"060a2b06010401823702011e": "SPC_SIPINFO_OBJID",
"060a2b060104018237020104": "spcIndirectDataContext",
"060a2b0601040182370202": "CTL for Software Publishers Trusted CAs",
"060a2b060104018237020201": "szOID_TRUSTED_CODESIGNING_CA_LIST",
"060a2b060104018237020202": "szOID_TRUSTED_CLIENT_AUTH_CA_LIST",
"060a2b060104018237020203": "szOID_TRUSTED_SERVER_AUTH_CA_LIST",
"060a2b06010401823714": "Microsoft Enrollment Infrastructure",
"060a2b0601040182371401": "szOID_AUTO_ENROLL_CTL_USAGE",
"060a2b0601040182371402": "szOID_ENROLL_CERTTYPE_EXTENSION",
"060a2b060104018237140201": "szOID_ENROLLMENT_AGENT",
"060a2b060104018237140202": "szOID_KP_SMARTCARD_LOGON",
"060a2b060104018237140203": "szOID_NT_PRINCIPAL_NAME",
"060a2b0601040182371403": "szOID_CERT_MANIFOLD",
"06092b06010401823715": "Microsoft CertSrv Infrastructure",
"06092b0601040182371501": "szOID_CERTSRV_CA_VERSION",
"06092b0601040182371514": "Client Information",
"060a2b06010401823719": "Microsoft Directory Service",
"060a2b0601040182371901": "szOID_NTDS_REPLICATION",
"060a2b06010401823703": "Time Stamping",
"060a2b060104018237030201": "SPC_TIME_STAMP_REQUEST_OBJID",
"060a2b0601040182371e": "IIS",
"060a2b0601040182371f": "Windows updates and service packs",
"060a2b0601040182371f01": "szOID_PRODUCT_UPDATE",
"060a2b06010401823704": "Permissions",
"060a2b06010401823728": "Fonts",
"060a2b06010401823729": "Microsoft Licensing and Registration",
"060a2b0601040182372a": "Microsoft Corporate PKI (ITG)",
"060a2b06010401823758": "CAPICOM",
"060a2b0601040182375801": "szOID_CAPICOM_VERSION",
"060a2b0601040182375802": "szOID_CAPICOM_ATTRIBUTE",
"060a2b060104018237580201": "szOID_CAPICOM_DOCUMENT_NAME",
"060a2b060104018237580202": "szOID_CAPICOM_DOCUMENT_DESCRIPTION",
"060a2b0601040182375803": "szOID_CAPICOM_ENCRYPTED_DATA",
"060a2b060104018237580301": "szOID_CAPICOM_ENCRYPTED_CONTENT",
"06032b0601050507": "pkix",
"06032b060105050701": "privateExtension",
"06032b06010505070101": "authorityInfoAccess",
"06032b06010505070c02": "CMC Data",
"06032b060105050702": "policyQualifierIds",
// "06032b06010505070201" : "cps",
"06032b06010505070202": "unotice",
"06032b060105050703": "keyPurpose",
"06032b06010505070301": "serverAuth",
"06032b06010505070302": "clientAuth",
"06032b06010505070303": "codeSigning",
"06032b06010505070304": "emailProtection",
"06032b06010505070305": "ipsecEndSystem",
"06032b06010505070306": "ipsecTunnel",
"06032b06010505070307": "ipsecUser",
"06032b06010505070308": "timeStamping",
"06032b060105050704": "cmpInformationTypes",
"06032b06010505070401": "caProtEncCert",
"06032b06010505070402": "signKeyPairTypes",
"06032b06010505070403": "encKeyPairTypes",
"06032b06010505070404": "preferredSymmAlg",
"06032b06010505070405": "caKeyUpdateInfo",
"06032b06010505070406": "currentCRL",
"06032b06010505073001": "ocsp",
"06032b06010505073002": "caIssuers",
"06032b06010505080101": "HMAC-MD5",
"06032b06010505080102": "HMAC-SHA",
"060360864801650201010a": "mosaicKeyManagementAlgorithm",
"060360864801650201010b": "sdnsKMandSigAlgorithm",
"060360864801650201010c": "mosaicKMandSigAlgorithm",
"060360864801650201010d": "SuiteASignatureAlgorithm",
"060360864801650201010e": "SuiteAConfidentialityAlgorithm",
"060360864801650201010f": "SuiteAIntegrityAlgorithm",
"06036086480186f84201": "cert-extension",
// "06036086480186f8420101" : "netscape-cert-type",
"06036086480186f842010a": "EntityLogo",
"06036086480186f842010b": "UserPicture",
// "06036086480186f842010c" : "netscape-ssl-server-name",
// "06036086480186f842010d" : "netscape-comment",
// "06036086480186f8420102" : "netscape-base-url",
// "06036086480186f8420103" : "netscape-revocation-url",
// "06036086480186f8420104" : "netscape-ca-revocation-url",
// "06036086480186f8420107" : "netscape-cert-renewal-url",
// "06036086480186f8420108" : "netscape-ca-policy-url",
"06036086480186f8420109": "HomePage-url",
"06036086480186f84202": "data-type",
"06036086480186f8420201": "GIF",
"06036086480186f8420202": "JPEG",
"06036086480186f8420203": "URL",
"06036086480186f8420204": "HTML",
"06036086480186f8420205": "netscape-cert-sequence",
"06036086480186f8420206": "netscape-cert-url",
"06036086480186f84203": "directory",
"06036086480186f8420401": "serverGatedCrypto",
"06036086480186f845010603": "Unknown Verisign extension",
"06036086480186f845010606": "Unknown Verisign extension",
"06036086480186f84501070101": "Verisign certificatePolicy",
"06036086480186f8450107010101": "Unknown Verisign policy qualifier",
"06036086480186f8450107010102": "Unknown Verisign policy qualifier",
"0603678105": "TCPA",
"060367810501": "tcpaSpecVersion",
"060367810502": "tcpaAttribute",
"06036781050201": "tcpaAtTpmManufacturer",
"0603678105020a": "tcpaAtSecurityQualities",
"0603678105020b": "tcpaAtTpmProtectionProfile",
"0603678105020c": "tcpaAtTpmSecurityTarget",
"0603678105020d": "tcpaAtFoundationProtectionProfile",
"0603678105020e": "tcpaAtFoundationSecurityTarget",
"0603678105020f": "tcpaAtTpmIdLabel",
"06036781050202": "tcpaAtTpmModel",
"06036781050203": "tcpaAtTpmVersion",
"06036781050204": "tcpaAtPlatformManufacturer",
"06036781050205": "tcpaAtPlatformModel",
"06036781050206": "tcpaAtPlatformVersion",
"06036781050207": "tcpaAtComponentManufacturer",
"06036781050208": "tcpaAtComponentModel",
"06036781050209": "tcpaAtComponentVersion",
"060367810503": "tcpaProtocol",
"06036781050301": "tcpaPrttTpmIdProtocol",
"0603672a00": "contentType",
"0603672a0000": "PANData",
"0603672a0001": "PANToken",
"0603672a0002": "PANOnly",
"0603672a01": "msgExt",
"0603672a0a": "national",
"0603672a0a8140": "Japan",
"0603672a02": "field",
"0603672a0200": "fullName",
"0603672a0201": "givenName",
"0603672a020a": "amount",
"0603672a0202": "familyName",
"0603672a0203": "birthFamilyName",
"0603672a0204": "placeName",
"0603672a0205": "identificationNumber",
"0603672a0206": "month",
"0603672a0207": "date",
"0603672a02070b": "accountNumber",
"0603672a02070c": "passPhrase",
"0603672a0208": "address",
"0603672a0209": "telephone",
"0603672a03": "attribute",
"0603672a0300": "cert",
"0603672a030000": "rootKeyThumb",
"0603672a030001": "additionalPolicy",
"0603672a04": "algorithm",
"0603672a05": "policy",
"0603672a0500": "root",
"0603672a06": "module",
"0603672a07": "certExt",
"0603672a0700": "hashedRootKey",
"0603672a0701": "certificateType",
"0603672a0702": "merchantData",
"0603672a0703": "cardCertRequired",
"0603672a0704": "tunneling",
"0603672a0705": "setExtensions",
"0603672a0706": "setQualifier",
"0603672a08": "brand",
"0603672a0801": "IATA-ATA",
"0603672a081e": "Diners",
"0603672a0822": "AmericanExpress",
"0603672a0804": "VISA",
"0603672a0805": "MasterCard",
"0603672a08ae7b": "Novus",
"0603672a09": "vendor",
"0603672a0900": "GlobeSet",
"0603672a0901": "IBM",
"0603672a090a": "Griffin",
"0603672a090b": "Certicom",
"0603672a090c": "OSS",
"0603672a090d": "TenthMountain",
"0603672a090e": "Antares",
"0603672a090f": "ECC",
"0603672a0910": "Maithean",
"0603672a0911": "Netscape",
"0603672a0912": "Verisign",
"0603672a0913": "BlueMoney",
"0603672a0902": "CyberCash",
"0603672a0914": "Lacerte",
"0603672a0915": "Fujitsu",
"0603672a0916": "eLab",
"0603672a0917": "Entrust",
"0603672a0918": "VIAnet",
"0603672a0919": "III",
"0603672a091a": "OpenMarket",
"0603672a091b": "Lexem",
"0603672a091c": "Intertrader",
"0603672a091d": "Persimmon",
"0603672a0903": "Terisa",
"0603672a091e": "NABLE",
"0603672a091f": "espace-net",
"0603672a0920": "Hitachi",
"0603672a0921": "Microsoft",
"0603672a0922": "NEC",
"0603672a0923": "Mitsubishi",
"0603672a0924": "NCR",
"0603672a0925": "e-COMM",
"0603672a0926": "Gemplus",
"0603672a0904": "RSADSI",
"0603672a0905": "VeriFone",
"0603672a0906": "TrinTech",
"0603672a0907": "BankGate",
"0603672a0908": "GTE",
"0603672a0909": "CompuSource",
"0603551d01": "authorityKeyIdentifier",
"0603551d0a": "basicConstraints",
"0603551d0b": "nameConstraints",
"0603551d0c": "policyConstraints",
"0603551d0d": "basicConstraints",
"0603551d0e": "subjectKeyIdentifier",
"0603551d0f": "keyUsage",
"0603551d10": "privateKeyUsagePeriod",
"0603551d11": "subjectAltName",
"0603551d12": "issuerAltName",
"0603551d13": "basicConstraints",
"0603551d02": "keyAttributes",
"0603551d14": "cRLNumber",
"0603551d15": "cRLReason",
"0603551d16": "expirationDate",
"0603551d17": "instructionCode",
"0603551d18": "invalidityDate",
"0603551d1a": "issuingDistributionPoint",
"0603551d1b": "deltaCRLIndicator",
"0603551d1c": "issuingDistributionPoint",
"0603551d1d": "certificateIssuer",
"0603551d03": "certificatePolicies",
"0603551d1e": "nameConstraints",
"0603551d1f": "cRLDistributionPoints",
"0603551d20": "certificatePolicies",
"0603551d21": "policyMappings",
"0603551d22": "policyConstraints",
"0603551d23": "authorityKeyIdentifier",
"0603551d24": "policyConstraints",
"0603551d25": "extKeyUsage",
"0603551d04": "keyUsageRestriction",
"0603551d05": "policyMapping",
"0603551d06": "subtreesConstraint",
"0603551d07": "subjectAltName",
"0603551d08": "issuerAltName",
"0603551d09": "subjectDirectoryAttributes",
"0603550400": "objectClass",
"0603550401": "aliasObjectName",
// "060355040c" : "title",
"060355040d": "description",
"060355040e": "searchGuide",
"060355040f": "businessCategory",
"0603550410": "postalAddress",
"0603550411": "postalCode",
"0603550412": "postOfficeBox",
"0603550413": "physicalDeliveryOfficeName",
"0603550402": "knowledgeInformation",
// "0603550414" : "telephoneNumber",
"0603550415": "telexNumber",
"0603550416": "teletexTerminalIdentifier",
"0603550417": "facsimileTelephoneNumber",
"0603550418": "x121Address",
"0603550419": "internationalISDNNumber",
"060355041a": "registeredAddress",
"060355041b": "destinationIndicator",
"060355041c": "preferredDeliveryMehtod",
"060355041d": "presentationAddress",
"060355041e": "supportedApplicationContext",
"060355041f": "member",
"0603550420": "owner",
"0603550421": "roleOccupant",
"0603550422": "seeAlso",
"0603550423": "userPassword",
"0603550424": "userCertificate",
"0603550425": "caCertificate",
"0603550426": "authorityRevocationList",
"0603550427": "certificateRevocationList",
"0603550428": "crossCertificatePair",
"0603550429": "givenName",
// "060355042a" : "givenName",
"0603550405": "serialNumber",
"0603550434": "supportedAlgorithms",
"0603550435": "deltaRevocationList",
"060355043a": "crossCertificatePair",
// "0603550409" : "streetAddress",
"06035508": "X.500-Algorithms",
"0603550801": "X.500-Alg-Encryption",
"060355080101": "rsa",
"0603604c0101": "DPC"
};

View File

@@ -20,7 +20,7 @@ const Rotate = {
* @constant
* @default
*/
ROTATE_WHOLE: false,
ROTATE_CARRY: false,
/**
* Runs rotation operations across the input data.
@@ -53,7 +53,7 @@ const Rotate = {
*/
runRotr: function(input, args) {
if (args[1]) {
return Rotate._rotrWhole(input, args[0]);
return Rotate._rotrCarry(input, args[0]);
} else {
return Rotate._rot(input, args[0], Rotate._rotr);
}
@@ -69,7 +69,7 @@ const Rotate = {
*/
runRotl: function(input, args) {
if (args[1]) {
return Rotate._rotlWhole(input, args[0]);
return Rotate._rotlCarry(input, args[0]);
} else {
return Rotate._rot(input, args[0], Rotate._rotl);
}
@@ -197,7 +197,7 @@ const Rotate = {
* @param {number} amount
* @returns {byteArray}
*/
_rotrWhole: function(data, amount) {
_rotrCarry: function(data, amount) {
let carryBits = 0,
newByte,
result = [];
@@ -223,7 +223,7 @@ const Rotate = {
* @param {number} amount
* @returns {byteArray}
*/
_rotlWhole: function(data, amount) {
_rotlCarry: function(data, amount) {
let carryBits = 0,
newByte,
result = [];

View File

@@ -1,5 +1,4 @@
import Utils from "../Utils.js";
import * as JsDiff from "diff";
/**
@@ -36,11 +35,11 @@ const StrUtils = {
},
{
name: "URL",
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
},
{
name: "Domain",
value: "(?:(https?):\\/\\/)?([-\\w.]+)\\.(com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+"
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
},
{
name: "Windows file path",
@@ -294,83 +293,6 @@ const StrUtils = {
},
/**
* @constant
* @default
*/
DIFF_SAMPLE_DELIMITER: "\\n\\n",
/**
* @constant
* @default
*/
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
/**
* Diff operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runDiff: function(input, args) {
let sampleDelim = args[0],
diffBy = args[1],
showAdded = args[2],
showRemoved = args[3],
ignoreWhitespace = args[4],
samples = input.split(sampleDelim),
output = "",
diff;
if (!samples || samples.length !== 2) {
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
}
switch (diffBy) {
case "Character":
diff = JsDiff.diffChars(samples[0], samples[1]);
break;
case "Word":
if (ignoreWhitespace) {
diff = JsDiff.diffWords(samples[0], samples[1]);
} else {
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
}
break;
case "Line":
if (ignoreWhitespace) {
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
} else {
diff = JsDiff.diffLines(samples[0], samples[1]);
}
break;
case "Sentence":
diff = JsDiff.diffSentences(samples[0], samples[1]);
break;
case "CSS":
diff = JsDiff.diffCss(samples[0], samples[1]);
break;
case "JSON":
diff = JsDiff.diffJson(samples[0], samples[1]);
break;
default:
return "Invalid 'Diff by' option.";
}
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else {
output += Utils.escapeHtml(diff[i].value);
}
}
return output;
},
/**
* @constant
* @default
@@ -450,14 +372,84 @@ const StrUtils = {
/**
* Parse escaped string operation.
* @constant
* @default
*/
ESCAPE_REPLACEMENTS: [
{"escaped": "\\\\", "unescaped": "\\"}, // Must be first
{"escaped": "\\'", "unescaped": "'"},
{"escaped": "\\\"", "unescaped": "\""},
{"escaped": "\\n", "unescaped": "\n"},
{"escaped": "\\r", "unescaped": "\r"},
{"escaped": "\\t", "unescaped": "\t"},
{"escaped": "\\b", "unescaped": "\b"},
{"escaped": "\\f", "unescaped": "\f"},
],
/**
* Escape string operation.
*
* @author Vel0x [dalemy@microsoft.com]
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*
* @example
* StrUtils.runUnescape("Don't do that", [])
* > "Don\'t do that"
* StrUtils.runUnescape(`Hello
* World`, [])
* > "Hello\nWorld"
*/
runParseEscapedString: function(input, args) {
return Utils.parseEscapedChars(input);
runEscape: function(input, args) {
return StrUtils._replaceByKeys(input, "unescaped", "escaped");
},
/**
* Unescape string operation.
*
* @author Vel0x [dalemy@microsoft.com]
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*
* @example
* StrUtils.runUnescape("Don\'t do that", [])
* > "Don't do that"
* StrUtils.runUnescape("Hello\nWorld", [])
* > `Hello
* World`
*/
runUnescape: function(input, args) {
return StrUtils._replaceByKeys(input, "escaped", "unescaped");
},
/**
* Replaces all matching tokens in ESCAPE_REPLACEMENTS with the correction. The
* ordering is determined by the patternKey and the replacementKey.
*
* @author Vel0x [dalemy@microsoft.com]
* @author Matt C [matt@artemisbot.uk]
*
* @param {string} input
* @param {string} pattern_key
* @param {string} replacement_key
* @returns {string}
*/
_replaceByKeys: function(input, patternKey, replacementKey) {
let output = input;
// Catch the \\x encoded characters
if (patternKey === "escaped") output = Utils.parseEscapedChars(input);
StrUtils.ESCAPE_REPLACEMENTS.forEach(replacement => {
output = output.split(replacement[patternKey]).join(replacement[replacementKey]);
});
return output;
},

View File

@@ -1,5 +1,4 @@
import Utils from "../core/Utils.js";
import Chef from "../core/Chef.js";
import Manager from "./Manager.js";
import HTMLCategory from "./HTMLCategory.js";
import HTMLOperation from "./HTMLOperation.js";
@@ -27,7 +26,6 @@ const App = function(categories, operations, defaultFavourites, defaultOptions)
this.doptions = defaultOptions;
this.options = Utils.extend({}, defaultOptions);
this.chef = new Chef();
this.manager = new Manager(this);
this.baking = false;
@@ -35,8 +33,6 @@ const App = function(categories, operations, defaultFavourites, defaultOptions)
this.autoBakePause = false;
this.progress = 0;
this.ingId = 0;
window.chef = this.chef;
};
@@ -54,6 +50,8 @@ App.prototype.setup = function() {
this.resetLayout();
this.setCompileMessage();
this.loadURIParams();
this.appLoaded = true;
this.loaded();
};
@@ -64,6 +62,11 @@ App.prototype.setup = function() {
* @fires Manager#apploaded
*/
App.prototype.loaded = function() {
// Check that both the app and the worker have loaded successfully, and that
// we haven't already loaded before attempting to remove the loading screen.
if (!this.workerLoaded || !this.appLoaded ||
!document.getElementById("loader-wrapper")) return;
// Trigger CSS animations to remove preloader
document.body.classList.add("loaded");
@@ -94,76 +97,24 @@ App.prototype.handleError = function(err) {
/**
* Updates the UI to show if baking is in process or not.
*
* @param {bakingStatus}
*/
App.prototype.setBakingStatus = function(bakingStatus) {
this.baking = bakingStatus;
let inputLoadingIcon = document.querySelector("#input .title .loading-icon"),
outputLoadingIcon = document.querySelector("#output .title .loading-icon"),
outputElement = document.querySelector("#output-text");
if (bakingStatus) {
inputLoadingIcon.style.display = "inline-block";
outputLoadingIcon.style.display = "inline-block";
outputElement.classList.add("disabled");
outputElement.disabled = true;
} else {
inputLoadingIcon.style.display = "none";
outputLoadingIcon.style.display = "none";
outputElement.classList.remove("disabled");
outputElement.disabled = false;
}
};
/**
* Calls the Chef to bake the current input using the current recipe.
* Asks the ChefWorker to bake the current input using the current recipe.
*
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
* whole recipe.
*/
App.prototype.bake = async function(step) {
let response;
App.prototype.bake = function(step) {
if (this.baking) return;
this.setBakingStatus(true);
// Reset attemptHighlight flag
this.options.attemptHighlight = true;
try {
response = await this.chef.bake(
this.getInput(), // The user's input
this.getRecipeConfig(), // The configuration of the recipe
this.options, // Options set by the user
this.progress, // The current position in the recipe
step // Whether or not to take one step or execute the whole recipe
);
} catch (err) {
this.handleError(err);
}
this.setBakingStatus(false);
if (!response) return;
if (response.error) {
this.handleError(response.error);
}
this.options = response.options;
this.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result;
this.progress = response.progress;
this.manager.recipe.updateBreakpointIndicator(response.progress);
this.manager.output.set(response.result, response.type, response.duration);
// If baking took too long, disable auto-bake
if (response.duration > this.options.autoBakeThreshold && this.autoBake_) {
this.manager.controls.setAutoBake(false);
this.alert("Baking took longer than " + this.options.autoBakeThreshold +
"ms, Auto Bake has been disabled.", "warning", 5000);
}
this.manager.worker.bake(
this.getInput(), // The user's input
this.getRecipeConfig(), // The configuration of the recipe
this.options, // Options set by the user
this.progress, // The current position in the recipe
step // Whether or not to take one step or execute the whole recipe
);
};
@@ -171,30 +122,31 @@ App.prototype.bake = async function(step) {
* Runs Auto Bake if it is set.
*/
App.prototype.autoBake = function() {
if (this.autoBake_ && !this.autoBakePause) {
if (this.autoBake_ && !this.autoBakePause && !this.baking) {
this.bake();
} else {
this.manager.controls.showStaleIndicator();
}
};
/**
* Runs a silent bake forcing the browser to load and cache all the relevant JavaScript code needed
* Runs a silent bake, forcing the browser to load and cache all the relevant JavaScript code needed
* to do a real bake.
*
* The output will not be modified (hence "silent" bake). This will only actually execute the
* recipe if auto-bake is enabled, otherwise it will just load the recipe, ingredients and dish.
*
* @returns {number} - The number of miliseconds it took to run the silent bake.
* The output will not be modified (hence "silent" bake). This will only actually execute the recipe
* if auto-bake is enabled, otherwise it will just wake up the ChefWorker with an empty recipe.
*/
App.prototype.silentBake = function() {
let startTime = new Date().getTime(),
recipeConfig = this.getRecipeConfig();
let recipeConfig = [];
if (this.autoBake_) {
this.chef.silentBake(recipeConfig);
// If auto-bake is not enabled we don't want to actually run the recipe as it may be disabled
// for a good reason.
recipeConfig = this.getRecipeConfig();
}
return new Date().getTime() - startTime;
this.manager.worker.silentBake(recipeConfig);
};
@@ -264,7 +216,7 @@ App.prototype.populateOperationsList = function() {
App.prototype.initialiseSplitter = function() {
this.columnSplitter = Split(["#operations", "#recipe", "#IO"], {
sizes: [20, 30, 50],
minSize: [240, 325, 440],
minSize: [240, 325, 450],
gutterSize: 4,
onDrag: function() {
this.manager.controls.adjustWidth();
@@ -288,7 +240,7 @@ App.prototype.initialiseSplitter = function() {
App.prototype.loadLocalStorage = function() {
// Load options
let lOptions;
if (localStorage.options !== undefined) {
if (this.isLocalStorageAvailable() && localStorage.options !== undefined) {
lOptions = JSON.parse(localStorage.options);
}
this.manager.options.load(lOptions);
@@ -304,13 +256,17 @@ App.prototype.loadLocalStorage = function() {
* If the user currently has no saved favourites, the defaults from the view constructor are used.
*/
App.prototype.loadFavourites = function() {
let favourites = localStorage.favourites &&
localStorage.favourites.length > 2 ?
JSON.parse(localStorage.favourites) :
this.dfavourites;
let favourites;
favourites = this.validFavourites(favourites);
this.saveFavourites(favourites);
if (this.isLocalStorageAvailable()) {
favourites = localStorage.favourites && localStorage.favourites.length > 2 ?
JSON.parse(localStorage.favourites) :
this.dfavourites;
favourites = this.validFavourites(favourites);
this.saveFavourites(favourites);
} else {
favourites = this.dfavourites;
}
const favCat = this.categories.filter(function(c) {
return c.name === "Favourites";
@@ -354,6 +310,15 @@ App.prototype.validFavourites = function(favourites) {
* @param {string[]} favourites - A list of the user's favourite operations
*/
App.prototype.saveFavourites = function(favourites) {
if (!this.isLocalStorageAvailable()) {
this.alert(
"Your security settings do not allow access to local storage so your favourites cannot be saved.",
"danger",
5000
);
return false;
}
localStorage.setItem("favourites", JSON.stringify(this.validFavourites(favourites)));
};
@@ -411,7 +376,7 @@ App.prototype.loadURIParams = function() {
// Read in recipe from URI params
if (this.uriParams.recipe) {
try {
const recipeConfig = JSON.parse(this.uriParams.recipe);
const recipeConfig = Utils.parseRecipeConfig(this.uriParams.recipe);
this.setRecipeConfig(recipeConfig);
} catch (err) {}
} else if (this.uriParams.op) {
@@ -482,6 +447,7 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
// Populate arguments
const args = item.querySelectorAll(".arg");
for (let j = 0; j < args.length; j++) {
if (recipeConfig[i].args[j] === undefined) continue;
if (args[j].getAttribute("type") === "checkbox") {
// checkbox
args[j].checked = recipeConfig[i].args[j];
@@ -550,6 +516,22 @@ App.prototype.setCompileMessage = function() {
};
/**
* Determines whether the browser supports Local Storage and if it is accessible.
*
* @returns {boolean}
*/
App.prototype.isLocalStorageAvailable = function() {
try {
if (!localStorage) return false;
return true;
} catch (err) {
// Access to LocalStorage is denied
return false;
}
};
/**
* Pops up a message to the user and writes it to the console log.
*
@@ -676,7 +658,14 @@ App.prototype.stateChange = function(e) {
if (recipeConfig.length === 1) {
title = `${recipeConfig[0].op} - ${title}`;
} else if (recipeConfig.length > 1) {
title = `${recipeConfig.length} operations - ${title}`;
// See how long the full recipe is
const ops = recipeConfig.map(op => op.op).join(", ");
if (ops.length < 45) {
title = `${ops} - ${title}`;
} else {
// If it's too long, just use the first one and say how many more there are
title = `${recipeConfig[0].op}, ${recipeConfig.length - 1} more - ${title}`;
}
}
document.title = title;

View File

@@ -78,10 +78,11 @@ ControlsWaiter.prototype.setAutoBake = function(value) {
* Handler to trigger baking.
*/
ControlsWaiter.prototype.bakeClick = function() {
this.app.bake();
const outputText = document.getElementById("output-text");
outputText.focus();
outputText.setSelectionRange(0, 0);
if (document.getElementById("bake").textContent.indexOf("Bake") > 0) {
this.app.bake();
} else {
this.manager.worker.cancelBake();
}
};
@@ -90,9 +91,6 @@ ControlsWaiter.prototype.bakeClick = function() {
*/
ControlsWaiter.prototype.stepClick = function() {
this.app.bake(true);
const outputText = document.getElementById("output-text");
outputText.focus();
outputText.setSelectionRange(0, 0);
};
@@ -170,7 +168,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
const link = baseURL || window.location.protocol + "//" +
window.location.host +
window.location.pathname;
const recipeStr = JSON.stringify(recipeConfig);
const recipeStr = Utils.generatePrettyRecipe(recipeConfig);
const inputStr = Utils.toBase64(this.app.getInput(), "A-Za-z0-9+/"); // B64 alphabet with no padding
includeRecipe = includeRecipe && (recipeConfig.length > 0);
@@ -184,7 +182,7 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
const hash = params
.filter(v => v)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.map(([key, value]) => `${key}=${Utils.encodeURIFragment(value)}`)
.join("&");
if (hash) {
@@ -198,9 +196,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
/**
* Handler for changes made to the save dialog text area. Re-initialises the save link.
*/
ControlsWaiter.prototype.saveTextChange = function() {
ControlsWaiter.prototype.saveTextChange = function(e) {
try {
const recipeConfig = JSON.parse(document.getElementById("save-text").value);
const recipeConfig = Utils.parseRecipeConfig(e.target.value);
this.initialiseSaveLink(recipeConfig);
} catch (err) {}
};
@@ -211,9 +209,16 @@ ControlsWaiter.prototype.saveTextChange = function() {
*/
ControlsWaiter.prototype.saveClick = function() {
const recipeConfig = this.app.getRecipeConfig();
const recipeStr = JSON.stringify(recipeConfig).replace(/},{/g, "},\n{");
const recipeStr = JSON.stringify(recipeConfig);
document.getElementById("save-text").value = recipeStr;
document.getElementById("save-text-chef").value = Utils.generatePrettyRecipe(recipeConfig, true);
document.getElementById("save-text-clean").value = JSON.stringify(recipeConfig, null, 2)
.replace(/{\n\s+"/g, "{ \"")
.replace(/\[\n\s{3,}/g, "[")
.replace(/\n\s{3,}]/g, "]")
.replace(/\s*\n\s*}/g, " }")
.replace(/\n\s{6,}/g, " ");
document.getElementById("save-text-compact").value = recipeStr;
this.initialiseSaveLink(recipeConfig);
$("#save-modal").modal();
@@ -249,8 +254,17 @@ ControlsWaiter.prototype.loadClick = function() {
* Saves the recipe specified in the save textarea to local storage.
*/
ControlsWaiter.prototype.saveButtonClick = function() {
if (!this.app.isLocalStorageAvailable()) {
this.app.alert(
"Your security settings do not allow access to local storage so your recipe cannot be saved.",
"danger",
5000
);
return false;
}
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
const recipeStr = document.getElementById("save-text").value;
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
if (!recipeName) {
this.app.alert("Please enter a recipe name", "danger", 2000);
@@ -278,6 +292,8 @@ ControlsWaiter.prototype.saveButtonClick = function() {
* Populates the list of saved recipes in the load dialog box from local storage.
*/
ControlsWaiter.prototype.populateLoadRecipesList = function() {
if (!this.app.isLocalStorageAvailable()) return false;
const loadNameEl = document.getElementById("load-name");
// Remove current recipes from select
@@ -308,6 +324,8 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
* Removes the currently selected recipe from local storage.
*/
ControlsWaiter.prototype.loadDeleteClick = function() {
if (!this.app.isLocalStorageAvailable()) return false;
const id = parseInt(document.getElementById("load-name").value, 10);
const rawSavedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
@@ -323,6 +341,8 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
* Displays the selected recipe in the load text box.
*/
ControlsWaiter.prototype.loadNameChange = function(e) {
if (!this.app.isLocalStorageAvailable()) return false;
const el = e.target;
const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
@@ -339,7 +359,7 @@ ControlsWaiter.prototype.loadNameChange = function(e) {
*/
ControlsWaiter.prototype.loadButtonClick = function() {
try {
const recipeConfig = JSON.parse(document.getElementById("load-text").value);
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
this.app.setRecipeConfig(recipeConfig);
$("#rec-list [data-toggle=popover]").popover();
@@ -368,4 +388,49 @@ ControlsWaiter.prototype.supportButtonClick = function(e) {
}
};
/**
* Shows the stale indicator to show that the input or recipe has changed
* since the last bake.
*/
ControlsWaiter.prototype.showStaleIndicator = function() {
const staleIndicator = document.getElementById("stale-indicator");
staleIndicator.style.visibility = "visible";
staleIndicator.style.opacity = 1;
};
/**
* Hides the stale indicator to show that the input or recipe has not changed
* since the last bake.
*/
ControlsWaiter.prototype.hideStaleIndicator = function() {
const staleIndicator = document.getElementById("stale-indicator");
staleIndicator.style.opacity = 0;
staleIndicator.style.visibility = "hidden";
};
/**
* Switches the Bake button between 'Bake' and 'Cancel' functions.
*
* @param {boolean} cancel - Whether to change to cancel or not
*/
ControlsWaiter.prototype.toggleBakeButtonFunction = function(cancel) {
const bakeButton = document.getElementById("bake"),
btnText = bakeButton.querySelector("span");
if (cancel) {
btnText.innerText = "Cancel";
bakeButton.classList.remove("btn-success");
bakeButton.classList.add("btn-danger");
} else {
btnText.innerText = "Bake!";
bakeButton.classList.remove("btn-danger");
bakeButton.classList.add("btn-success");
}
};
export default ControlsWaiter;

View File

@@ -10,9 +10,11 @@ import Utils from "../core/Utils.js";
*
* @constructor
* @param {App} app - The main view object for CyberChef.
* @param {Manager} manager - The CyberChef event manager.
*/
const HighlighterWaiter = function(app) {
const HighlighterWaiter = function(app, manager) {
this.app = app;
this.manager = manager;
this.mouseButtonDown = false;
this.mouseTarget = null;
@@ -329,41 +331,6 @@ HighlighterWaiter.prototype.removeHighlights = function() {
};
/**
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
* entire recipe supports highlighting.
*
* @returns {Object[]} highlights
* @returns {function} highlights[].f
* @returns {function} highlights[].b
* @returns {Object[]} highlights[].args
*/
HighlighterWaiter.prototype.generateHighlightList = function() {
const recipeConfig = this.app.getRecipeConfig();
const highlights = [];
for (let i = 0; i < recipeConfig.length; i++) {
if (recipeConfig[i].disabled) continue;
// If any breakpoints are set, do not attempt to highlight
if (recipeConfig[i].breakpoint) return false;
const op = this.app.operations[recipeConfig[i].op];
// If any of the operations do not support highlighting, fail immediately.
if (op.highlight === false || op.highlight === undefined) return false;
highlights.push({
f: op.highlight,
b: op.highlightReverse,
args: recipeConfig[i].args
});
}
return highlights;
};
/**
* Highlights the given offsets in the output.
* We will only highlight if:
@@ -376,26 +343,8 @@ HighlighterWaiter.prototype.generateHighlightList = function() {
* @param {number} pos.end - The end offset.
*/
HighlighterWaiter.prototype.highlightOutput = function(pos) {
const highlights = this.generateHighlightList();
if (!highlights || !this.app.autoBake_) {
return false;
}
for (let i = 0; i < highlights.length; i++) {
// Remove multiple highlights before processing again
pos = [pos[0]];
if (typeof highlights[i].f == "function") {
pos = highlights[i].f(pos, highlights[i].args);
}
}
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
this.highlight(
document.getElementById("output-text"),
document.getElementById("output-highlighter"),
pos);
if (!this.app.autoBake_ || this.app.baking) return false;
this.manager.worker.highlight(this.app.getRecipeConfig(), "forward", pos);
};
@@ -411,25 +360,28 @@ HighlighterWaiter.prototype.highlightOutput = function(pos) {
* @param {number} pos.end - The end offset.
*/
HighlighterWaiter.prototype.highlightInput = function(pos) {
const highlights = this.generateHighlightList();
if (!this.app.autoBake_ || this.app.baking) return false;
this.manager.worker.highlight(this.app.getRecipeConfig(), "reverse", pos);
};
if (!highlights || !this.app.autoBake_) {
return false;
}
for (let i = 0; i < highlights.length; i++) {
// Remove multiple highlights before processing again
pos = [pos[0]];
/**
* Displays highlight offsets sent back from the Chef.
*
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
* @param {string} direction
*/
HighlighterWaiter.prototype.displayHighlights = function(pos, direction) {
if (!pos) return;
if (typeof highlights[i].b == "function") {
pos = highlights[i].b(pos, highlights[i].args);
}
}
const io = direction === "forward" ? "output" : "input";
document.getElementById("input-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
document.getElementById(io + "-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
this.highlight(
document.getElementById("input-text"),
document.getElementById("input-highlighter"),
document.getElementById(io + "-text"),
document.getElementById(io + "-highlighter"),
pos);
};

View File

@@ -158,17 +158,15 @@ InputWaiter.prototype.inputDrop = function(e) {
const CHUNK_SIZE = 20480; // 20KB
const setInput = function() {
if (inputCharcode.length > 100000 && this.app.autoBake_) {
this.manager.controls.setAutoBake(false);
this.app.alert("Turned off Auto Bake as the input is large", "warning", 5000);
}
this.set(inputCharcode);
this.app.autoBakePause = true;
const recipeConfig = this.app.getRecipeConfig();
if (!recipeConfig[0] || recipeConfig[0].op !== "From Hex") {
recipeConfig.unshift({op: "From Hex", args: ["Space"]});
this.app.setRecipeConfig(recipeConfig);
}
this.app.autoBakePause = false;
this.set(inputCharcode);
el.classList.remove("loadingFile");
}.bind(this);

View File

@@ -1,3 +1,4 @@
import WorkerWaiter from "./WorkerWaiter.js";
import WindowWaiter from "./WindowWaiter.js";
import ControlsWaiter from "./ControlsWaiter.js";
import RecipeWaiter from "./RecipeWaiter.js";
@@ -49,6 +50,7 @@ const Manager = function(app) {
this.statechange = new CustomEvent("statechange", {bubbles: true});
// Define Waiter objects to handle various areas
this.worker = new WorkerWaiter(this.app, this);
this.window = new WindowWaiter(this.app);
this.controls = new ControlsWaiter(this.app, this);
this.recipe = new RecipeWaiter(this.app, this);
@@ -56,7 +58,7 @@ const Manager = function(app) {
this.input = new InputWaiter(this.app, this);
this.output = new OutputWaiter(this.app, this);
this.options = new OptionsWaiter(this.app);
this.highlighter = new HighlighterWaiter(this.app);
this.highlighter = new HighlighterWaiter(this.app, this);
this.seasonal = new SeasonalWaiter(this.app, this);
// Object to store dynamic handlers to fire on elements that may not exist yet
@@ -70,6 +72,7 @@ const Manager = function(app) {
* Sets up the various components and listeners.
*/
Manager.prototype.setup = function() {
this.worker.registerChefWorker();
this.recipe.initialiseOperationDragNDrop();
this.controls.autoBakeChange();
this.seasonal.load();
@@ -102,7 +105,7 @@ Manager.prototype.initialiseEventListeners = function() {
document.getElementById("load-name").addEventListener("change", this.controls.loadNameChange.bind(this.controls));
document.getElementById("load-button").addEventListener("click", this.controls.loadButtonClick.bind(this.controls));
document.getElementById("support").addEventListener("click", this.controls.supportButtonClick.bind(this.controls));
this.addMultiEventListener("#save-text", "keyup paste", this.controls.saveTextChange, this.controls);
this.addMultiEventListeners("#save-texts textarea", "keyup paste", this.controls.saveTextChange, this.controls);
// Operations
this.addMultiEventListener("#search", "keyup paste search", this.ops.searchOperations, this.ops);
@@ -118,6 +121,7 @@ Manager.prototype.initialiseEventListeners = function() {
// Recipe
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".arg", "change", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".arg", "input", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe);
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);

View File

@@ -38,7 +38,6 @@ OperationsWaiter.prototype.searchOperations = function(e) {
selected = this.getSelectedOp(ops);
if (selected > -1) {
this.manager.recipe.addOperation(ops[selected].innerHTML);
this.app.autoBake();
}
}
}
@@ -197,7 +196,6 @@ OperationsWaiter.prototype.operationDblclick = function(e) {
const li = e.target;
this.manager.recipe.addOperation(li.textContent);
this.app.autoBake();
};
@@ -231,7 +229,7 @@ OperationsWaiter.prototype.editFavouritesClick = function(e) {
filter: ".remove-icon",
onFilter: function (evt) {
const el = editableList.closest(evt.item);
if (el) {
if (el && el.parentNode) {
$(el).popover("destroy");
el.parentNode.removeChild(el);
}

View File

@@ -87,7 +87,9 @@ OptionsWaiter.prototype.switchChange = function(e, state) {
const option = el.getAttribute("option");
this.app.options[option] = state;
localStorage.setItem("options", JSON.stringify(this.app.options));
if (this.app.isLocalStorageAvailable())
localStorage.setItem("options", JSON.stringify(this.app.options));
};
@@ -102,7 +104,9 @@ OptionsWaiter.prototype.numberChange = function(e) {
const option = el.getAttribute("option");
this.app.options[option] = parseInt(el.value, 10);
localStorage.setItem("options", JSON.stringify(this.app.options));
if (this.app.isLocalStorageAvailable())
localStorage.setItem("options", JSON.stringify(this.app.options));
};
@@ -117,7 +121,9 @@ OptionsWaiter.prototype.selectChange = function(e) {
const option = el.getAttribute("option");
this.app.options[option] = el.value;
localStorage.setItem("options", JSON.stringify(this.app.options));
if (this.app.isLocalStorageAvailable())
localStorage.setItem("options", JSON.stringify(this.app.options));
};

View File

@@ -201,4 +201,44 @@ OutputWaiter.prototype.maximiseOutputClick = function(e) {
}
};
/**
* Shows or hides the loading icon.
*
* @param {boolean} value
*/
OutputWaiter.prototype.toggleLoader = function(value) {
const outputLoader = document.getElementById("output-loader"),
outputElement = document.getElementById("output-text");
if (value) {
this.manager.controls.hideStaleIndicator();
this.bakingStatusTimeout = setTimeout(function() {
outputElement.disabled = true;
outputLoader.style.visibility = "visible";
outputLoader.style.opacity = 1;
this.manager.controls.toggleBakeButtonFunction(true);
}.bind(this), 200);
} else {
clearTimeout(this.bakingStatusTimeout);
outputElement.disabled = false;
outputLoader.style.opacity = 0;
outputLoader.style.visibility = "hidden";
this.manager.controls.toggleBakeButtonFunction(false);
this.setStatusMsg("");
}
};
/**
* Sets the baking status message value.
*
* @param {string} msg
*/
OutputWaiter.prototype.setStatusMsg = function(msg) {
const el = document.querySelector("#output-loader .loading-msg");
el.textContent = msg;
};
export default OutputWaiter;

View File

@@ -295,6 +295,9 @@ RecipeWaiter.prototype.getConfig = function() {
option: ingList[j].previousSibling.children[0].textContent.slice(0, -1),
string: ingList[j].value
};
} else if (ingList[j].getAttribute("type") === "number") {
// number
ingredients[j] = parseFloat(ingList[j].value, 10);
} else {
// all others
ingredients[j] = ingList[j].value;

180
src/web/WorkerWaiter.js Normal file
View File

@@ -0,0 +1,180 @@
import Utils from "../core/Utils.js";
import ChefWorker from "worker-loader?inline&fallback=false!../core/ChefWorker.js";
/**
* Waiter to handle conversations with the ChefWorker.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @constructor
* @param {App} app - The main view object for CyberChef.
* @param {Manager} manager - The CyberChef event manager.
*/
const WorkerWaiter = function(app, manager) {
this.app = app;
this.manager = manager;
};
/**
* Sets up the ChefWorker and associated listeners.
*/
WorkerWaiter.prototype.registerChefWorker = function() {
this.chefWorker = new ChefWorker();
this.chefWorker.addEventListener("message", this.handleChefMessage.bind(this));
let docURL = document.location.href.split(/[#?]/)[0];
const index = docURL.lastIndexOf("/");
if (index > 0) {
docURL = docURL.substring(0, index);
}
this.chefWorker.postMessage({"action": "docURL", "data": docURL});
};
/**
* Handler for messages sent back by the ChefWorker.
*
* @param {MessageEvent} e
*/
WorkerWaiter.prototype.handleChefMessage = function(e) {
const r = e.data;
switch (r.action) {
case "bakeSuccess":
this.bakingComplete(r.data);
break;
case "bakeError":
this.app.handleError(r.data);
this.setBakingStatus(false);
break;
case "silentBakeComplete":
break;
case "workerLoaded":
this.app.workerLoaded = true;
this.app.loaded();
break;
case "statusMessage":
this.manager.output.setStatusMsg(r.data);
break;
case "optionUpdate":
this.app.options[r.data.option] = r.data.value;
break;
case "highlightsCalculated":
this.manager.highlighter.displayHighlights(r.data.pos, r.data.direction);
break;
default:
console.error("Unrecognised message from ChefWorker", e);
break;
}
};
/**
* Updates the UI to show if baking is in process or not.
*
* @param {bakingStatus}
*/
WorkerWaiter.prototype.setBakingStatus = function(bakingStatus) {
this.app.baking = bakingStatus;
this.manager.output.toggleLoader(bakingStatus);
};
/**
* Cancels the current bake by terminating the ChefWorker and creating a new one.
*/
WorkerWaiter.prototype.cancelBake = function() {
this.chefWorker.terminate();
this.registerChefWorker();
this.setBakingStatus(false);
this.manager.controls.showStaleIndicator();
};
/**
* Handler for completed bakes.
*
* @param {Object} response
*/
WorkerWaiter.prototype.bakingComplete = function(response) {
this.setBakingStatus(false);
if (!response) return;
if (response.error) {
this.app.handleError(response.error);
}
this.app.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result;
this.app.progress = response.progress;
this.manager.recipe.updateBreakpointIndicator(response.progress);
this.manager.output.set(response.result, response.type, response.duration);
};
/**
* Asks the ChefWorker to bake the current input using the current recipe.
*
* @param {string} input
* @param {Object[]} recipeConfig
* @param {Object} options
* @param {number} progress
* @param {boolean} step
*/
WorkerWaiter.prototype.bake = function(input, recipeConfig, options, progress, step) {
this.setBakingStatus(true);
this.chefWorker.postMessage({
action: "bake",
data: {
input: input,
recipeConfig: recipeConfig,
options: options,
progress: progress,
step: step
}
});
};
/**
* Asks the ChefWorker to run a silent bake, forcing the browser to load and cache all the relevant
* JavaScript code needed to do a real bake.
*
* @param {Objectp[]} [recipeConfig]
*/
WorkerWaiter.prototype.silentBake = function(recipeConfig) {
this.chefWorker.postMessage({
action: "silentBake",
data: {
recipeConfig: recipeConfig
}
});
};
/**
* Asks the ChefWorker to calculate highlight offsets if possible.
*
* @param {Object[]} recipeConfig
* @param {string} direction
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
*/
WorkerWaiter.prototype.highlight = function(recipeConfig, direction, pos) {
this.chefWorker.postMessage({
action: "highlight",
data: {
recipeConfig: recipeConfig,
direction: direction,
pos: pos
}
});
};
export default WorkerWaiter;

View File

@@ -36,8 +36,10 @@
// Load theme before the preloader is shown
try {
document.querySelector(":root").className = JSON.parse(localStorage.getItem("options")).theme;
} catch (e) {}
document.querySelector(":root").className = (JSON.parse(localStorage.getItem("options")) || {}).theme;
} catch (err) {
// LocalStorage access is denied by security settings
}
// Define loading messages
const loadingMsgs = [
@@ -73,7 +75,8 @@
loadingMsgs.push(msg);
try {
const el = document.getElementById("preloader-msg");
el.className = "loading"; // Causes CSS transition on first message
if (!el.classList.contains("loading"))
el.classList.add("loading"); // Causes CSS transition on first message
el.innerHTML = msg;
} catch (err) {} // Ignore errors if DOM not yet ready
}
@@ -90,8 +93,8 @@
<body>
<!-- Preloader overlay -->
<div id="loader-wrapper">
<div id="preloader"></div>
<div id="preloader-msg"></div>
<div id="preloader" class="loader"></div>
<div id="preloader-msg" class="loading-msg"></div>
</div>
<!-- End preloader overlay -->
<span id="edit-favourites" class="btn btn-default btn-sm"><img aria-hidden="true" src="<%- require('../static/images/favourite-16x16.png') %>" alt="Star Icon"/> Edit</span>
@@ -142,7 +145,7 @@
<div id="bake-group">
<button type="button" class="btn btn-success btn-lg" id="bake">
<img aria-hidden="true" src="<%- require('../static/images/cook_male-32x32.png') %>" alt="Chef Icon"/>
Bake!
<span>Bake!</span>
</button>
<label class="btn btn-success btn-lg" id="auto-bake-label" for="auto-bake">
<input type="checkbox" checked="checked" id="auto-bake">
@@ -168,7 +171,6 @@
<div id="input" class="split no-select">
<div class="title no-select">
<label for="input-text">Input</label>
<div class="loading-icon" style="display: none"></div>
<div class="btn-group io-btn-group">
<button type="button" class="btn btn-default btn-sm" id="clr-io"><img aria-hidden="true" src="<%- require('../static/images/recycle-16x16.png') %>" alt="Recycle Icon"/> Clear I/O</button>
<button type="button" class="btn btn-default btn-sm" id="reset-layout"><img aria-hidden="true" src="<%- require('../static/images/layout-16x16.png') %>" alt="Grid Icon"/> Reset layout</button>
@@ -185,7 +187,6 @@
<div id="output" class="split">
<div class="title no-select">
<label for="output-text">Output</label>
<div class="loading-icon" style="display: none"></div>
<div class="btn-group io-btn-group">
<button type="button" class="btn btn-default btn-sm" id="save-to-file" title="Save to file"><img aria-hidden="true" src="<%- require('../static/images/save_as-16x16.png') %>" alt="Save Icon"/> Save to file</button>
<button type="button" class="btn btn-default btn-sm" id="switch" title="Move output to input"><img aria-hidden="true" src="<%- require('../static/images/switch-16x16.png') %>" alt="Switch Icon"/> Move output to input</button>
@@ -194,11 +195,16 @@
</div>
<div class="io-info" id="output-info"></div>
<div class="io-info" id="output-selection-info"></div>
<span id="stale-indicator" title="The output is stale.&#10;The input or recipe has changed since this output was generated. Bake again to get the new value.">&#x1F551;</span>
</div>
<div class="textarea-wrapper">
<div id="output-highlighter" class="no-select"></div>
<div id="output-html"></div>
<textarea id="output-text" readonly="readonly"></textarea>
<div id="output-loader">
<div class="loader"></div>
<div class="loading-msg"></div>
</div>
</div>
</div>
</div>
@@ -215,7 +221,22 @@
<div class="modal-body">
<div class="form-group">
<label for="save-text">Save your recipe to local storage or copy the following string to load later</label>
<textarea class="form-control" id="save-text" rows="5"></textarea>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#chef-format" role="tab" data-toggle="tab">Chef format</a></li>
<li role="presentation"><a href="#clean-json" role="tab" data-toggle="tab">Clean JSON</a></li>
<li role="presentation"><a href="#compact-json" role="tab" data-toggle="tab">Compact JSON</a></li>
</ul>
<div class="tab-content" id="save-texts">
<div role="tabpanel" class="tab-pane active" id="chef-format">
<textarea class="form-control" id="save-text-chef" rows="5"></textarea>
</div>
<div role="tabpanel" class="tab-pane" id="clean-json">
<textarea class="form-control" id="save-text-clean" rows="5"></textarea>
</div>
<div role="tabpanel" class="tab-pane" id="compact-json">
<textarea class="form-control" id="save-text-compact" rows="5"></textarea>
</div>
</div>
</div>
<div class="form-group">
<label for="save-name">Recipe name</label>
@@ -280,6 +301,7 @@
<select option="theme" id="theme">
<option value="classic">Classic</option>
<option value="dark">Dark</option>
<option value="geocities">GeoCities</option>
</select>
<label for="theme"> Theme (only supported in modern browsers)</label>
</div>
@@ -307,10 +329,6 @@
<input type="number" option="errorTimeout" id="errorTimeout" />
<label for="errorTimeout"> Operation error timeout in ms (0 for never) </label>
</div>
<div class="option-item">
<input type="number" option="autoBakeThreshold" id="autoBakeThreshold"/>
<label for="autoBakeThreshold"> Auto Bake threshold in ms </label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="reset-options">Reset options to default</button>
@@ -390,12 +408,12 @@
<div class="collapse" id="faq-examples">
<p>There are around 200 operations in CyberChef allowing you to carry out simple and complex tasks easily. Here are some examples:</p>
<ul>
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
<li><a href="#recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
<li><a href="#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1">Decode a Base64-encoded string</a></li>
<li><a href="#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
<li><a href="#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
<li><a href="#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
</ul>
</div>
<blockquote>
@@ -415,7 +433,7 @@
<div class="collapse" id="faq-fork">
<p>Maybe you have 10 timestamps that you want to parse or 16 encoded strings that all have the same key.</p>
<p>The 'Fork' operation (found in the 'Flow control' category) splits up the input line by line and runs all subsequent operations on each line separately. Each output is then displayed on a separate line. These delimiters can be changed, so if your inputs are separated by commas, you can change the split delimiter to a comma instead.</p>
<p><a href='#recipe=%5B%7B"op"%3A"Fork"%2C"args"%3A%5B"%5C%5Cn"%2C"%5C%5Cn"%5D%7D%2C%7B"op"%3A"From%20UNIX%20Timestamp"%2C"args"%3A%5B"Seconds%20(s)"%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA%3D%3D'>Click here</a> for an example.</p>
<p><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Click here</a> for an example.</p>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="report-bug">

View File

@@ -17,7 +17,7 @@ import CanvasComponents from "../core/lib/canvascomponents.js";
// CyberChef
import App from "./App.js";
import Categories from "../core/config/Categories.js";
import OperationConfig from "../core/config/OperationConfig.js";
import OperationConfig from "../core/config/MetaConfig.js";
/**
@@ -44,7 +44,6 @@ function main() {
wordWrap: true,
showErrors: true,
errorTimeout: 4000,
autoBakeThreshold: 200,
attemptHighlight: true,
theme: "classic",
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 773 B

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 445 B

View File

@@ -9,6 +9,7 @@
/* Themes */
@import "./themes/_classic.css";
@import "./themes/_dark.css";
@import "./themes/_geocities.css";
/* Utilities */
@import "./utils/_overrides.css";

Some files were not shown because too many files have changed in this diff Show More