mirror of
https://github.com/gchq/CyberChef
synced 2026-01-06 18:43:23 +00:00
Compare commits
154 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6845aa03c | ||
|
|
4a673bd92a | ||
|
|
fdffabfdd4 | ||
|
|
ba8591293b | ||
|
|
9b3aae10cf | ||
|
|
5c85c4df63 | ||
|
|
8ece2603fb | ||
|
|
1b54584820 | ||
|
|
3ce3866000 | ||
|
|
becc258b6c | ||
|
|
16c9e7119d | ||
|
|
f5888fea9c | ||
|
|
b5162c7549 | ||
|
|
1baea1da3d | ||
|
|
40899a6fe4 | ||
|
|
66c533431d | ||
|
|
74ae77f17a | ||
|
|
99eb1cced5 | ||
|
|
c880ecf3c4 | ||
|
|
c54c34d88e | ||
|
|
60b3c597a7 | ||
|
|
372ab32539 | ||
|
|
e14745a973 | ||
|
|
afffe584cf | ||
|
|
cf532f1e30 | ||
|
|
46425ba552 | ||
|
|
9f65fac4e6 | ||
|
|
af98feff51 | ||
|
|
339c741a2c | ||
|
|
d1bde23f00 | ||
|
|
be544faf0f | ||
|
|
eff77fd3bb | ||
|
|
3df57ba3dd | ||
|
|
4bae662357 | ||
|
|
357c90546e | ||
|
|
54769a90ac | ||
|
|
0550aedd54 | ||
|
|
5947ed21fc | ||
|
|
0a0949246f | ||
|
|
09c6e181fb | ||
|
|
02cf394bcd | ||
|
|
46afbf9888 | ||
|
|
7cf19d22a8 | ||
|
|
46d708360f | ||
|
|
7ec91e2366 | ||
|
|
a74ee47bf0 | ||
|
|
7b68b92498 | ||
|
|
274f3acd45 | ||
|
|
53dff8b30f | ||
|
|
9892ee273e | ||
|
|
7dccecb336 | ||
|
|
aa09da0403 | ||
|
|
98d7f1481c | ||
|
|
7d8bdbcf7e | ||
|
|
db009d3689 | ||
|
|
d7bc529a95 | ||
|
|
3f035294a6 | ||
|
|
36282e362f | ||
|
|
223353cf4d | ||
|
|
ded32da632 | ||
|
|
d6fc21cc34 | ||
|
|
b86e960456 | ||
|
|
7747bfe0f2 | ||
|
|
fabea8cc61 | ||
|
|
de4cd2eebc | ||
|
|
e16ce1d9c2 | ||
|
|
345ad741b3 | ||
|
|
e53108c493 | ||
|
|
6129378854 | ||
|
|
11a1416dcc | ||
|
|
9025538544 | ||
|
|
46929e1844 | ||
|
|
bf023cad48 | ||
|
|
f649236bad | ||
|
|
54b1454c0a | ||
|
|
a41b1c2f5e | ||
|
|
0327d7cb7a | ||
|
|
621d7c3683 | ||
|
|
ae7c3fca31 | ||
|
|
1b3295ff59 | ||
|
|
e40e7a0e4e | ||
|
|
cf5fd7cbf2 | ||
|
|
ec37a676a8 | ||
|
|
f33193e122 | ||
|
|
7c40204e4f | ||
|
|
2b2ffb3346 | ||
|
|
39b7e4ff9e | ||
|
|
a1109c43f6 | ||
|
|
e6eafc2843 | ||
|
|
3e8dea73d2 | ||
|
|
bbf19ee944 | ||
|
|
f6c8c9e76c | ||
|
|
9dba1232b7 | ||
|
|
bf14c8983f | ||
|
|
3ab95384df | ||
|
|
953a581a94 | ||
|
|
3bfddd708c | ||
|
|
13a54ec318 | ||
|
|
2781640a2a | ||
|
|
7989f119d3 | ||
|
|
2e0aa7ae87 | ||
|
|
0b5ee7c79f | ||
|
|
23cbe1c426 | ||
|
|
de727bcddc | ||
|
|
c9d9730726 | ||
|
|
a380aed878 | ||
|
|
4dafa50799 | ||
|
|
d4ae241758 | ||
|
|
53e69835ff | ||
|
|
939208903a | ||
|
|
616b38c6fb | ||
|
|
a302df8f91 | ||
|
|
093512a55a | ||
|
|
007224c92e | ||
|
|
738ee33959 | ||
|
|
d720a6b250 | ||
|
|
5ce3cc17bb | ||
|
|
5c35205315 | ||
|
|
10751934e4 | ||
|
|
d658f91106 | ||
|
|
fae96af17d | ||
|
|
57c1a03c4f | ||
|
|
fad163e0eb | ||
|
|
7ad3992bd1 | ||
|
|
e7b5c0e37c | ||
|
|
cc35127459 | ||
|
|
1c0ecd29c2 | ||
|
|
18c6b9bc09 | ||
|
|
2233b9a094 | ||
|
|
e0f000b913 | ||
|
|
73864e0809 | ||
|
|
4c3324aea1 | ||
|
|
ac2fcee90f | ||
|
|
94e00115fe | ||
|
|
29255d2338 | ||
|
|
39278cfce7 | ||
|
|
46cc48cfb9 | ||
|
|
eb4009949d | ||
|
|
57c48a4bd2 | ||
|
|
45011de494 | ||
|
|
5e51ed0a5f | ||
|
|
8a029e5147 | ||
|
|
4251089687 | ||
|
|
dbcd670ca8 | ||
|
|
462f619f43 | ||
|
|
123a0ccd70 | ||
|
|
4c737475d4 | ||
|
|
4e0d97f2c1 | ||
|
|
85906cafbb | ||
|
|
a8dc691033 | ||
|
|
4d7988b78e | ||
|
|
841e760b04 | ||
|
|
31e758ca45 | ||
|
|
f81ca3ba60 |
54
.github/workflows/master.yml
vendored
Normal file
54
.github/workflows/master.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Master
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
npm install
|
||||
export NODE_OPTIONS=--max_old_space_size=2048
|
||||
|
||||
- name: Lint
|
||||
run: npx grunt lint
|
||||
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
npm test
|
||||
npx grunt testnodeconsumer
|
||||
|
||||
- name: Production Build
|
||||
if: success()
|
||||
run: npx grunt prod
|
||||
|
||||
- name: Generate sitemap
|
||||
run: npx grunt exec:sitemap
|
||||
|
||||
- name: UI Tests
|
||||
if: success()
|
||||
run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
|
||||
- name: Prepare for GitHub Pages
|
||||
if: success()
|
||||
run: npx grunt copy:ghPages
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
if: success() && github.ref == 'refs/heads/master'
|
||||
uses: crazy-max/ghaction-github-pages@v2
|
||||
with:
|
||||
target_branch: gh-pages
|
||||
build_dir: ./build/prod
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
37
.github/workflows/pull_requests.yml
vendored
Normal file
37
.github/workflows/pull_requests.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened]
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
npm install
|
||||
export NODE_OPTIONS=--max_old_space_size=2048
|
||||
|
||||
- name: Lint
|
||||
run: npx grunt lint
|
||||
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
npm test
|
||||
npx grunt testnodeconsumer
|
||||
|
||||
- name: Production Build
|
||||
if: success()
|
||||
run: npx grunt prod
|
||||
|
||||
- name: UI Tests
|
||||
if: success()
|
||||
run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
55
.github/workflows/releases.yml
vendored
Normal file
55
.github/workflows/releases.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '10.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
npm install
|
||||
export NODE_OPTIONS=--max_old_space_size=2048
|
||||
|
||||
- name: Lint
|
||||
run: npx grunt lint
|
||||
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
npm test
|
||||
npx grunt testnodeconsumer
|
||||
|
||||
- name: Production Build
|
||||
if: success()
|
||||
run: npx grunt prod
|
||||
|
||||
- name: UI Tests
|
||||
if: success()
|
||||
run: xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||
|
||||
- name: Upload Release Assets
|
||||
if: success()
|
||||
id: upload-release-assets
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: build/prod/*.zip
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
|
||||
- name: Publish to NPM
|
||||
if: success()
|
||||
uses: JS-DevTools/npm-publish@v1
|
||||
with:
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
55
.travis.yml
55
.travis.yml
@@ -1,55 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- lts/dubnium
|
||||
cache: npm
|
||||
os: linux
|
||||
addons:
|
||||
chrome: stable
|
||||
install: npm install
|
||||
before_script:
|
||||
- npm install -g grunt
|
||||
- export NODE_OPTIONS=--max_old_space_size=2048
|
||||
script:
|
||||
- grunt lint
|
||||
- npm test
|
||||
- grunt testnodeconsumer
|
||||
- grunt prod --msg="$COMPILE_MSG"
|
||||
- xvfb-run --server-args="-screen 0 1200x800x24" grunt testui
|
||||
before_deploy:
|
||||
- grunt exec:sitemap
|
||||
- grunt copy:ghPages
|
||||
deploy:
|
||||
- provider: pages
|
||||
edge: true
|
||||
token: $GITHUB_TOKEN
|
||||
local_dir: build/prod/
|
||||
target_branch: gh-pages
|
||||
on:
|
||||
repo: gchq/CyberChef
|
||||
branch: master
|
||||
- provider: releases
|
||||
edge: true
|
||||
token:
|
||||
secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA="
|
||||
file_glob: true
|
||||
file:
|
||||
- build/prod/*.zip
|
||||
- src/node/cjs.js
|
||||
on:
|
||||
repo: gchq/CyberChef
|
||||
tags: true
|
||||
- provider: npm
|
||||
edge: true
|
||||
email: "n1474335@gmail.com"
|
||||
api_token:
|
||||
secure: "UnDQL3Kh+GK2toL0TK3FObO0ujVssU3Eg4BBuYdjwLB81GhiGE5/DTh7THdZPOpbLo6wQeOwfZDuMeKC1OU+0Uf4NsdYFu1aq6xMO20qBQ4qUfgsyiK4Qgywj9gk0p1+OFZdGAZ/j1CNRAaF71XQIY6iV84c+SO4WoizXYrNT0Jh4sr2DA4/97G2xmJtPi0qOzYrJ09R56ZUozmqeik5G0pMRIuJRbpjS/7bZXV+N7WV0ombZc9RkUaetbabEVOLQ+Xx5YAIVq+VuEeMe9VBSnxY/FfCLmy1wJsjGzpLCyBI9nbrG4nw8Wgc2m8NfK9rcpIvBTGner9r2j60NVDkZ8kLZPrqXhq6AZMwa+oz6K5UQCqRo2RRQzSGwXxg67HY5Tcq+oNmjd+DqpPg4LZ3eGlluyP5XfG+hpSr9Ya4d8q8SrUWLxkoLHI6ZKMtoKFbTCSSQPiluW5hsZxjz3yDkkjsJw64M/EM8UyJrgaXqDklQu+7rBGKLfsK6os7RDiqjBWpQ7gwpo8HvY0O8yqEAabPz+QGkanpjcCOZCXFbSkzWxYy37RMAPu88iINVZVlZE4l+WJenCpZY95ueyy0mG9cyMSzVRPyX6A+/n4H6VMFPFjpGDLTD588ACEjY1lmHfS/eXwXJcgqPPD2gW0XdRdUheU/ssqlfCfGWQMTDXs="
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/83c143a6822e218d5b34
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: never
|
||||
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,7 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## Versioning
|
||||
|
||||
CyberChef uses the [semver](https://semver.org/) system to manage versioning: MAJOR.MINOR.PATCH.
|
||||
|
||||
- MAJOR version changes represent a significant change to the fundamental architecture of CyberChef and may (but don't always) make breaking changes that are not backwards compatible.
|
||||
- MINOR version changes usually mean the addition of new operations or reasonably significant new features.
|
||||
- PATCH versions are used for bug fixes and any other small tweaks that modify or improve existing capabilities.
|
||||
|
||||
All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master).
|
||||
|
||||
|
||||
## Details
|
||||
|
||||
### [9.24.0] - 2020-02-02
|
||||
- 'SM3' hashing function added along with more configuration options for other hashing operations [@n1073645] [@n1474335] | [#1022]
|
||||
|
||||
### [9.23.0] - 2020-02-01
|
||||
- Various RSA operations added to encrypt, decrypt, sign, verify and generate keys [@mattnotmitt] [@GCHQ77703] | [#652]
|
||||
|
||||
### [9.22.0] - 2021-02-01
|
||||
- 'Unicode Text Format' operation added [@mattnotmitt] | [#1083]
|
||||
|
||||
### [9.21.0] - 2020-06-12
|
||||
- Node API now exports `magic` operation [@d98762625] | [#1049]
|
||||
|
||||
### [9.20.0] - 2020-03-27
|
||||
- 'Parse ObjectID Timestamp' operation added [@dmfj] | [#987]
|
||||
|
||||
@@ -224,6 +247,10 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
|
||||
|
||||
[9.24.0]: https://github.com/gchq/CyberChef/releases/tag/v9.24.0
|
||||
[9.23.0]: https://github.com/gchq/CyberChef/releases/tag/v9.23.0
|
||||
[9.22.0]: https://github.com/gchq/CyberChef/releases/tag/v9.22.0
|
||||
[9.21.0]: https://github.com/gchq/CyberChef/releases/tag/v9.21.0
|
||||
[9.20.0]: https://github.com/gchq/CyberChef/releases/tag/v9.20.0
|
||||
[9.19.0]: https://github.com/gchq/CyberChef/releases/tag/v9.19.0
|
||||
[9.18.0]: https://github.com/gchq/CyberChef/releases/tag/v9.18.0
|
||||
@@ -323,6 +350,7 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[@pointhi]: https://github.com/pointhi
|
||||
[@MarvinJWendt]: https://github.com/MarvinJWendt
|
||||
[@dmfj]: https://github.com/dmfj
|
||||
[@mattnotmitt]: https://github.com/mattnotmitt
|
||||
|
||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||
@@ -384,6 +412,7 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#625]: https://github.com/gchq/CyberChef/pull/625
|
||||
[#627]: https://github.com/gchq/CyberChef/pull/627
|
||||
[#632]: https://github.com/gchq/CyberChef/pull/632
|
||||
[#652]: https://github.com/gchq/CyberChef/pull/652
|
||||
[#653]: https://github.com/gchq/CyberChef/pull/653
|
||||
[#674]: https://github.com/gchq/CyberChef/pull/674
|
||||
[#683]: https://github.com/gchq/CyberChef/pull/683
|
||||
@@ -395,3 +424,6 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#965]: https://github.com/gchq/CyberChef/pull/965
|
||||
[#966]: https://github.com/gchq/CyberChef/pull/966
|
||||
[#987]: https://github.com/gchq/CyberChef/pull/987
|
||||
[#1022]: https://github.com/gchq/CyberChef/pull/1022
|
||||
[#1049]: https://github.com/gchq/CyberChef/pull/1049
|
||||
[#1083]: https://github.com/gchq/CyberChef/pull/1083
|
||||
19
Gruntfile.js
19
Gruntfile.js
@@ -37,7 +37,7 @@ module.exports = function (grunt) {
|
||||
]);
|
||||
|
||||
grunt.registerTask("configTests",
|
||||
"A task which configures config files in preparation for tests to be run. Use `npm tests` to run tests.",
|
||||
"A task which configures config files in preparation for tests to be run. Use `npm test` to run tests.",
|
||||
[
|
||||
"clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex"
|
||||
]);
|
||||
@@ -78,7 +78,6 @@ module.exports = function (grunt) {
|
||||
grunt.loadNpmTasks("grunt-contrib-watch");
|
||||
grunt.loadNpmTasks("grunt-chmod");
|
||||
grunt.loadNpmTasks("grunt-exec");
|
||||
grunt.loadNpmTasks("grunt-accessibility");
|
||||
grunt.loadNpmTasks("grunt-concurrent");
|
||||
grunt.loadNpmTasks("grunt-contrib-connect");
|
||||
grunt.loadNpmTasks("grunt-zip");
|
||||
@@ -197,18 +196,6 @@ module.exports = function (grunt) {
|
||||
node: ["src/node/**/*.{js,mjs}"],
|
||||
tests: ["tests/**/*.{js,mjs}"],
|
||||
},
|
||||
accessibility: {
|
||||
options: {
|
||||
accessibilityLevel: "WCAG2A",
|
||||
verbose: false,
|
||||
ignore: [
|
||||
"WCAG2A.Principle1.Guideline1_3.1_3_1.H42.2"
|
||||
]
|
||||
},
|
||||
test: {
|
||||
src: ["build/**/*.html"]
|
||||
}
|
||||
},
|
||||
webpack: {
|
||||
options: webpackConfig,
|
||||
web: webpackProdConf(),
|
||||
@@ -302,7 +289,7 @@ module.exports = function (grunt) {
|
||||
},
|
||||
files: [
|
||||
{
|
||||
src: "build/prod/index.html",
|
||||
src: ["build/prod/index.html"],
|
||||
dest: "build/prod/index.html"
|
||||
}
|
||||
]
|
||||
@@ -324,7 +311,7 @@ module.exports = function (grunt) {
|
||||
},
|
||||
files: [
|
||||
{
|
||||
src: "build/prod/index.html",
|
||||
src: ["build/prod/index.html"],
|
||||
dest: `build/prod/CyberChef_v${pkg.version}.html`
|
||||
}
|
||||
]
|
||||
|
||||
10308
package-lock.json
generated
10308
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
156
package.json
156
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.20.0",
|
||||
"version": "9.24.1",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -36,124 +36,131 @@
|
||||
"node >= 10"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.8.7",
|
||||
"@babel/plugin-transform-runtime": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"autoprefixer": "^9.7.4",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"autoprefixer": "^10.2.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.0",
|
||||
"chromedriver": "^80.0.1",
|
||||
"cli-progress": "^3.6.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"chromedriver": "^88.0.0",
|
||||
"cli-progress": "^3.9.0",
|
||||
"colors": "^1.4.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"eslint": "^6.8.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"file-loader": "^6.0.0",
|
||||
"grunt": "^1.1.0",
|
||||
"grunt-accessibility": "~6.0.0",
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
"css-loader": "^5.0.1",
|
||||
"eslint": "^7.19.0",
|
||||
"exports-loader": "^2.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"grunt": "^1.3.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-concurrent": "^3.0.0",
|
||||
"grunt-contrib-clean": "~2.0.0",
|
||||
"grunt-contrib-connect": "^2.1.0",
|
||||
"grunt-contrib-connect": "^3.0.0",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-eslint": "^22.0.0",
|
||||
"grunt-eslint": "^23.0.0",
|
||||
"grunt-exec": "~3.0.0",
|
||||
"grunt-webpack": "^3.1.3",
|
||||
"grunt-webpack": "^4.0.2",
|
||||
"grunt-zip": "^0.18.2",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"imports-loader": "^0.8.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"nightwatch": "^1.3.4",
|
||||
"node-sass": "^4.13.1",
|
||||
"postcss-css-variables": "^0.14.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"sitemap": "^6.1.0",
|
||||
"style-loader": "^1.1.3",
|
||||
"svg-url-loader": "^5.0.0",
|
||||
"url-loader": "^4.0.0",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-bundle-analyzer": "^3.6.1",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-node-externals": "^1.7.2",
|
||||
"worker-loader": "^2.0.0"
|
||||
"html-webpack-plugin": "^4.5.1",
|
||||
"imports-loader": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^1.3.5",
|
||||
"nightwatch": "^1.5.1",
|
||||
"node-sass": "^5.0.0",
|
||||
"postcss": "^8.2.4",
|
||||
"postcss-css-variables": "^0.17.0",
|
||||
"postcss-import": "^14.0.0",
|
||||
"postcss-loader": "^4.2.0",
|
||||
"prompt": "^1.1.0",
|
||||
"sass-loader": "^10.1.1",
|
||||
"sitemap": "^6.3.5",
|
||||
"style-loader": "^2.0.0",
|
||||
"svg-url-loader": "^7.1.1",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.19.0",
|
||||
"webpack-bundle-analyzer": "^4.4.0",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-node-externals": "^2.5.2",
|
||||
"worker-loader": "^3.0.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.8.7",
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"arrive": "^2.4.1",
|
||||
"avsc": "^5.4.19",
|
||||
"avsc": "^5.5.3",
|
||||
"babel-plugin-transform-builtin-extend": "1.1.2",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"blakejs": "^1.1.0",
|
||||
"bootstrap": "4.4.1",
|
||||
"bootstrap": "4.6.0",
|
||||
"bootstrap-colorpicker": "^3.2.0",
|
||||
"bootstrap-material-design": "^4.1.2",
|
||||
"bson": "^4.0.3",
|
||||
"bootstrap-material-design": "^4.1.3",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
"bson": "^4.2.2",
|
||||
"buffer": "^6.0.3",
|
||||
"chi-squared": "^1.1.0",
|
||||
"codepage": "^1.14.0",
|
||||
"core-js": "^3.6.4",
|
||||
"core-js": "^3.8.3",
|
||||
"crypto-api": "^0.8.5",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"crypto-js": "^4.0.0",
|
||||
"ctph.js": "0.0.5",
|
||||
"d3": "^5.15.0",
|
||||
"d3": "^6.5.0",
|
||||
"d3-hexbin": "^0.2.2",
|
||||
"diff": "^4.0.2",
|
||||
"es6-promisify": "^6.1.0",
|
||||
"escodegen": "^1.14.1",
|
||||
"diff": "^5.0.0",
|
||||
"es6-promisify": "^6.1.1",
|
||||
"escodegen": "^2.0.0",
|
||||
"esm": "^3.2.25",
|
||||
"esmangle": "^1.0.1",
|
||||
"esprima": "^4.0.1",
|
||||
"exif-parser": "^0.1.12",
|
||||
"file-saver": "^2.0.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"flat": "^5.0.2",
|
||||
"geodesy": "^1.1.3",
|
||||
"highlight.js": "^9.18.1",
|
||||
"jimp": "^0.9.5",
|
||||
"jquery": "3.4.1",
|
||||
"highlight.js": "^10.5.0",
|
||||
"jimp": "^0.16.1",
|
||||
"jquery": "3.5.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
"jsesc": "^2.5.2",
|
||||
"jsonpath": "^1.0.2",
|
||||
"jsesc": "^3.0.2",
|
||||
"jsonpath": "^1.1.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jsqr": "^1.2.0",
|
||||
"jsrsasign": "8.0.12",
|
||||
"kbpgp": "2.1.13",
|
||||
"jsqr": "^1.3.1",
|
||||
"jsrsasign": "10.1.5",
|
||||
"kbpgp": "2.1.15",
|
||||
"libbzip2-wasm": "0.0.4",
|
||||
"libyara-wasm": "^1.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"loglevel": "^1.6.7",
|
||||
"libyara-wasm": "^1.1.0",
|
||||
"lodash": "^4.17.20",
|
||||
"loglevel": "^1.7.1",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"markdown-it": "^10.0.0",
|
||||
"moment": "^2.24.0",
|
||||
"moment-timezone": "^0.5.28",
|
||||
"markdown-it": "^12.0.4",
|
||||
"moment": "^2.29.1",
|
||||
"moment-timezone": "^0.5.32",
|
||||
"ngeohash": "^0.6.3",
|
||||
"node-forge": "^0.9.1",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-md6": "^0.1.0",
|
||||
"nodom": "^2.4.0",
|
||||
"notepack.io": "^2.3.0",
|
||||
"nwmatcher": "^1.4.4",
|
||||
"otp": "^0.1.3",
|
||||
"path": "^0.12.7",
|
||||
"popper.js": "^1.16.1",
|
||||
"process": "^0.11.10",
|
||||
"qr-image": "^3.2.0",
|
||||
"scryptsy": "^2.1.0",
|
||||
"snackbarjs": "^1.1.0",
|
||||
"sortablejs": "^1.10.2",
|
||||
"split.js": "^1.5.11",
|
||||
"sortablejs": "^1.13.0",
|
||||
"split.js": "^1.6.2",
|
||||
"ssdeep.js": "0.0.2",
|
||||
"tesseract.js": "^2.0.2",
|
||||
"ua-parser-js": "^0.7.21",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"terser": "^5.5.1",
|
||||
"tesseract.js": "^2.1.1",
|
||||
"ua-parser-js": "^0.7.23",
|
||||
"unorm": "^1.6.0",
|
||||
"utf8": "^3.0.0",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.3.0",
|
||||
"xpath": "0.0.27",
|
||||
"xregexp": "^4.3.0",
|
||||
"xmldom": "^0.4.0",
|
||||
"xpath": "0.0.32",
|
||||
"xregexp": "^4.4.1",
|
||||
"zlibjs": "^0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -165,6 +172,7 @@
|
||||
"testui": "grunt testui",
|
||||
"testuidev": "npx nightwatch --env=dev",
|
||||
"lint": "grunt lint",
|
||||
"postinstall": "bash postinstall.sh",
|
||||
"newop": "node --experimental-modules src/core/config/scripts/newOperation.mjs"
|
||||
}
|
||||
}
|
||||
|
||||
8
postinstall.sh
Executable file
8
postinstall.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Add file extensions to Crypto-Api imports
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
find ./node_modules/crypto-api/src/ \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i '' -e '/\.mjs/!s/\(from "\.[^"]*\)";/\1.mjs";/g'
|
||||
else
|
||||
find ./node_modules/crypto-api/src/ \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i -e '/\.mjs/!s/\(from "\.[^"]*\)";/\1.mjs";/g'
|
||||
fi
|
||||
@@ -134,6 +134,11 @@
|
||||
"PGP Verify",
|
||||
"PGP Encrypt and Sign",
|
||||
"PGP Decrypt and Verify",
|
||||
"Generate RSA Key Pair",
|
||||
"RSA Sign",
|
||||
"RSA Verify",
|
||||
"RSA Encrypt",
|
||||
"RSA Decrypt",
|
||||
"Parse SSH Host Key"
|
||||
]
|
||||
},
|
||||
@@ -200,6 +205,7 @@
|
||||
"ops": [
|
||||
"Encode text",
|
||||
"Decode text",
|
||||
"Unicode Text Format",
|
||||
"Remove Diacritics",
|
||||
"Unescape Unicode Characters",
|
||||
"Convert to NATO alphabet"
|
||||
@@ -313,6 +319,7 @@
|
||||
"SHA1",
|
||||
"SHA2",
|
||||
"SHA3",
|
||||
"SM3",
|
||||
"Keccak",
|
||||
"Shake",
|
||||
"RIPEMD",
|
||||
|
||||
@@ -17,7 +17,7 @@ class DishJSON extends DishType {
|
||||
*/
|
||||
static toArrayBuffer() {
|
||||
DishJSON.checkForValue(this.value);
|
||||
this.value = this.value ? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4)) : new ArrayBuffer;
|
||||
this.value = this.value !== undefined ? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4)) : new ArrayBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
const crypto = {};
|
||||
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
|
||||
/* dojo-release-1.8.1/dojo/_base/lang.js.uncompressed.js */
|
||||
|
||||
@@ -468,6 +468,34 @@ export const FILE_SIGNATURES = {
|
||||
],
|
||||
extractor: null
|
||||
},
|
||||
{
|
||||
name: "Targa Image",
|
||||
extension: "tga",
|
||||
mime: "image/x-targa",
|
||||
description: "",
|
||||
signature: [
|
||||
{ // This signature is not at the beginning of the file. The extractor works backwards.
|
||||
0: 0x54,
|
||||
1: 0x52,
|
||||
2: 0x55,
|
||||
3: 0x45,
|
||||
4: 0x56,
|
||||
5: 0x49,
|
||||
6: 0x53,
|
||||
7: 0x49,
|
||||
8: 0x4f,
|
||||
9: 0x4e,
|
||||
10: 0x2d,
|
||||
11: 0x58,
|
||||
12: 0x46,
|
||||
13: 0x49,
|
||||
14: 0x4c,
|
||||
15: 0x45,
|
||||
16: 0x2e
|
||||
}
|
||||
],
|
||||
extractor: extractTARGA
|
||||
}
|
||||
],
|
||||
"Video": [
|
||||
{ // Place before webm
|
||||
@@ -3047,6 +3075,90 @@ export function extractICO(bytes, offset) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TARGA extractor.
|
||||
*
|
||||
* @param {Uint8Array} bytes
|
||||
* @param {number} offset
|
||||
*/
|
||||
export function extractTARGA(bytes, offset) {
|
||||
// Need all the bytes since we do not know how far up the image goes.
|
||||
const stream = new Stream(bytes);
|
||||
stream.moveTo(offset - 8);
|
||||
|
||||
// Read in the offsets of the possible areas.
|
||||
const extensionOffset = stream.readInt(4, "le");
|
||||
const developerOffset = stream.readInt(4, "le");
|
||||
|
||||
stream.moveBackwardsBy(8);
|
||||
|
||||
/**
|
||||
* Moves backwards in the stream until it meet bytes that are the same as the amount of bytes moved.
|
||||
*
|
||||
* @param {number} sizeOfSize
|
||||
* @param {number} maxSize
|
||||
*/
|
||||
function moveBackwardsUntilSize(maxSize, sizeOfSize) {
|
||||
for (let i = 0; i < maxSize; i++) {
|
||||
stream.moveBackwardsBy(1);
|
||||
|
||||
// Read in sizeOfSize amount of bytes in.
|
||||
const size = stream.readInt(sizeOfSize, "le") - 1;
|
||||
stream.moveBackwardsBy(sizeOfSize);
|
||||
|
||||
// If the size matches.
|
||||
if (size === i)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves backwards in the stream until we meet bytes(when calculated) that are the same as the amount of bytes moved.
|
||||
*/
|
||||
function moveBackwardsUntilImageSize() {
|
||||
stream.moveBackwardsBy(5);
|
||||
|
||||
// The documentation said that 0x100000 was the largest the file could be.
|
||||
for (let i = 0; i < 0x100000; i++) {
|
||||
|
||||
// (Height * Width * pixel depth in bits)/8
|
||||
const total = (stream.readInt(2, "le") * stream.readInt(2, "le") * stream.readInt(1))/8;
|
||||
if (total === i-1)
|
||||
break;
|
||||
|
||||
stream.moveBackwardsBy(6);
|
||||
}
|
||||
}
|
||||
|
||||
if (extensionOffset || developerOffset) {
|
||||
if (extensionOffset) {
|
||||
// Size is stored in two bytes hence the maximum is 0xffff.
|
||||
moveBackwardsUntilSize(0xffff, 2);
|
||||
|
||||
// Move to where we think the start of the file is.
|
||||
stream.moveBackwardsBy(extensionOffset);
|
||||
} else if (developerOffset) {
|
||||
// Size is stored in 4 bytes hence the maxiumum is 0xffffffff.
|
||||
moveBackwardsUntilSize(0xffffffff, 4);
|
||||
|
||||
// Size is stored in byte position 6 so have to move back.
|
||||
stream.moveBackwardsBy(6);
|
||||
|
||||
// Move to where we think the start of the file is.
|
||||
stream.moveBackwardsBy(developerOffset);
|
||||
}
|
||||
} else {
|
||||
// Move backwards until size === number of bytes passed.
|
||||
moveBackwardsUntilImageSize();
|
||||
|
||||
// Move backwards over the reaminder of the header + the 5 we borrowed in moveBackwardsUntilImageSize().
|
||||
stream.moveBackwardsBy(0xc+5);
|
||||
}
|
||||
|
||||
return stream.carve(stream.position, offset+0x12);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* WAV extractor.
|
||||
*
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import jsQR from "jsqr";
|
||||
import qr from "qr-image";
|
||||
import jimp from "jimp";
|
||||
import Utils from "../Utils.mjs";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Parses a QR code image from an image
|
||||
|
||||
17
src/core/lib/RSA.mjs
Normal file
17
src/core/lib/RSA.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* RSA resources.
|
||||
*
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import forge from "node-forge";
|
||||
|
||||
export const MD_ALGORITHMS = {
|
||||
"SHA-1": forge.md.sha1,
|
||||
"MD5": forge.md.md5,
|
||||
"SHA-256": forge.md.sha256,
|
||||
"SHA-384": forge.md.sha384,
|
||||
"SHA-512": forge.md.sha512,
|
||||
};
|
||||
@@ -303,11 +303,13 @@ export default class Stream {
|
||||
/**
|
||||
* Returns a slice of the stream up to the current position.
|
||||
*
|
||||
* @param {number} [start=0]
|
||||
* @param {number} [finish=this.position]
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
carve() {
|
||||
if (this.bitPos > 0) this.position++;
|
||||
return this.bytes.slice(0, this.position);
|
||||
carve(start=0, finish=this.position) {
|
||||
if (this.bitPos > 0) finish++;
|
||||
return this.bytes.slice(start, finish);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
@@ -41,8 +41,33 @@ class AESDecrypt extends Operation {
|
||||
},
|
||||
{
|
||||
"name": "Mode",
|
||||
"type": "option",
|
||||
"value": ["CBC", "CFB", "OFB", "CTR", "GCM", "ECB"]
|
||||
"type": "argSelector",
|
||||
"value": [
|
||||
{
|
||||
name: "CBC",
|
||||
off: [5, 6]
|
||||
},
|
||||
{
|
||||
name: "CFB",
|
||||
off: [5, 6]
|
||||
},
|
||||
{
|
||||
name: "OFB",
|
||||
off: [5, 6]
|
||||
},
|
||||
{
|
||||
name: "CTR",
|
||||
off: [5, 6]
|
||||
},
|
||||
{
|
||||
name: "GCM",
|
||||
on: [5, 6]
|
||||
},
|
||||
{
|
||||
name: "ECB",
|
||||
off: [5, 6]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Input",
|
||||
@@ -59,6 +84,11 @@ class AESDecrypt extends Operation {
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "Additional Authenticated Data",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -76,7 +106,8 @@ class AESDecrypt extends Operation {
|
||||
mode = args[2],
|
||||
inputType = args[3],
|
||||
outputType = args[4],
|
||||
gcmTag = Utils.convertToByteString(args[5].string, args[5].option);
|
||||
gcmTag = Utils.convertToByteString(args[5].string, args[5].option),
|
||||
aad = args[6];
|
||||
|
||||
if ([16, 24, 32].indexOf(key.length) < 0) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||
@@ -92,7 +123,8 @@ The following algorithms will be used based on the size of the key:
|
||||
const decipher = forge.cipher.createDecipher("AES-" + mode, key);
|
||||
decipher.start({
|
||||
iv: iv.length === 0 ? "" : iv,
|
||||
tag: gcmTag
|
||||
tag: mode === "GCM" ? gcmTag : undefined,
|
||||
additionalData: mode === "GCM" ? aad : undefined
|
||||
});
|
||||
decipher.update(forge.util.createBuffer(input));
|
||||
const result = decipher.finish();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
@@ -41,8 +41,33 @@ class AESEncrypt extends Operation {
|
||||
},
|
||||
{
|
||||
"name": "Mode",
|
||||
"type": "option",
|
||||
"value": ["CBC", "CFB", "OFB", "CTR", "GCM", "ECB"]
|
||||
"type": "argSelector",
|
||||
"value": [
|
||||
{
|
||||
name: "CBC",
|
||||
off: [5]
|
||||
},
|
||||
{
|
||||
name: "CFB",
|
||||
off: [5]
|
||||
},
|
||||
{
|
||||
name: "OFB",
|
||||
off: [5]
|
||||
},
|
||||
{
|
||||
name: "CTR",
|
||||
off: [5]
|
||||
},
|
||||
{
|
||||
name: "GCM",
|
||||
on: [5]
|
||||
},
|
||||
{
|
||||
name: "ECB",
|
||||
off: [5]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Input",
|
||||
@@ -53,6 +78,11 @@ class AESEncrypt extends Operation {
|
||||
"name": "Output",
|
||||
"type": "option",
|
||||
"value": ["Hex", "Raw"]
|
||||
},
|
||||
{
|
||||
"name": "Additional Authenticated Data",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -69,7 +99,8 @@ class AESEncrypt extends Operation {
|
||||
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||
mode = args[2],
|
||||
inputType = args[3],
|
||||
outputType = args[4];
|
||||
outputType = args[4],
|
||||
aad = args[5];
|
||||
|
||||
if ([16, 24, 32].indexOf(key.length) < 0) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||
@@ -83,7 +114,10 @@ The following algorithms will be used based on the size of the key:
|
||||
input = Utils.convertToByteString(input, inputType);
|
||||
|
||||
const cipher = forge.cipher.createCipher("AES-" + mode, key);
|
||||
cipher.start({iv: iv});
|
||||
cipher.start({
|
||||
iv: iv,
|
||||
additionalData: mode === "GCM" ? aad : undefined
|
||||
});
|
||||
cipher.update(forge.util.createBuffer(input));
|
||||
cipher.finish();
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Add Text To Image operation
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { Blowfish } from "../lib/Blowfish.mjs";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { Blowfish } from "../lib/Blowfish.mjs";
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import jimp from "jimp";
|
||||
import { gaussianBlur } from "../lib/ImageManipulation.mjs";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Blur Image operation
|
||||
|
||||
@@ -21,7 +21,7 @@ class CTPH extends Operation {
|
||||
this.name = "CTPH";
|
||||
this.module = "Crypto";
|
||||
this.description = "Context Triggered Piecewise Hashing, also called Fuzzy Hashing, can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.<br><br>CTPH was originally based on the work of Dr. Andrew Tridgell and a spam email detector called SpamSum. This method was adapted by Jesse Kornblum and published at the DFRWS conference in 2006 in a paper 'Identifying Almost Identical Files Using Context Triggered Piecewise Hashing'.";
|
||||
this.infoURL = "https://forensicswiki.org/wiki/Context_Triggered_Piecewise_Hashing";
|
||||
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=Context_Triggered_Piecewise_Hashing";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
|
||||
@@ -24,7 +24,7 @@ class CompareCTPHHashes extends Operation {
|
||||
this.name = "Compare CTPH hashes";
|
||||
this.module = "Crypto";
|
||||
this.description = "Compares two Context Triggered Piecewise Hashing (CTPH) fuzzy hashes to determine the similarity between them on a scale of 0 to 100.";
|
||||
this.infoURL = "https://forensicswiki.org/wiki/Context_Triggered_Piecewise_Hashing";
|
||||
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=Context_Triggered_Piecewise_Hashing";
|
||||
this.inputType = "string";
|
||||
this.outputType = "Number";
|
||||
this.args = [
|
||||
|
||||
@@ -24,7 +24,7 @@ class CompareSSDEEPHashes extends Operation {
|
||||
this.name = "Compare SSDEEP hashes";
|
||||
this.module = "Crypto";
|
||||
this.description = "Compares two SSDEEP fuzzy hashes to determine the similarity between them on a scale of 0 to 100.";
|
||||
this.infoURL = "https://forensicswiki.org/wiki/Ssdeep";
|
||||
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=Ssdeep";
|
||||
this.inputType = "string";
|
||||
this.outputType = "Number";
|
||||
this.args = [
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Contain Image operation
|
||||
|
||||
@@ -8,7 +8,8 @@ import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Convert Image Format operation
|
||||
@@ -88,7 +89,7 @@ class ConvertImageFormat extends Operation {
|
||||
"Sub": jimp.PNG_FILTER_SUB,
|
||||
"Up": jimp.PNG_FILTER_UP,
|
||||
"Average": jimp.PNG_FILTER_AVERAGE,
|
||||
"Paeth": jimp.PNG_FILTER_PATH // Incorrect spelling in Jimp library
|
||||
"Paeth": jimp.PNG_FILTER_PATH
|
||||
};
|
||||
|
||||
const mime = formatMap[format];
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Cover Image operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Crop Image operation
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* DES Decrypt operation
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* DES Encrypt operation
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* Derive PBKDF2 key operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Image Dither operation
|
||||
|
||||
@@ -24,7 +24,7 @@ class ExtractFiles extends Operation {
|
||||
this.name = "Extract Files";
|
||||
this.module = "Default";
|
||||
this.description = "Performs file carving to attempt to extract files from the input.<br><br>This operation is currently capable of carving out the following formats:<ul><li>JPG</li><li>EXE</li><li>ZIP</li><li>PDF</li><li>PNG</li><li>BMP</li><li>FLV</li><li>RTF</li><li>DOCX, PPTX, XLSX</li><li>EPUB</li><li>GZIP</li><li>ZLIB</li><li>ELF, BIN, AXF, O, PRX, SO</li></ul>";
|
||||
this.infoURL = "https://forensicswiki.org/wiki/File_Carving";
|
||||
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=File_Carving";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "List<File>";
|
||||
this.presentType = "html";
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { fromBinary } from "../lib/Binary.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Extract LSB operation
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
import {RGBA_DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Flip Image operation
|
||||
|
||||
@@ -31,6 +31,11 @@ class FromBinary extends Operation {
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": BIN_DELIM_OPTIONS
|
||||
},
|
||||
{
|
||||
"name": "Byte Length",
|
||||
"type": "number",
|
||||
"value": 8
|
||||
}
|
||||
];
|
||||
this.checks = [
|
||||
@@ -78,7 +83,8 @@ class FromBinary extends Operation {
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
return fromBinary(input, args[0]);
|
||||
const byteLen = args[1] ? args[1] : 8;
|
||||
return fromBinary(input, args[0], byteLen);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ class GenerateHOTP extends Operation {
|
||||
|
||||
this.name = "Generate HOTP";
|
||||
this.module = "Default";
|
||||
this.description = "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated.";
|
||||
this.description = "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OAUTH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/HMAC-based_One-time_Password_algorithm";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
@@ -59,7 +59,7 @@ class GenerateHOTP extends Operation {
|
||||
name: args[0],
|
||||
keySize: args[1],
|
||||
codeLength: args[2],
|
||||
secret: (new ToBase32).run(input, []),
|
||||
secret: (new ToBase32).run(input, []).split("=")[0],
|
||||
});
|
||||
const counter = args[3];
|
||||
return `URI: ${otpObj.hotpURL}\n\nPassword: ${otpObj.hotp(counter)}`;
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import {isImage} from "../lib/FileType";
|
||||
import {toBase64} from "../lib/Base64";
|
||||
import jimp from "jimp";
|
||||
import {isWorkerEnvironment} from "../Utils";
|
||||
import {isImage} from "../lib/FileType.mjs";
|
||||
import {toBase64} from "../lib/Base64.mjs";
|
||||
import {isWorkerEnvironment} from "../Utils.mjs";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Generate Image operation
|
||||
|
||||
@@ -25,7 +25,7 @@ class GeneratePGPKeyPair extends Operation {
|
||||
|
||||
this.name = "Generate PGP Key Pair";
|
||||
this.module = "PGP";
|
||||
this.description = "Generates a new public/private PGP key pair. Supports RSA and Eliptic Curve (EC) keys.";
|
||||
this.description = "Generates a new public/private PGP key pair. Supports RSA and Eliptic Curve (EC) keys.<br><br>WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
@@ -33,7 +33,7 @@ class GeneratePGPKeyPair extends Operation {
|
||||
{
|
||||
"name": "Key type",
|
||||
"type": "option",
|
||||
"value": ["RSA-1024", "RSA-2048", "RSA-4096", "ECC-256", "ECC-384"]
|
||||
"value": ["RSA-1024", "RSA-2048", "RSA-4096", "ECC-256", "ECC-384", "ECC-521"]
|
||||
},
|
||||
{
|
||||
"name": "Password (optional)",
|
||||
@@ -59,12 +59,15 @@ class GeneratePGPKeyPair extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const [keyType, keySize] = args[0].split("-"),
|
||||
password = args[1],
|
||||
let [keyType, keySize] = args[0].split("-");
|
||||
const password = args[1],
|
||||
name = args[2],
|
||||
email = args[3];
|
||||
let userIdentifier = "";
|
||||
|
||||
keyType = keyType.toLowerCase();
|
||||
keySize = parseInt(keySize, 10);
|
||||
|
||||
if (name) userIdentifier += name;
|
||||
if (email) userIdentifier += ` <${email}>`;
|
||||
|
||||
|
||||
87
src/core/operations/GenerateRSAKeyPair.mjs
Normal file
87
src/core/operations/GenerateRSAKeyPair.mjs
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* Generate RSA Key Pair operation
|
||||
*/
|
||||
class GenerateRSAKeyPair extends Operation {
|
||||
|
||||
/**
|
||||
* GenerateRSAKeyPair constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Generate RSA Key Pair";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Generate an RSA key pair with a given number of bits.<br><br>WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "RSA Key Length",
|
||||
type: "option",
|
||||
value: [
|
||||
"1024",
|
||||
"2048",
|
||||
"4096"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Output Format",
|
||||
type: "option",
|
||||
value: [
|
||||
"PEM",
|
||||
"JSON",
|
||||
"DER"
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const [keyLength, outputFormat] = args;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
forge.pki.rsa.generateKeyPair({
|
||||
bits: Number(keyLength),
|
||||
workers: -1,
|
||||
workerScript: "assets/forge/prime.worker.min.js"
|
||||
}, (err, keypair) => {
|
||||
if (err) return reject(err);
|
||||
|
||||
let result;
|
||||
|
||||
switch (outputFormat) {
|
||||
case "PEM":
|
||||
result = forge.pki.publicKeyToPem(keypair.publicKey) + "\n" + forge.pki.privateKeyToPem(keypair.privateKey);
|
||||
break;
|
||||
case "JSON":
|
||||
result = JSON.stringify(keypair);
|
||||
break;
|
||||
case "DER":
|
||||
result = forge.asn1.toDer(forge.pki.privateKeyToAsn1(keypair.privateKey)).getBytes();
|
||||
break;
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GenerateRSAKeyPair;
|
||||
@@ -21,7 +21,7 @@ class GenerateTOTP extends Operation {
|
||||
|
||||
this.name = "Generate TOTP";
|
||||
this.module = "Default";
|
||||
this.description = "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. T0 and T1 are in seconds.";
|
||||
this.description = "The Time-based One-Time Password algorithm (TOTP) is an algorithm that computes a one-time password from a shared secret key and the current time. It has been adopted as Internet Engineering Task Force standard RFC 6238, is the cornerstone of Initiative For Open Authentication (OAUTH), and is used in a number of two-factor authentication systems. A TOTP is an HOTP where the counter is the current time.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated. T0 and T1 are in seconds.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Time-based_One-time_Password_algorithm";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
@@ -64,7 +64,7 @@ class GenerateTOTP extends Operation {
|
||||
name: args[0],
|
||||
keySize: args[1],
|
||||
codeLength: args[2],
|
||||
secret: (new ToBase32).run(input, []),
|
||||
secret: (new ToBase32).run(input, []).split("=")[0],
|
||||
epoch: args[3],
|
||||
timeSlice: args[4]
|
||||
});
|
||||
|
||||
@@ -20,11 +20,19 @@ class HAS160 extends Operation {
|
||||
|
||||
this.name = "HAS-160";
|
||||
this.module = "Crypto";
|
||||
this.description = "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists of 80 rounds.";
|
||||
this.description = "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists, by default, of 80 rounds.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/HAS-160";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.args = [
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "number",
|
||||
value: 80,
|
||||
min: 1,
|
||||
max: 80
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +41,7 @@ class HAS160 extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return runHash("has160", input);
|
||||
return runHash("has160", input, {rounds: args[0]});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ class HaversineDistance extends Operation {
|
||||
|
||||
const lat1 = parseFloat(values[1]);
|
||||
const lng1 = parseFloat(values[3]);
|
||||
const lat2 = parseFloat(values[6]);
|
||||
const lng2 = parseFloat(values[8]);
|
||||
const lat2 = parseFloat(values[5]);
|
||||
const lng2 = parseFloat(values[7]);
|
||||
|
||||
const TO_RAD = Math.PI / 180;
|
||||
const dLat = (lat2-lat1) * TO_RAD;
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Image Brightness / Contrast operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Image Filter operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Image Hue/Saturation/Lightness operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Image Opacity operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Invert Image operation
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import * as flat from "flat";
|
||||
const flatten = flat.default ? flat.default.flatten : flat.flatten;
|
||||
|
||||
/**
|
||||
* JSON to CSV operation
|
||||
@@ -38,6 +40,40 @@ class JSONToCSV extends Operation {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts JSON to a CSV equivalent.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
toCSV() {
|
||||
const self = this;
|
||||
// If the JSON is an array of arrays, this is easy
|
||||
if (this.flattened[0] instanceof Array) {
|
||||
return this.flattened
|
||||
.map(row => row
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(this.cellDelim)
|
||||
)
|
||||
.join(this.rowDelim) +
|
||||
this.rowDelim;
|
||||
}
|
||||
|
||||
// If it's an array of dictionaries...
|
||||
const header = Object.keys(this.flattened[0]);
|
||||
return header
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(this.cellDelim) +
|
||||
this.rowDelim +
|
||||
this.flattened
|
||||
.map(row => header
|
||||
.map(h => row[h])
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(this.cellDelim)
|
||||
)
|
||||
.join(this.rowDelim) +
|
||||
this.rowDelim;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSON} input
|
||||
* @param {Object[]} args
|
||||
@@ -49,40 +85,23 @@ class JSONToCSV extends Operation {
|
||||
// Record values so they don't have to be passed to other functions explicitly
|
||||
this.cellDelim = cellDelim;
|
||||
this.rowDelim = rowDelim;
|
||||
const self = this;
|
||||
|
||||
if (!(input instanceof Array)) {
|
||||
input = [input];
|
||||
this.flattened = input;
|
||||
if (!(this.flattened instanceof Array)) {
|
||||
this.flattened = [input];
|
||||
}
|
||||
|
||||
try {
|
||||
// If the JSON is an array of arrays, this is easy
|
||||
if (input[0] instanceof Array) {
|
||||
return input
|
||||
.map(row => row
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(cellDelim)
|
||||
)
|
||||
.join(rowDelim) +
|
||||
rowDelim;
|
||||
}
|
||||
|
||||
// If it's an array of dictionaries...
|
||||
const header = Object.keys(input[0]);
|
||||
return header
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(cellDelim) +
|
||||
rowDelim +
|
||||
input
|
||||
.map(row => header
|
||||
.map(h => row[h])
|
||||
.map(self.escapeCellContents.bind(self))
|
||||
.join(cellDelim)
|
||||
)
|
||||
.join(rowDelim) +
|
||||
rowDelim;
|
||||
return this.toCSV();
|
||||
} catch (err) {
|
||||
throw new OperationError("Unable to parse JSON to CSV: " + err.toString());
|
||||
try {
|
||||
this.flattened = flatten(input);
|
||||
if (!(this.flattened instanceof Array)) {
|
||||
this.flattened = [this.flattened];
|
||||
}
|
||||
return this.toCSV();
|
||||
} catch (err) {
|
||||
throw new OperationError("Unable to parse JSON to CSV: " + err.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Operation from "../Operation.mjs";
|
||||
import * as esprima from "esprima";
|
||||
import escodegen from "escodegen";
|
||||
import esmangle from "esmangle";
|
||||
import * as terser from "terser";
|
||||
|
||||
/**
|
||||
* JavaScript Minify operation
|
||||
@@ -33,23 +32,12 @@ class JavaScriptMinify extends Operation {
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
let result = "";
|
||||
const AST = esprima.parseScript(input),
|
||||
optimisedAST = esmangle.optimize(AST, null),
|
||||
mangledAST = esmangle.mangle(optimisedAST);
|
||||
|
||||
result = escodegen.generate(mangledAST, {
|
||||
format: {
|
||||
renumber: true,
|
||||
hexadecimal: true,
|
||||
escapeless: true,
|
||||
compact: true,
|
||||
semicolons: false,
|
||||
parentheses: false
|
||||
}
|
||||
});
|
||||
return result;
|
||||
async run(input, args) {
|
||||
const result = await terser.minify(input);
|
||||
if (result.error) {
|
||||
throw new OperationError(`Error minifying JavaScript. (${result.error})`);
|
||||
}
|
||||
return result.code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,11 +20,18 @@ class MD2 extends Operation {
|
||||
|
||||
this.name = "MD2";
|
||||
this.module = "Crypto";
|
||||
this.description = "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.<br><br>Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA.";
|
||||
this.description = "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.<br><br>Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA. The message digest algorithm consists, by default, of 18 rounds.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/MD2_(cryptography)";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.args = [
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "number",
|
||||
value: 18,
|
||||
min: 0
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +40,7 @@ class MD2 extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return runHash("md2", input);
|
||||
return runHash("md2", input, {rounds: args[0]});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Normalise Image operation
|
||||
|
||||
@@ -51,7 +51,7 @@ class NormaliseUnicode extends Operation {
|
||||
case "NFKD":
|
||||
return unorm.nfkd(input);
|
||||
case "NFKC":
|
||||
return unorm.nfc(input);
|
||||
return unorm.nfkc(input);
|
||||
default:
|
||||
throw new OperationError("Unknown Normalisation Form");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author mshwed [m@ttshwed.com]
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
@@ -12,7 +13,7 @@ import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
|
||||
import Tesseract from "tesseract.js";
|
||||
const { TesseractWorker } = Tesseract;
|
||||
const { createWorker } = Tesseract;
|
||||
|
||||
import process from "process";
|
||||
|
||||
@@ -60,23 +61,30 @@ class OpticalCharacterRecognition extends Operation {
|
||||
const assetDir = isWorkerEnvironment() ? `${self.docURL}/assets/` : `${process.cwd()}/src/core/vendor/`;
|
||||
|
||||
try {
|
||||
self.sendStatusMessage("Spinning up Tesseract worker...");
|
||||
const image = `data:${type};base64,${toBase64(input)}`;
|
||||
const worker = new TesseractWorker({
|
||||
const worker = createWorker({
|
||||
workerPath: `${assetDir}tesseract/worker.min.js`,
|
||||
langPath: `${assetDir}tesseract/lang-data`,
|
||||
corePath: `${assetDir}tesseract/tesseract-core.wasm.js`,
|
||||
});
|
||||
const result = await worker.recognize(image)
|
||||
.progress(progress => {
|
||||
logger: progress => {
|
||||
if (isWorkerEnvironment()) {
|
||||
self.sendStatusMessage(`Status: ${progress.status} - ${(parseFloat(progress.progress)*100).toFixed(2)}%`);
|
||||
self.sendStatusMessage(`Status: ${progress.status}${progress.status === "recognizing text" ? ` - ${(parseFloat(progress.progress)*100).toFixed(2)}%`: "" }`);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
await worker.load();
|
||||
self.sendStatusMessage("Loading English language...");
|
||||
await worker.loadLanguage("eng");
|
||||
self.sendStatusMessage("Intialising Tesseract API...");
|
||||
await worker.initialize("eng");
|
||||
self.sendStatusMessage("Finding text...");
|
||||
const result = await worker.recognize(image);
|
||||
|
||||
if (showConfidence) {
|
||||
return `Confidence: ${result.confidence}%\n\n${result.text}`;
|
||||
return `Confidence: ${result.data.confidence}%\n\n${result.data.text}`;
|
||||
} else {
|
||||
return result.text;
|
||||
return result.data.text;
|
||||
}
|
||||
} catch (err) {
|
||||
throw new OperationError(`Error performing OCR on image. (${err})`);
|
||||
|
||||
@@ -72,7 +72,7 @@ class ParseDateTime extends Operation {
|
||||
"\nLeap year: " + date.isLeapYear() +
|
||||
"\nDays in this month: " + date.daysInMonth() +
|
||||
"\n\nDay of year: " + date.dayOfYear() +
|
||||
"\nWeek number: " + date.weekYear() +
|
||||
"\nWeek number: " + date.week() +
|
||||
"\nQuarter: " + date.quarter();
|
||||
|
||||
return output;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
import BigNumber from "bignumber.js";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* RC2 Decrypt operation
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,11 @@ class ROT13 extends Operation {
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Rotate numbers",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Amount",
|
||||
type: "number",
|
||||
@@ -51,8 +56,9 @@ class ROT13 extends Operation {
|
||||
run(input, args) {
|
||||
const output = input,
|
||||
rot13Lowercase = args[0],
|
||||
rot13Upperacse = args[1];
|
||||
let amount = args[2],
|
||||
rot13Upperacse = args[1],
|
||||
rotNumbers = args[2];
|
||||
let amount = args[3],
|
||||
chr;
|
||||
|
||||
if (amount) {
|
||||
@@ -68,6 +74,9 @@ class ROT13 extends Operation {
|
||||
} else if (rot13Lowercase && chr >= 97 && chr <= 122) { // Lower case
|
||||
chr = (chr - 97 + amount) % 26;
|
||||
output[i] = chr + 97;
|
||||
} else if (rotNumbers && chr >= 48 && chr <= 57) { // Numbers
|
||||
chr = (chr - 48 + amount) % 10;
|
||||
output[i] = chr + 48;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
86
src/core/operations/RSADecrypt.mjs
Normal file
86
src/core/operations/RSADecrypt.mjs
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge";
|
||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||
|
||||
/**
|
||||
* RSA Decrypt operation
|
||||
*/
|
||||
class RSADecrypt extends Operation {
|
||||
|
||||
/**
|
||||
* RSADecrypt constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "RSA Decrypt";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Decrypt an RSA encrypted message with a PEM encoded private key.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "RSA Private Key (PEM)",
|
||||
type: "text",
|
||||
value: "-----BEGIN RSA PRIVATE KEY-----"
|
||||
},
|
||||
{
|
||||
name: "Key Password",
|
||||
type: "text",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Encryption Scheme",
|
||||
type: "argSelector",
|
||||
value: [
|
||||
{
|
||||
name: "RSA-OAEP",
|
||||
on: [3]
|
||||
},
|
||||
{
|
||||
name: "RSAES-PKCS1-V1_5",
|
||||
off: [3]
|
||||
},
|
||||
{
|
||||
name: "RAW",
|
||||
off: [3]
|
||||
}]
|
||||
},
|
||||
{
|
||||
name: "Message Digest Algorithm",
|
||||
type: "option",
|
||||
value: Object.keys(MD_ALGORITHMS)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [pemKey, password, scheme, md] = args;
|
||||
if (pemKey.replace("-----BEGIN RSA PRIVATE KEY-----", "").length === 0) {
|
||||
throw new OperationError("Please enter a private key.");
|
||||
}
|
||||
try {
|
||||
const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password);
|
||||
const dMsg = privKey.decrypt(input, scheme, {md: MD_ALGORITHMS[md].create()});
|
||||
return forge.util.decodeUtf8(dMsg);
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSADecrypt;
|
||||
89
src/core/operations/RSAEncrypt.mjs
Normal file
89
src/core/operations/RSAEncrypt.mjs
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge";
|
||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||
|
||||
/**
|
||||
* RSA Encrypt operation
|
||||
*/
|
||||
class RSAEncrypt extends Operation {
|
||||
|
||||
/**
|
||||
* RSAEncrypt constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "RSA Encrypt";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Encrypt a message with a PEM encoded RSA public key.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "RSA Public Key (PEM)",
|
||||
type: "text",
|
||||
value: "-----BEGIN RSA PUBLIC KEY-----"
|
||||
},
|
||||
{
|
||||
name: "Encryption Scheme",
|
||||
type: "argSelector",
|
||||
value: [
|
||||
{
|
||||
name: "RSA-OAEP",
|
||||
on: [2]
|
||||
},
|
||||
{
|
||||
name: "RSAES-PKCS1-V1_5",
|
||||
off: [2]
|
||||
},
|
||||
{
|
||||
name: "RAW",
|
||||
off: [2]
|
||||
}]
|
||||
},
|
||||
{
|
||||
name: "Message Digest Algorithm",
|
||||
type: "option",
|
||||
value: Object.keys(MD_ALGORITHMS)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [pemKey, scheme, md] = args;
|
||||
|
||||
if (pemKey.replace("-----BEGIN RSA PUBLIC KEY-----", "").length === 0) {
|
||||
throw new OperationError("Please enter a public key.");
|
||||
}
|
||||
try {
|
||||
// Load public key
|
||||
const pubKey = forge.pki.publicKeyFromPem(pemKey);
|
||||
// https://github.com/digitalbazaar/forge/issues/465#issuecomment-271097600
|
||||
const plaintextBytes = forge.util.encodeUtf8(input);
|
||||
// Encrypt message
|
||||
const eMsg = pubKey.encrypt(plaintextBytes, scheme, {md: MD_ALGORITHMS[md].create()});
|
||||
return eMsg;
|
||||
} catch (err) {
|
||||
if (err.message === "RSAES-OAEP input message length is too long.") {
|
||||
throw new OperationError(`RSAES-OAEP input message length (${err.length}) is longer than the maximum allowed length (${err.maxLength}).`);
|
||||
}
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSAEncrypt;
|
||||
74
src/core/operations/RSASign.mjs
Normal file
74
src/core/operations/RSASign.mjs
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge";
|
||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||
|
||||
/**
|
||||
* RSA Sign operation
|
||||
*/
|
||||
class RSASign extends Operation {
|
||||
|
||||
/**
|
||||
* RSASign constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "RSA Sign";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Sign a plaintext message with a PEM encoded RSA key.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "RSA Private Key (PEM)",
|
||||
type: "text",
|
||||
value: "-----BEGIN RSA PRIVATE KEY-----"
|
||||
},
|
||||
{
|
||||
name: "Key Password",
|
||||
type: "text",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Message Digest Algorithm",
|
||||
type: "option",
|
||||
value: Object.keys(MD_ALGORITHMS)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [key, password, mdAlgo] = args;
|
||||
if (key.replace("-----BEGIN RSA PRIVATE KEY-----", "").length === 0) {
|
||||
throw new OperationError("Please enter a private key.");
|
||||
}
|
||||
try {
|
||||
const privateKey = forge.pki.decryptRsaPrivateKey(key, password);
|
||||
// Generate message hash
|
||||
const md = MD_ALGORITHMS[mdAlgo].create();
|
||||
md.update(input, "utf8");
|
||||
// Sign message hash
|
||||
const sig = privateKey.sign(md);
|
||||
return sig;
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSASign;
|
||||
77
src/core/operations/RSAVerify.mjs
Normal file
77
src/core/operations/RSAVerify.mjs
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge";
|
||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||
|
||||
/**
|
||||
* RSA Verify operation
|
||||
*/
|
||||
class RSAVerify extends Operation {
|
||||
|
||||
/**
|
||||
* RSAVerify constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "RSA Verify";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Verify a message against a signature and a public PEM encoded RSA key.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "RSA Public Key (PEM)",
|
||||
type: "text",
|
||||
value: "-----BEGIN RSA PUBLIC KEY-----"
|
||||
},
|
||||
{
|
||||
name: "Message",
|
||||
type: "text",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Message Digest Algorithm",
|
||||
type: "option",
|
||||
value: Object.keys(MD_ALGORITHMS)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [pemKey, message, mdAlgo] = args;
|
||||
if (pemKey.replace("-----BEGIN RSA PUBLIC KEY-----", "").length === 0) {
|
||||
throw new OperationError("Please enter a public key.");
|
||||
}
|
||||
try {
|
||||
// Load public key
|
||||
const pubKey = forge.pki.publicKeyFromPem(pemKey);
|
||||
// Generate message digest
|
||||
const md = MD_ALGORITHMS[mdAlgo].create();
|
||||
md.update(message, "utf8");
|
||||
// Compare signed message digest and generated message digest
|
||||
const result = pubKey.verify(md.digest().bytes(), input);
|
||||
return result ? "Verified OK" : "Verification Failure";
|
||||
} catch (err) {
|
||||
if (err.message === "Encrypted message length is invalid.") {
|
||||
throw new OperationError(`Signature length (${err.length}) does not match expected length based on key (${err.expected}).`);
|
||||
}
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSAVerify;
|
||||
@@ -46,7 +46,7 @@ class RailFenceCipherDecode extends Operation {
|
||||
run(input, args) {
|
||||
const [key, offset] = args;
|
||||
|
||||
let cipher = input;
|
||||
const cipher = input;
|
||||
|
||||
if (key < 2) {
|
||||
throw new OperationError("Key has to be bigger than 2");
|
||||
@@ -59,13 +59,6 @@ class RailFenceCipherDecode extends Operation {
|
||||
}
|
||||
|
||||
const cycle = (key - 1) * 2;
|
||||
|
||||
const rest = cipher.length % key;
|
||||
|
||||
if (rest !== 0) {
|
||||
cipher = cipher + (" ".repeat(key - rest));
|
||||
}
|
||||
|
||||
const plaintext = new Array(cipher.length);
|
||||
|
||||
let j = 0;
|
||||
|
||||
@@ -10,7 +10,8 @@ import Utils from "../Utils.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { runHash } from "../lib/Hash.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Randomize Colour Palette operation
|
||||
|
||||
@@ -19,7 +19,7 @@ class RemoveDiacritics extends Operation {
|
||||
|
||||
this.name = "Remove Diacritics";
|
||||
this.module = "Default";
|
||||
this.description = "Replaces accented characters with their latin character equivalent.";
|
||||
this.description = "Replaces accented characters with their latin character equivalent. Accented characters are made up of Unicode combining characters, so unicode text formatting such as strikethroughs and underlines will also be removed.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Diacritic";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Resize Image operation
|
||||
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Rotate Image operation
|
||||
|
||||
@@ -20,11 +20,18 @@ class SHA0 extends Operation {
|
||||
|
||||
this.name = "SHA0";
|
||||
this.module = "Crypto";
|
||||
this.description = "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.";
|
||||
this.description = "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1. The message digest algorithm consists, by default, of 80 rounds.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/SHA-1#SHA-0";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.args = [
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "number",
|
||||
value: 80,
|
||||
min: 16
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +40,7 @@ class SHA0 extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return runHash("sha0", input);
|
||||
return runHash("sha0", input, {rounds: args[0]});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,11 +20,18 @@ class SHA1 extends Operation {
|
||||
|
||||
this.name = "SHA1";
|
||||
this.module = "Crypto";
|
||||
this.description = "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.<br><br>However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.";
|
||||
this.description = "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.<br><br>However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved. The message digest algorithm consists, by default, of 80 rounds.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/SHA-1";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.args = [
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "number",
|
||||
value: 80,
|
||||
min: 16
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +40,7 @@ class SHA1 extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
return runHash("sha1", input);
|
||||
return runHash("sha1", input, {rounds: args[0]});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,15 +20,58 @@ class SHA2 extends Operation {
|
||||
|
||||
this.name = "SHA2";
|
||||
this.module = "Crypto";
|
||||
this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul>";
|
||||
this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/SHA-2";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Size",
|
||||
"type": "option",
|
||||
"value": ["512", "256", "384", "224", "512/256", "512/224"]
|
||||
name: "Size",
|
||||
type: "argSelector",
|
||||
value: [
|
||||
{
|
||||
name: "512",
|
||||
on: [2],
|
||||
off: [1]
|
||||
},
|
||||
{
|
||||
name: "384",
|
||||
on: [2],
|
||||
off: [1]
|
||||
},
|
||||
{
|
||||
name: "256",
|
||||
on: [1],
|
||||
off: [2]
|
||||
},
|
||||
{
|
||||
name: "224",
|
||||
on: [1],
|
||||
off: [2]
|
||||
},
|
||||
{
|
||||
name: "512/256",
|
||||
on: [2],
|
||||
off: [1]
|
||||
},
|
||||
{
|
||||
name: "512/224",
|
||||
on: [2],
|
||||
off: [1]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rounds", // For SHA256 variants
|
||||
type: "number",
|
||||
value: 64,
|
||||
min: 16
|
||||
},
|
||||
{
|
||||
name: "Rounds", // For SHA512 variants
|
||||
type: "number",
|
||||
value: 160,
|
||||
min: 32
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -40,7 +83,8 @@ class SHA2 extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
const size = args[0];
|
||||
return runHash("sha" + size, input);
|
||||
const rounds = (size === "256" || size === "224") ? args[1] : args[2];
|
||||
return runHash("sha" + size, input, {rounds: rounds});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
57
src/core/operations/SM3.mjs
Normal file
57
src/core/operations/SM3.mjs
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import Sm3 from "crypto-api/src/hasher/sm3.mjs";
|
||||
import {toHex} from "crypto-api/src/encoder/hex.mjs";
|
||||
|
||||
/**
|
||||
* SM3 operation
|
||||
*/
|
||||
class SM3 extends Operation {
|
||||
|
||||
/**
|
||||
* SM3 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "SM3";
|
||||
this.module = "Crypto";
|
||||
this.description = "SM3 is a cryptographic hash function used in the Chinese National Standard. SM3 is mainly used in digital signatures, message authentication codes, and pseudorandom number generators. The message digest algorithm consists, by default, of 64 rounds and length of 256.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/SM3_(hash_function)";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Length",
|
||||
type: "number",
|
||||
value: 256
|
||||
},
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "number",
|
||||
value: 64,
|
||||
min: 16
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const msg = Utils.arrayBufferToStr(input, false);
|
||||
const hasher = new Sm3({length: args[0], rounds: args[1]});
|
||||
hasher.update(msg);
|
||||
return toHex(hasher.finalize());
|
||||
}
|
||||
}
|
||||
|
||||
export default SM3;
|
||||
@@ -21,7 +21,7 @@ class SSDEEP extends Operation {
|
||||
this.name = "SSDEEP";
|
||||
this.module = "Crypto";
|
||||
this.description = "SSDEEP is a program for computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.<br><br>SSDEEP hashes are now widely used for simple identification purposes (e.g. the 'Basic Properties' section in VirusTotal). Although 'better' fuzzy hashes are available, SSDEEP is still one of the primary choices because of its speed and being a de facto standard.<br><br>This operation is fundamentally the same as the CTPH operation, however their outputs differ in format.";
|
||||
this.infoURL = "https://forensicswiki.org/wiki/Ssdeep";
|
||||
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=Ssdeep";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
|
||||
@@ -41,7 +41,7 @@ class ScanForEmbeddedFiles extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
let output = "Scanning data for 'magic bytes' which may indicate embedded files. The following results may be false positives and should not be treat as reliable. Any sufficiently long file is likely to contain these magic bytes coincidentally.\n",
|
||||
let output = "Scanning data for 'magic bytes' which may indicate embedded files. The following results may be false positives and should not be treated as reliable. Any sufficiently long file is likely to contain these magic bytes coincidentally.\n",
|
||||
numFound = 0;
|
||||
const categories = [],
|
||||
data = new Uint8Array(input);
|
||||
|
||||
@@ -10,7 +10,8 @@ import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import { gaussianBlur } from "../lib/ImageManipulation.mjs";
|
||||
import { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Sharpen Image operation
|
||||
|
||||
@@ -26,14 +26,17 @@ class Snefru extends Operation {
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Rounds",
|
||||
"type": "option",
|
||||
"value": ["8", "4", "2"]
|
||||
name: "Size",
|
||||
type: "number",
|
||||
value: 128,
|
||||
min: 32,
|
||||
max: 480,
|
||||
step: 32
|
||||
},
|
||||
{
|
||||
"name": "Size",
|
||||
"type": "option",
|
||||
"value": ["256", "128"]
|
||||
name: "Rounds",
|
||||
type: "option",
|
||||
value: ["8", "4", "2"]
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -45,8 +48,8 @@ class Snefru extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
return runHash("snefru", input, {
|
||||
rounds: args[0],
|
||||
length: args[1]
|
||||
length: args[0],
|
||||
rounds: args[1]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import {isImage} from "../lib/FileType.mjs";
|
||||
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* Split Colour Channels operation
|
||||
|
||||
@@ -31,6 +31,11 @@ class ToBinary extends Operation {
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": BIN_DELIM_OPTIONS
|
||||
},
|
||||
{
|
||||
"name": "Byte Length",
|
||||
"type": "number",
|
||||
"value": 8
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -42,7 +47,8 @@ class ToBinary extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
input = new Uint8Array(input);
|
||||
return toBinary(input, args[0]);
|
||||
const padding = args[1] ? args[1] : 8;
|
||||
return toBinary(input, args[0], padding);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* Triple DES Decrypt operation
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge/dist/forge.min.js";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* Triple DES Encrypt operation
|
||||
|
||||
@@ -34,7 +34,7 @@ class UNIXTimestampToWindowsFiletime extends Operation {
|
||||
{
|
||||
"name": "Output format",
|
||||
"type": "option",
|
||||
"value": ["Decimal", "Hex"]
|
||||
"value": ["Decimal", "Hex (big endian)", "Hex (little endian)"]
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -65,11 +65,24 @@ class UNIXTimestampToWindowsFiletime extends Operation {
|
||||
|
||||
input = input.plus(new BigNumber("116444736000000000"));
|
||||
|
||||
if (format === "Hex") {
|
||||
return input.toString(16);
|
||||
let result;
|
||||
if (format.startsWith("Hex")) {
|
||||
result = input.toString(16);
|
||||
} else {
|
||||
return input.toFixed();
|
||||
result = input.toFixed();
|
||||
}
|
||||
|
||||
if (format === "Hex (little endian)") {
|
||||
// Swap endianness
|
||||
let flipped = "";
|
||||
for (let i = result.length - 2; i >= 0; i -= 2) {
|
||||
flipped += result.charAt(i);
|
||||
flipped += result.charAt(i + 1);
|
||||
}
|
||||
result = flipped;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
67
src/core/operations/UnicodeTextFormat.mjs
Normal file
67
src/core/operations/UnicodeTextFormat.mjs
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* Unicode Text Format operation
|
||||
*/
|
||||
class UnicodeTextFormat extends Operation {
|
||||
|
||||
/**
|
||||
* UnicodeTextFormat constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Unicode Text Format";
|
||||
this.module = "Default";
|
||||
this.description = "Adds Unicode combining characters to change formatting of plaintext.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Combining_character";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
name: "Underline",
|
||||
type: "boolean",
|
||||
value: "false"
|
||||
},
|
||||
{
|
||||
name: "Strikethrough",
|
||||
type: "boolean",
|
||||
value: "false"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [underline, strikethrough] = args;
|
||||
let output = input.map(char => [char]);
|
||||
if (strikethrough) {
|
||||
output = output.map(charFormat => {
|
||||
charFormat.push(...Utils.strToUtf8ByteArray("\u0336"));
|
||||
return charFormat;
|
||||
});
|
||||
}
|
||||
if (underline) {
|
||||
output = output.map(charFormat => {
|
||||
charFormat.push(...Utils.strToUtf8ByteArray("\u0332"));
|
||||
return charFormat;
|
||||
});
|
||||
}
|
||||
// return output.flat(); - Not supported in Node 10, polyfilled
|
||||
return [].concat(...output);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default UnicodeTextFormat;
|
||||
@@ -9,7 +9,8 @@ import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { isImage } from "../lib/FileType.mjs";
|
||||
import { toBase64 } from "../lib/Base64.mjs";
|
||||
import jimp from "jimp";
|
||||
import jimplib from "jimp/es/index.js";
|
||||
const jimp = jimplib.default ? jimplib.default : jimplib;
|
||||
|
||||
/**
|
||||
* View Bit Plane operation
|
||||
|
||||
@@ -26,9 +26,16 @@ class Whirlpool extends Operation {
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Variant",
|
||||
"type": "option",
|
||||
"value": ["Whirlpool", "Whirlpool-T", "Whirlpool-0"]
|
||||
name: "Variant",
|
||||
type: "option",
|
||||
value: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"]
|
||||
},
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "number",
|
||||
value: 10,
|
||||
min: 1,
|
||||
max: 10
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -40,7 +47,7 @@ class Whirlpool extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
const variant = args[0].toLowerCase();
|
||||
return runHash(variant, input);
|
||||
return runHash(variant, input, {rounds: args[1]});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class WindowsFiletimeToUNIXTimestamp extends Operation {
|
||||
{
|
||||
"name": "Input format",
|
||||
"type": "option",
|
||||
"value": ["Decimal", "Hex"]
|
||||
"value": ["Decimal", "Hex (big endian)", "Hex (little endian)"]
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -49,7 +49,17 @@ class WindowsFiletimeToUNIXTimestamp extends Operation {
|
||||
|
||||
if (!input) return "";
|
||||
|
||||
if (format === "Hex") {
|
||||
if (format === "Hex (little endian)") {
|
||||
// Swap endianness
|
||||
let result = "";
|
||||
for (let i = input.length - 2; i >= 0; i -= 2) {
|
||||
result += input.charAt(i);
|
||||
result += input.charAt(i + 1);
|
||||
}
|
||||
input = result;
|
||||
}
|
||||
|
||||
if (format.startsWith("Hex")) {
|
||||
input = new BigNumber(input, 16);
|
||||
} else {
|
||||
input = new BigNumber(input);
|
||||
|
||||
@@ -50,7 +50,19 @@ class XPathExpression extends Operation {
|
||||
|
||||
let doc;
|
||||
try {
|
||||
doc = new xmldom.DOMParser().parseFromString(input, "application/xml");
|
||||
doc = new xmldom.DOMParser({
|
||||
errorHandler: {
|
||||
warning(w) {
|
||||
throw w;
|
||||
},
|
||||
error(e) {
|
||||
throw e;
|
||||
},
|
||||
fatalError(e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}).parseFromString(input, "application/xml");
|
||||
} catch (err) {
|
||||
throw new OperationError("Invalid input XML.");
|
||||
}
|
||||
|
||||
24
src/core/vendor/tesseract/tesseract-core.wasm.js
vendored
24
src/core/vendor/tesseract/tesseract-core.wasm.js
vendored
File diff suppressed because one or more lines are too long
17
src/core/vendor/tesseract/worker.min.js
vendored
17
src/core/vendor/tesseract/worker.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -24,20 +24,30 @@ class NodeRecipe {
|
||||
|
||||
|
||||
/**
|
||||
* Validate an ingredient $ coerce to operation if necessary.
|
||||
* Validate an ingredient & coerce to operation if necessary.
|
||||
* @param {String | Function | Object} ing
|
||||
* @returns {Function || Object} The operation, or an object with the
|
||||
* operation and its arguments
|
||||
* @throws {TypeError} If it cannot find the operation in chef's list of operations.
|
||||
*/
|
||||
_validateIngredient(ing) {
|
||||
// CASE operation name given. Find operation and validate
|
||||
if (typeof ing === "string") {
|
||||
const op = operations.find((op) => {
|
||||
return sanitise(op.opName) === sanitise(ing);
|
||||
});
|
||||
if (op) {
|
||||
return op;
|
||||
// Need to validate against case 2
|
||||
return this._validateIngredient(op);
|
||||
} else {
|
||||
throw new TypeError(`Couldn't find an operation with name '${ing}'.`);
|
||||
}
|
||||
// CASE operation given. Check its a chef operation and check its not flowcontrol
|
||||
} else if (typeof ing === "function") {
|
||||
if (ing.flowControl) {
|
||||
throw new TypeError(`flowControl operations like ${ing.opName} are not currently allowed in recipes for chef.bake in the Node API`);
|
||||
}
|
||||
|
||||
if (operations.includes(ing)) {
|
||||
return ing;
|
||||
} else {
|
||||
@@ -57,7 +67,7 @@ class NodeRecipe {
|
||||
|
||||
|
||||
/**
|
||||
* Parse config for recipe.
|
||||
* Parse an opList from a recipeConfig and assign it to the recipe's opList.
|
||||
* @param {String | Function | String[] | Function[] | [String | Function]} recipeConfig
|
||||
*/
|
||||
_parseConfig(recipeConfig) {
|
||||
|
||||
@@ -177,6 +177,7 @@ export function _wrap(OpClass) {
|
||||
// Check to see if class's run function is async.
|
||||
const opInstance = new OpClass();
|
||||
const isAsync = opInstance.run.constructor.name === "AsyncFunction";
|
||||
const isFlowControl = opInstance.flowControl;
|
||||
|
||||
let wrapped;
|
||||
|
||||
@@ -191,7 +192,28 @@ export function _wrap(OpClass) {
|
||||
*/
|
||||
wrapped = async (input, args=null) => {
|
||||
const {transformedInput, transformedArgs} = prepareOp(opInstance, input, args);
|
||||
|
||||
// SPECIAL CASE for Magic. Other flowControl operations will
|
||||
// not work because the opList is not passed in.
|
||||
if (isFlowControl) {
|
||||
opInstance.ingValues = transformedArgs;
|
||||
|
||||
const state = {
|
||||
progress: 0,
|
||||
dish: ensureIsDish(transformedInput),
|
||||
opList: [opInstance],
|
||||
};
|
||||
|
||||
const updatedState = await opInstance.run(state);
|
||||
|
||||
return new NodeDish({
|
||||
value: updatedState.dish.value,
|
||||
type: opInstance.outputType,
|
||||
});
|
||||
}
|
||||
|
||||
const result = await opInstance.run(transformedInput, transformedArgs);
|
||||
|
||||
return new NodeDish({
|
||||
value: result,
|
||||
type: opInstance.outputType,
|
||||
@@ -218,6 +240,8 @@ export function _wrap(OpClass) {
|
||||
// used in chef.help
|
||||
wrapped.opName = OpClass.name;
|
||||
wrapped.args = createArgInfo(opInstance);
|
||||
// Used in NodeRecipe to check for flowControl ops
|
||||
wrapped.flowControl = isFlowControl;
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
@@ -292,25 +316,18 @@ export function help(input) {
|
||||
|
||||
|
||||
/**
|
||||
* bake [Wrapped] - Perform an array of operations on some input.
|
||||
* @returns {Function}
|
||||
* bake
|
||||
*
|
||||
* @param {*} input - some input for a recipe.
|
||||
* @param {String | Function | String[] | Function[] | [String | Function]} recipeConfig -
|
||||
* An operation, operation name, or an array of either.
|
||||
* @returns {NodeDish} of the result
|
||||
* @throws {TypeError} if invalid recipe given.
|
||||
*/
|
||||
export function bake() {
|
||||
|
||||
/**
|
||||
* bake
|
||||
*
|
||||
* @param {*} input - some input for a recipe.
|
||||
* @param {String | Function | String[] | Function[] | [String | Function]} recipeConfig -
|
||||
* An operation, operation name, or an array of either.
|
||||
* @returns {SyncDish} of the result
|
||||
* @throws {TypeError} if invalid recipe given.
|
||||
*/
|
||||
return function(input, recipeConfig) {
|
||||
const recipe = new NodeRecipe(recipeConfig);
|
||||
const dish = ensureIsDish(input);
|
||||
return recipe.execute(dish);
|
||||
};
|
||||
export function bake(input, recipeConfig) {
|
||||
const recipe = new NodeRecipe(recipeConfig);
|
||||
const dish = ensureIsDish(input);
|
||||
return recipe.execute(dish);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -100,8 +100,7 @@ Object.keys(operations).forEach((op) => {
|
||||
|
||||
code += `];
|
||||
|
||||
const prebaked = bake(operations);
|
||||
chef.bake = prebaked;
|
||||
chef.bake = bake;
|
||||
export default chef;
|
||||
|
||||
// Operations as top level exports.
|
||||
@@ -114,7 +113,7 @@ Object.keys(operations).forEach((op) => {
|
||||
});
|
||||
|
||||
code += " NodeDish as Dish,\n";
|
||||
code += " prebaked as bake,\n";
|
||||
code += " bake,\n";
|
||||
code += " help,\n";
|
||||
code += " OperationError,\n";
|
||||
code += " ExcludedOperationError,\n";
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Utils, { debounce } from "../core/Utils";
|
||||
import {fromBase64} from "../core/lib/Base64";
|
||||
import Manager from "./Manager";
|
||||
import HTMLCategory from "./HTMLCategory";
|
||||
import HTMLOperation from "./HTMLOperation";
|
||||
import Utils, { debounce } from "../core/Utils.mjs";
|
||||
import {fromBase64} from "../core/lib/Base64.mjs";
|
||||
import Manager from "./Manager.mjs";
|
||||
import HTMLCategory from "./HTMLCategory.mjs";
|
||||
import HTMLOperation from "./HTMLOperation.mjs";
|
||||
import Split from "split.js";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" width="550px" height="350px" viewBox="0 0 550 350" xml:space="preserve" onload="setup(evt)">
|
||||
<script type="text/ecmascript">
|
||||
// <![CDATA[
|
||||
<![CDATA[
|
||||
function setup(evt) {
|
||||
const allRotors = evt.target.ownerDocument.querySelectorAll('.rotor');
|
||||
const rotors = [];
|
||||
const initTime = Date.now();
|
||||
const tick = 360/26;
|
||||
const speed = 1000; // Time for one full rotation of the fast rotor
|
||||
const speed = 1000; /* Time for one full rotation of the fast rotor */
|
||||
|
||||
for (const rotor of allRotors) {
|
||||
const row = parseInt(rotor.classList.value.match(/row(\d)/)[1], 10);
|
||||
@@ -46,13 +46,13 @@
|
||||
rotor.last = rotor.last + rotor.wait * numTicks;
|
||||
rotor.el.setAttribute("transform", "rotate(" + rotor.pos + ", " + rotor.x + ", " + rotor.y + ")");
|
||||
} else {
|
||||
// Don't bother looking at the rest
|
||||
/* Don't bother looking at the rest */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, speed/26/1.5 - 5);
|
||||
}
|
||||
// ]]>
|
||||
]]>
|
||||
</script>
|
||||
<style>
|
||||
.row0 {--primary-color: #e5d41b;}
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
@@ -4,7 +4,7 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import ChefWorker from "worker-loader?inline&fallback=false!../../core/ChefWorker.js";
|
||||
import ChefWorker from "worker-loader?inline=no-fallback!../../core/ChefWorker.js";
|
||||
|
||||
/**
|
||||
* Waiter to handle conversations with a ChefWorker in the background.
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import LoaderWorker from "worker-loader?inline&fallback=false!../workers/LoaderWorker.js";
|
||||
import InputWorker from "worker-loader?inline&fallback=false!../workers/InputWorker.mjs";
|
||||
import LoaderWorker from "worker-loader?inline=no-fallback!../workers/LoaderWorker.js";
|
||||
import InputWorker from "worker-loader?inline=no-fallback!../workers/InputWorker.mjs";
|
||||
import Utils, { debounce } from "../../core/Utils.mjs";
|
||||
import { toBase64 } from "../../core/lib/Base64.mjs";
|
||||
import { isImage } from "../../core/lib/FileType.mjs";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import Utils, { debounce } from "../../core/Utils.mjs";
|
||||
import Dish from "../../core/Dish.mjs";
|
||||
import FileSaver from "file-saver";
|
||||
import ZipWorker from "worker-loader?inline&fallback=false!../workers/ZipWorker.mjs";
|
||||
import ZipWorker from "worker-loader?inline=no-fallback!../workers/ZipWorker.mjs";
|
||||
|
||||
/**
|
||||
* Waiter to handle events related to the output
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user