mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-22 15:56:16 -04:00
Merge branch 'gchq:master' into parse-ethernet-frame
This commit is contained in:
commit
bd642569e7
44 changed files with 1640 additions and 114 deletions
43
CHANGELOG.md
43
CHANGELOG.md
|
@ -13,6 +13,24 @@ All major and minor version changes will be documented in this file. Details of
|
|||
|
||||
## Details
|
||||
|
||||
### [10.15.0] - 2024-04-02
|
||||
- Fix Ciphersaber2 key concatenation [@zb3] | [#1765]
|
||||
- Fix DeriveEVPKey's array parsing [@zb3] | [#1767]
|
||||
- Fix JWT operations [@a3957273] | [#1769]
|
||||
- Added 'Parse Certificate Signing Request' operation [@jkataja] | [#1504]
|
||||
- Added 'Extract Hash Values' operation [@MShwed] | [#512]
|
||||
- Added 'DateTime Delta' operation [@tomgond] | [#1732]
|
||||
|
||||
### [10.14.0] - 2024-03-31
|
||||
- Added 'To Float' and 'From Float' operations [@tcode2k16] | [#1762]
|
||||
- Fix ChaCha raw export option [@joostrijneveld] | [#1606]
|
||||
- Update x86 disassembler vendor library [@evanreichard] | [#1197]
|
||||
- Allow variable Blowfish key sizes [@cbeuw] | [#933]
|
||||
- Added 'XXTEA' operation [@devcydo] | [#1361]
|
||||
|
||||
### [10.13.0] - 2024-03-30
|
||||
- Added 'FangURL' operation [@breakersall] [@arnydo] | [#1591] [#654]
|
||||
|
||||
### [10.12.0] - 2024-03-29
|
||||
- Added 'Salsa20' and 'XSalsa20' operation [@joostrijneveld] | [#1750]
|
||||
|
||||
|
@ -400,6 +418,9 @@ All major and minor version changes will be documented in this file. Details of
|
|||
## [4.0.0] - 2016-11-28
|
||||
- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
|
||||
|
||||
[10.15.0]: https://github.com/gchq/CyberChef/releases/tag/v10.15.0
|
||||
[10.14.0]: https://github.com/gchq/CyberChef/releases/tag/v10.14.0
|
||||
[10.13.0]: https://github.com/gchq/CyberChef/releases/tag/v10.13.0
|
||||
[10.12.0]: https://github.com/gchq/CyberChef/releases/tag/v10.12.0
|
||||
[10.11.0]: https://github.com/gchq/CyberChef/releases/tag/v10.11.0
|
||||
[10.10.0]: https://github.com/gchq/CyberChef/releases/tag/v10.10.0
|
||||
|
@ -571,6 +592,12 @@ All major and minor version changes will be documented in this file. Details of
|
|||
[@AshCorr]: https://github.com/AshCorr
|
||||
[@simonw]: https://github.com/simonw
|
||||
[@chriswhite199]: https://github.com/chriswhite199
|
||||
[@breakersall]: https://github.com/breakersall
|
||||
[@evanreichard]: https://github.com/evanreichard
|
||||
[@devcydo]: https://github.com/devcydo
|
||||
[@zb3]: https://github.com/zb3
|
||||
[@jkataja]: https://github.com/jkataja
|
||||
[@tomgond]: https://github.com/tomgond
|
||||
|
||||
|
||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||
|
@ -698,8 +725,22 @@ All major and minor version changes will be documented in this file. Details of
|
|||
[#1667]: https://github.com/gchq/CyberChef/issues/1667
|
||||
[#1555]: https://github.com/gchq/CyberChef/issues/1555
|
||||
[#1694]: https://github.com/gchq/CyberChef/issues/1694
|
||||
[#1699]: https://github.com/gchq/CyberChef/issues/1694
|
||||
[#1699]: https://github.com/gchq/CyberChef/issues/1699
|
||||
[#1757]: https://github.com/gchq/CyberChef/issues/1757
|
||||
[#1752]: https://github.com/gchq/CyberChef/issues/1752
|
||||
[#1753]: https://github.com/gchq/CyberChef/issues/1753
|
||||
[#1750]: https://github.com/gchq/CyberChef/issues/1750
|
||||
[#1591]: https://github.com/gchq/CyberChef/issues/1591
|
||||
[#654]: https://github.com/gchq/CyberChef/issues/654
|
||||
[#1762]: https://github.com/gchq/CyberChef/issues/1762
|
||||
[#1606]: https://github.com/gchq/CyberChef/issues/1606
|
||||
[#1197]: https://github.com/gchq/CyberChef/issues/1197
|
||||
[#933]: https://github.com/gchq/CyberChef/issues/933
|
||||
[#1361]: https://github.com/gchq/CyberChef/issues/1361
|
||||
[#1765]: https://github.com/gchq/CyberChef/issues/1765
|
||||
[#1767]: https://github.com/gchq/CyberChef/issues/1767
|
||||
[#1769]: https://github.com/gchq/CyberChef/issues/1769
|
||||
[#1759]: https://github.com/gchq/CyberChef/issues/1759
|
||||
[#1504]: https://github.com/gchq/CyberChef/issues/1504
|
||||
[#512]: https://github.com/gchq/CyberChef/issues/512
|
||||
[#1732]: https://github.com/gchq/CyberChef/issues/1732
|
||||
|
|
|
@ -86,10 +86,12 @@ module.exports = function (grunt) {
|
|||
|
||||
|
||||
// Project configuration
|
||||
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||
const compileYear = grunt.template.today("UTC:yyyy"),
|
||||
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||
pkg = grunt.file.readJSON("package.json"),
|
||||
webpackConfig = require("./webpack.config.js"),
|
||||
BUILD_CONSTANTS = {
|
||||
COMPILE_YEAR: JSON.stringify(compileYear),
|
||||
COMPILE_TIME: JSON.stringify(compileTime),
|
||||
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
|
||||
PKG_VERSION: JSON.stringify(pkg.version),
|
||||
|
@ -125,6 +127,7 @@ module.exports = function (grunt) {
|
|||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
chunks: ["main"],
|
||||
compileYear: compileYear,
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
minify: {
|
||||
|
@ -227,6 +230,7 @@ module.exports = function (grunt) {
|
|||
filename: "index.html",
|
||||
template: "./src/web/html/index.html",
|
||||
chunks: ["main"],
|
||||
compileYear: compileYear,
|
||||
compileTime: compileTime,
|
||||
version: pkg.version,
|
||||
})
|
||||
|
|
49
package-lock.json
generated
49
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "cyberchef",
|
||||
"version": "10.10.0",
|
||||
"version": "10.15.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cyberchef",
|
||||
"version": "10.10.0",
|
||||
"version": "10.15.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
@ -46,6 +46,7 @@
|
|||
"flat": "^6.0.1",
|
||||
"geodesy": "1.1.3",
|
||||
"highlight.js": "^11.9.0",
|
||||
"ieee754": "^1.1.13",
|
||||
"jimp": "^0.16.13",
|
||||
"jquery": "3.7.1",
|
||||
"js-crc": "^0.2.0",
|
||||
|
@ -53,7 +54,7 @@
|
|||
"jsesc": "^3.0.2",
|
||||
"json5": "^2.2.3",
|
||||
"jsonpath-plus": "^8.0.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"jsqr": "^1.4.0",
|
||||
"jsrsasign": "^11.1.0",
|
||||
"kbpgp": "2.1.15",
|
||||
|
@ -9711,9 +9712,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
|
||||
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
|
||||
"dependencies": {
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
|
@ -9724,43 +9725,21 @@
|
|||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.once": "^4.0.0",
|
||||
"ms": "^2.1.1",
|
||||
"semver": "^7.5.4"
|
||||
"semver": "^5.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=4",
|
||||
"npm": ">=1.4.28"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/semver": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/jsqr": {
|
||||
"version": "1.4.0",
|
||||
"license": "Apache-2.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "cyberchef",
|
||||
"version": "10.12.1",
|
||||
"version": "10.15.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",
|
||||
|
@ -122,6 +122,7 @@
|
|||
"escodegen": "^2.1.0",
|
||||
"esprima": "^4.0.1",
|
||||
"exif-parser": "^0.1.12",
|
||||
"ieee754": "^1.1.13",
|
||||
"fernet": "^0.3.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"flat": "^6.0.1",
|
||||
|
@ -134,7 +135,7 @@
|
|||
"jsesc": "^3.0.2",
|
||||
"json5": "^2.2.3",
|
||||
"jsonpath-plus": "^8.0.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"jsqr": "^1.4.0",
|
||||
"jsrsasign": "^11.1.0",
|
||||
"kbpgp": "2.1.15",
|
||||
|
|
|
@ -893,7 +893,7 @@ class Utils {
|
|||
|
||||
|
||||
/**
|
||||
* Converts a string to it's title case equivalent.
|
||||
* Converts a string to its title case equivalent.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns string
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
"From Charcode",
|
||||
"To Decimal",
|
||||
"From Decimal",
|
||||
"To Float",
|
||||
"From Float",
|
||||
"To Binary",
|
||||
"From Binary",
|
||||
"To Octal",
|
||||
|
@ -153,7 +155,8 @@
|
|||
"Typex",
|
||||
"Lorenz",
|
||||
"Colossus",
|
||||
"SIGABA"
|
||||
"SIGABA",
|
||||
"XXTEA"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -176,7 +179,8 @@
|
|||
"RSA Verify",
|
||||
"RSA Encrypt",
|
||||
"RSA Decrypt",
|
||||
"Parse SSH Host Key"
|
||||
"Parse SSH Host Key",
|
||||
"Parse CSR"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -243,6 +247,7 @@
|
|||
"Encode NetBIOS Name",
|
||||
"Decode NetBIOS Name",
|
||||
"Defang URL",
|
||||
"Fang URL",
|
||||
"Defang IP Addresses"
|
||||
]
|
||||
},
|
||||
|
@ -318,6 +323,7 @@
|
|||
"To UNIX Timestamp",
|
||||
"Windows Filetime to UNIX Timestamp",
|
||||
"UNIX Timestamp to Windows Filetime",
|
||||
"DateTime Delta",
|
||||
"Extract dates",
|
||||
"Get Time",
|
||||
"Sleep"
|
||||
|
@ -334,6 +340,7 @@
|
|||
"Extract domains",
|
||||
"Extract file paths",
|
||||
"Extract dates",
|
||||
"Extract hashes",
|
||||
"Regular expression",
|
||||
"XPath expression",
|
||||
"JPath expression",
|
||||
|
@ -382,7 +389,6 @@
|
|||
"SHA2",
|
||||
"SHA3",
|
||||
"SM3",
|
||||
"MurmurHash3",
|
||||
"Keccak",
|
||||
"Shake",
|
||||
"RIPEMD",
|
||||
|
@ -407,6 +413,7 @@
|
|||
"Scrypt",
|
||||
"NT Hash",
|
||||
"LM Hash",
|
||||
"MurmurHash3",
|
||||
"Fletcher-8 Checksum",
|
||||
"Fletcher-16 Checksum",
|
||||
"Fletcher-32 Checksum",
|
||||
|
|
|
@ -147,7 +147,7 @@ class ${moduleName} extends Operation {
|
|||
this.name = "${result.opName}";
|
||||
this.module = "${result.module}";
|
||||
this.description = "${(new EscapeString).run(result.description, ["Special chars", "Double"])}";
|
||||
this.infoURL = "${result.infoURL}";
|
||||
this.infoURL = "${result.infoURL}"; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
|
||||
this.inputType = "${result.inputType}";
|
||||
this.outputType = "${result.outputType}";
|
||||
this.args = [
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @license Apache-2.0
|
||||
*/
|
||||
export function encode(tempIVP, key, rounds, input) {
|
||||
const ivp = new Uint8Array(key.concat(tempIVP));
|
||||
const ivp = new Uint8Array([...key, ...tempIVP]);
|
||||
const state = new Array(256).fill(0);
|
||||
let j = 0, i = 0;
|
||||
const result = [];
|
||||
|
|
|
@ -81,7 +81,7 @@ export const FILE_SIGNATURES = {
|
|||
0: 0x00,
|
||||
1: 0x00,
|
||||
2: 0x00,
|
||||
// 3 could be 0x24 or 0x18, so skip it
|
||||
3: [0x24, 0x18],
|
||||
4: 0x66, // ftypheic
|
||||
5: 0x74,
|
||||
6: 0x79,
|
||||
|
@ -2748,7 +2748,7 @@ export function extractGIF(bytes, offset) {
|
|||
stream.moveForwardsBy(11);
|
||||
|
||||
// Loop until next Graphic Control Extension.
|
||||
while (stream.getBytes(2) !== [0x21, 0xf9]) {
|
||||
while (!Array.from(stream.getBytes(2)).equals([0x21, 0xf9])) {
|
||||
stream.moveBackwardsBy(2);
|
||||
stream.moveForwardsBy(stream.readInt(1));
|
||||
if (!stream.readInt(1))
|
||||
|
|
|
@ -70,10 +70,14 @@ class BlowfishDecrypt extends Operation {
|
|||
inputType = args[3],
|
||||
outputType = args[4];
|
||||
|
||||
if (key.length !== 8) {
|
||||
if (key.length < 4 || key.length > 56) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||
|
||||
Blowfish uses a key length of 8 bytes (64 bits).`);
|
||||
Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`);
|
||||
}
|
||||
|
||||
if (iv.length !== 8) {
|
||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes`);
|
||||
}
|
||||
|
||||
input = Utils.convertToByteString(input, inputType);
|
||||
|
|
|
@ -70,10 +70,14 @@ class BlowfishEncrypt extends Operation {
|
|||
inputType = args[3],
|
||||
outputType = args[4];
|
||||
|
||||
if (key.length !== 8) {
|
||||
if (key.length < 4 || key.length > 56) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes
|
||||
|
||||
Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`);
|
||||
}
|
||||
|
||||
Blowfish uses a key length of 8 bytes (64 bits).`);
|
||||
if (iv.length !== 8) {
|
||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes`);
|
||||
}
|
||||
|
||||
input = Utils.convertToByteString(input, inputType);
|
||||
|
|
|
@ -100,7 +100,7 @@ class ChaCha extends Operation {
|
|||
super();
|
||||
|
||||
this.name = "ChaCha";
|
||||
this.module = "Default";
|
||||
this.module = "Ciphers";
|
||||
this.description = "ChaCha is a stream cipher designed by Daniel J. Bernstein. It is a variant of the Salsa stream cipher. Several parameterizations exist; 'ChaCha' may refer to the original construction, or to the variant as described in RFC-8439. ChaCha is often used with Poly1305, in the ChaCha20-Poly1305 AEAD construction.<br><br><b>Key:</b> ChaCha uses a key of 16 or 32 bytes (128 or 256 bits).<br><br><b>Nonce:</b> ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).<br><br><b>Counter:</b> ChaCha uses a counter of 4 or 8 bytes (32 or 64 bits); together, the nonce and counter must add up to 16 bytes. The counter starts at zero at the start of the keystream, and is incremented at every 64 bytes.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Salsa20#ChaCha_variant";
|
||||
this.inputType = "string";
|
||||
|
@ -191,7 +191,7 @@ ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`);
|
|||
if (outputType === "Hex") {
|
||||
return toHex(output);
|
||||
} else {
|
||||
return Utils.arrayBufferToStr(output);
|
||||
return Utils.arrayBufferToStr(Uint8Array.from(output).buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
107
src/core/operations/DateTimeDelta.mjs
Normal file
107
src/core/operations/DateTimeDelta.mjs
Normal file
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* @author tomgond [tom.gonda@gmail.com]
|
||||
* @copyright Crown Copyright 2024
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import moment from "moment-timezone";
|
||||
import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime.mjs";
|
||||
|
||||
/**
|
||||
* DateTime Delta operation
|
||||
*/
|
||||
class DateTimeDelta extends Operation {
|
||||
|
||||
/**
|
||||
* DateTimeDelta constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "DateTime Delta";
|
||||
this.module = "Default";
|
||||
this.description = "Calculates a new DateTime value given an input DateTime value and a time difference (delta) from the input DateTime value.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Built in formats",
|
||||
"type": "populateOption",
|
||||
"value": DATETIME_FORMATS,
|
||||
"target": 1
|
||||
},
|
||||
{
|
||||
"name": "Input format string",
|
||||
"type": "binaryString",
|
||||
"value": "DD/MM/YYYY HH:mm:ss"
|
||||
},
|
||||
{
|
||||
"name": "Time Operation",
|
||||
"type": "option",
|
||||
"value": ["Add", "Subtract"]
|
||||
},
|
||||
{
|
||||
"name": "Days",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Hours",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Minutes",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "Seconds",
|
||||
"type": "number",
|
||||
"value": 0
|
||||
}
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const inputTimezone = "UTC";
|
||||
const inputFormat = args[1];
|
||||
const operationType = args[2];
|
||||
const daysDelta = args[3];
|
||||
const hoursDelta = args[4];
|
||||
const minutesDelta = args[5];
|
||||
const secondsDelta = args[6];
|
||||
let date = "";
|
||||
|
||||
try {
|
||||
date = moment.tz(input, inputFormat, inputTimezone);
|
||||
if (!date || date.format() === "Invalid date") throw Error;
|
||||
} catch (err) {
|
||||
return `Invalid format.\n\n${FORMAT_EXAMPLES}`;
|
||||
}
|
||||
let newDate;
|
||||
if (operationType === "Add") {
|
||||
newDate = date.add(daysDelta, "days")
|
||||
.add(hoursDelta, "hours")
|
||||
.add(minutesDelta, "minutes")
|
||||
.add(secondsDelta, "seconds");
|
||||
|
||||
} else {
|
||||
newDate = date.add(-daysDelta, "days")
|
||||
.add(-hoursDelta, "hours")
|
||||
.add(-minutesDelta, "minutes")
|
||||
.add(-secondsDelta, "seconds");
|
||||
}
|
||||
return newDate.tz(inputTimezone).format(inputFormat.replace(/[<>]/g, ""));
|
||||
}
|
||||
}
|
||||
|
||||
export default DateTimeDelta;
|
|
@ -62,11 +62,13 @@ class DeriveEVPKey extends Operation {
|
|||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const passphrase = Utils.convertToByteString(args[0].string, args[0].option),
|
||||
const passphrase = CryptoJS.enc.Latin1.parse(
|
||||
Utils.convertToByteString(args[0].string, args[0].option)),
|
||||
keySize = args[1] / 32,
|
||||
iterations = args[2],
|
||||
hasher = args[3],
|
||||
salt = Utils.convertToByteString(args[4].string, args[4].option),
|
||||
salt = CryptoJS.enc.Latin1.parse(
|
||||
Utils.convertToByteString(args[4].string, args[4].option)),
|
||||
key = CryptoJS.EvpKDF(passphrase, salt, { // lgtm [js/insufficient-password-hash]
|
||||
keySize: keySize,
|
||||
hasher: CryptoJS.algo[hasher],
|
||||
|
|
84
src/core/operations/ExtractHashes.mjs
Normal file
84
src/core/operations/ExtractHashes.mjs
Normal file
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* @author mshwed [m@ttshwed.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import { search } from "../lib/Extract.mjs";
|
||||
|
||||
/**
|
||||
* Extract Hash Values operation
|
||||
*/
|
||||
class ExtractHashes extends Operation {
|
||||
|
||||
/**
|
||||
* ExtractHashValues constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Extract hashes";
|
||||
this.module = "Regex";
|
||||
this.description = "Extracts potential hashes based on hash character length";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Hash character length",
|
||||
type: "number",
|
||||
value: 40
|
||||
},
|
||||
{
|
||||
name: "All hashes",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Display Total",
|
||||
type: "boolean",
|
||||
value: false
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const results = [];
|
||||
let hashCount = 0;
|
||||
|
||||
const [hashLength, searchAllHashes, showDisplayTotal] = args;
|
||||
|
||||
// Convert character length to bit length
|
||||
let hashBitLengths = [(hashLength / 2) * 8];
|
||||
|
||||
if (searchAllHashes) hashBitLengths = [4, 8, 16, 32, 64, 128, 160, 192, 224, 256, 320, 384, 512, 1024];
|
||||
|
||||
for (const hashBitLength of hashBitLengths) {
|
||||
// Convert bit length to character length
|
||||
const hashCharacterLength = (hashBitLength / 8) * 2;
|
||||
|
||||
const regex = new RegExp(`(\\b|^)[a-f0-9]{${hashCharacterLength}}(\\b|$)`, "g");
|
||||
const searchResults = search(input, regex, null, false);
|
||||
|
||||
hashCount += searchResults.length;
|
||||
results.push(...searchResults);
|
||||
}
|
||||
|
||||
let output = "";
|
||||
if (showDisplayTotal) {
|
||||
output = `Total Results: ${hashCount}\n\n`;
|
||||
}
|
||||
|
||||
output = output + results.join("\n");
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ExtractHashes;
|
78
src/core/operations/FangURL.mjs
Normal file
78
src/core/operations/FangURL.mjs
Normal file
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @author arnydo [github@arnydo.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* FangURL operation
|
||||
*/
|
||||
class FangURL extends Operation {
|
||||
|
||||
/**
|
||||
* FangURL constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Fang URL";
|
||||
this.module = "Default";
|
||||
this.description = "Takes a 'Defanged' Universal Resource Locator (URL) and 'Fangs' it. Meaning, it removes the alterations (defanged) that render it useless so that it can be used again.";
|
||||
this.infoURL = "https://isc.sans.edu/forums/diary/Defang+all+the+things/22744/";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Restore [.]",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Restore hxxp",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Restore ://",
|
||||
type: "boolean",
|
||||
value: true
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [dots, http, slashes] = args;
|
||||
|
||||
input = fangURL(input, dots, http, slashes);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defangs a given URL
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {boolean} dots
|
||||
* @param {boolean} http
|
||||
* @param {boolean} slashes
|
||||
* @returns {string}
|
||||
*/
|
||||
function fangURL(url, dots, http, slashes) {
|
||||
if (dots) url = url.replace(/\[\.\]/g, ".");
|
||||
if (http) url = url.replace(/hxxp/g, "http");
|
||||
if (slashes) url = url.replace(/\[:\/\/\]/g, "://");
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
export default FangURL;
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @author sw5678
|
||||
* @copyright Crown Copyright 2016
|
||||
* @copyright Crown Copyright 2023
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
|
@ -21,7 +21,8 @@ class FileTree extends Operation {
|
|||
|
||||
this.name = "File Tree";
|
||||
this.module = "Default";
|
||||
this.description = "Creates file tree from list of file paths (similar to the tree command in Linux)";
|
||||
this.description = "Creates a file tree from a list of file paths (similar to the tree command in Linux)";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Tree_(command)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
|
|
|
@ -60,7 +60,7 @@ class FromBase58 extends Operation {
|
|||
run(input, args) {
|
||||
let alphabet = args[0] || ALPHABET_OPTIONS[0].value;
|
||||
const removeNonAlphaChars = args[1] === undefined ? true : args[1],
|
||||
result = [0];
|
||||
result = [];
|
||||
|
||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||
|
||||
|
@ -87,11 +87,9 @@ class FromBase58 extends Operation {
|
|||
}
|
||||
}
|
||||
|
||||
let carry = result[0] * 58 + index;
|
||||
result[0] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
let carry = index;
|
||||
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
carry += result[i] * 58;
|
||||
result[i] = carry & 0xFF;
|
||||
carry = carry >> 8;
|
||||
|
|
78
src/core/operations/FromFloat.mjs
Normal file
78
src/core/operations/FromFloat.mjs
Normal file
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import ieee754 from "ieee754";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||
|
||||
/**
|
||||
* From Float operation
|
||||
*/
|
||||
class FromFloat extends Operation {
|
||||
|
||||
/**
|
||||
* FromFloat constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "From Float";
|
||||
this.module = "Default";
|
||||
this.description = "Convert from IEEE754 Floating Point Numbers";
|
||||
this.infoURL = "https://wikipedia.org/wiki/IEEE_754";
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Endianness",
|
||||
"type": "option",
|
||||
"value": [
|
||||
"Big Endian",
|
||||
"Little Endian"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Size",
|
||||
"type": "option",
|
||||
"value": [
|
||||
"Float (4 bytes)",
|
||||
"Double (8 bytes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
if (input.length === 0) return [];
|
||||
|
||||
const [endianness, size, delimiterName] = args;
|
||||
const delim = Utils.charRep(delimiterName || "Space");
|
||||
const byteSize = size === "Double (8 bytes)" ? 8 : 4;
|
||||
const isLE = endianness === "Little Endian";
|
||||
const mLen = byteSize === 4 ? 23 : 52;
|
||||
const floats = input.split(delim);
|
||||
|
||||
const output = new Array(floats.length*byteSize);
|
||||
for (let i = 0; i < floats.length; i++) {
|
||||
ieee754.write(output, parseFloat(floats[i]), i*byteSize, isLE, mLen, byteSize);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FromFloat;
|
|
@ -50,12 +50,7 @@ class JWTSign extends Operation {
|
|||
|
||||
try {
|
||||
return jwt.sign(input, key, {
|
||||
algorithm: algorithm === "None" ? "none" : algorithm,
|
||||
|
||||
// To utilize jsonwebtoken 9+ library and maintain backwards compatibility for regression tests
|
||||
// This could be turned into operation args in a future PR
|
||||
allowInsecureKeySizes: true,
|
||||
allowInvalidAsymmetricKeyTypes: true
|
||||
algorithm: algorithm === "None" ? "none" : algorithm
|
||||
});
|
||||
} catch (err) {
|
||||
throw new OperationError(`Error: Have you entered the key correctly? The key should be either the secret for HMAC algorithms or the PEM-encoded private key for RSA and ECDSA.
|
||||
|
|
|
@ -22,7 +22,7 @@ class MurmurHash3 extends Operation {
|
|||
super();
|
||||
|
||||
this.name = "MurmurHash3";
|
||||
this.module = "Default";
|
||||
this.module = "Hashing";
|
||||
this.description = "Generates a MurmurHash v3 for a string input and an optional seed input";
|
||||
this.infoURL = "https://wikipedia.org/wiki/MurmurHash";
|
||||
this.inputType = "string";
|
||||
|
@ -115,11 +115,7 @@ class MurmurHash3 extends Operation {
|
|||
* @return {number} 32-bit signed integer
|
||||
*/
|
||||
unsignedToSigned(value) {
|
||||
if (value & 0x80000000) {
|
||||
return -0x100000000 + value;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
return value & 0x80000000 ? -0x100000000 + value : value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
273
src/core/operations/ParseCSR.mjs
Normal file
273
src/core/operations/ParseCSR.mjs
Normal file
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
* @author jkataja
|
||||
* @copyright Crown Copyright 2023
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import forge from "node-forge";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* Parse CSR operation
|
||||
*/
|
||||
class ParseCSR extends Operation {
|
||||
|
||||
/**
|
||||
* ParseCSR constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Parse CSR";
|
||||
this.module = "PublicKey";
|
||||
this.description = "Parse Certificate Signing Request (CSR) for an X.509 certificate";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Certificate_signing_request";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Input format",
|
||||
"type": "option",
|
||||
"value": ["PEM"]
|
||||
},
|
||||
{
|
||||
"name": "Key type",
|
||||
"type": "option",
|
||||
"value": ["RSA"]
|
||||
},
|
||||
{
|
||||
"name": "Strict ASN.1 value lengths",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
}
|
||||
];
|
||||
this.checks = [
|
||||
{
|
||||
"pattern": "^-+BEGIN CERTIFICATE REQUEST-+\\r?\\n[\\da-z+/\\n\\r]+-+END CERTIFICATE REQUEST-+\\r?\\n?$",
|
||||
"flags": "i",
|
||||
"args": ["PEM"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string} Human-readable description of a Certificate Signing Request (CSR).
|
||||
*/
|
||||
run(input, args) {
|
||||
if (!input.length) {
|
||||
return "No input";
|
||||
}
|
||||
|
||||
const csr = forge.pki.certificationRequestFromPem(input, args[1]);
|
||||
|
||||
// RSA algorithm is the only one supported for CSR in node-forge as of 1.3.1
|
||||
return `Version: ${1 + csr.version} (0x${Utils.hex(csr.version)})
|
||||
Subject${formatSubject(csr.subject)}
|
||||
Subject Alternative Names${formatSubjectAlternativeNames(csr)}
|
||||
Public Key
|
||||
Algorithm: RSA
|
||||
Length: ${csr.publicKey.n.bitLength()} bits
|
||||
Modulus: ${formatMultiLine(chop(csr.publicKey.n.toString(16).replace(/(..)/g, "$&:")))}
|
||||
Exponent: ${csr.publicKey.e} (0x${Utils.hex(csr.publicKey.e)})
|
||||
Signature
|
||||
Algorithm: ${forge.pki.oids[csr.signatureOid]}
|
||||
Signature: ${formatMultiLine(Utils.strToByteArray(csr.signature).map(b => Utils.hex(b)).join(":"))}
|
||||
Extensions${formatExtensions(csr)}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Subject of the request as a multi-line string
|
||||
* @param {*} subject CSR Subject
|
||||
* @returns Multi-line string describing Subject
|
||||
*/
|
||||
function formatSubject(subject) {
|
||||
let out = "\n";
|
||||
|
||||
for (const attribute of subject.attributes) {
|
||||
out += ` ${attribute.shortName} = ${attribute.value}\n`;
|
||||
}
|
||||
|
||||
return chop(out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format Subject Alternative Names from the name `subjectAltName` extension
|
||||
* @param {*} extension CSR object
|
||||
* @returns Multi-line string describing Subject Alternative Names
|
||||
*/
|
||||
function formatSubjectAlternativeNames(csr) {
|
||||
let out = "\n";
|
||||
|
||||
for (const attribute of csr.attributes) {
|
||||
for (const extension of attribute.extensions) {
|
||||
if (extension.name === "subjectAltName") {
|
||||
const names = [];
|
||||
for (const altName of extension.altNames) {
|
||||
switch (altName.type) {
|
||||
case 1:
|
||||
names.push(`EMAIL: ${altName.value}`);
|
||||
break;
|
||||
case 2:
|
||||
names.push(`DNS: ${altName.value}`);
|
||||
break;
|
||||
case 6:
|
||||
names.push(`URI: ${altName.value}`);
|
||||
break;
|
||||
case 7:
|
||||
names.push(`IP: ${altName.ip}`);
|
||||
break;
|
||||
default:
|
||||
names.push(`(unable to format type ${altName.type} name)\n`);
|
||||
}
|
||||
}
|
||||
out += indent(2, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chop(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format known extensions of a CSR
|
||||
* @param {*} csr CSR object
|
||||
* @returns Multi-line string describing attributes
|
||||
*/
|
||||
function formatExtensions(csr) {
|
||||
let out = "\n";
|
||||
|
||||
for (const attribute of csr.attributes) {
|
||||
for (const extension of attribute.extensions) {
|
||||
// formatted separately
|
||||
if (extension.name === "subjectAltName") {
|
||||
continue;
|
||||
}
|
||||
out += ` ${extension.name}${(extension.critical ? " CRITICAL" : "")}:\n`;
|
||||
let parts = [];
|
||||
switch (extension.name) {
|
||||
case "basicConstraints" :
|
||||
parts = describeBasicConstraints(extension);
|
||||
break;
|
||||
case "keyUsage" :
|
||||
parts = describeKeyUsage(extension);
|
||||
break;
|
||||
case "extKeyUsage" :
|
||||
parts = describeExtendedKeyUsage(extension);
|
||||
break;
|
||||
default :
|
||||
parts = ["(unable to format extension)"];
|
||||
}
|
||||
out += indent(4, parts);
|
||||
}
|
||||
}
|
||||
|
||||
return chop(out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format hex string onto multiple lines
|
||||
* @param {*} longStr
|
||||
* @returns Hex string as a multi-line hex string
|
||||
*/
|
||||
function formatMultiLine(longStr) {
|
||||
const lines = [];
|
||||
|
||||
for (let remain = longStr ; remain !== "" ; remain = remain.substring(48)) {
|
||||
lines.push(remain.substring(0, 48));
|
||||
}
|
||||
|
||||
return lines.join("\n ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe Basic Constraints
|
||||
* @see RFC 5280 4.2.1.9. Basic Constraints https://www.ietf.org/rfc/rfc5280.txt
|
||||
* @param {*} extension CSR extension with the name `basicConstraints`
|
||||
* @returns Array of strings describing Basic Constraints
|
||||
*/
|
||||
function describeBasicConstraints(extension) {
|
||||
const constraints = [];
|
||||
|
||||
constraints.push(`CA = ${extension.cA}`);
|
||||
if (extension.pathLenConstraint !== undefined) constraints.push(`PathLenConstraint = ${extension.pathLenConstraint}`);
|
||||
|
||||
return constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe Key Usage extension permitted use cases
|
||||
* @see RFC 5280 4.2.1.3. Key Usage https://www.ietf.org/rfc/rfc5280.txt
|
||||
* @param {*} extension CSR extension with the name `keyUsage`
|
||||
* @returns Array of strings describing Key Usage extension permitted use cases
|
||||
*/
|
||||
function describeKeyUsage(extension) {
|
||||
const usage = [];
|
||||
|
||||
if (extension.digitalSignature) usage.push("Digital signature");
|
||||
if (extension.nonRepudiation) usage.push("Non-repudiation");
|
||||
if (extension.keyEncipherment) usage.push("Key encipherment");
|
||||
if (extension.dataEncipherment) usage.push("Data encipherment");
|
||||
if (extension.keyAgreement) usage.push("Key agreement");
|
||||
if (extension.keyCertSign) usage.push("Key certificate signing");
|
||||
if (extension.cRLSign) usage.push("CRL signing");
|
||||
if (extension.encipherOnly) usage.push("Encipher only");
|
||||
if (extension.decipherOnly) usage.push("Decipher only");
|
||||
|
||||
if (usage.length === 0) usage.push("(none)");
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe Extended Key Usage extension permitted use cases
|
||||
* @see RFC 5280 4.2.1.12. Extended Key Usage https://www.ietf.org/rfc/rfc5280.txt
|
||||
* @param {*} extension CSR extension with the name `extendedKeyUsage`
|
||||
* @returns Array of strings describing Extended Key Usage extension permitted use cases
|
||||
*/
|
||||
function describeExtendedKeyUsage(extension) {
|
||||
const usage = [];
|
||||
|
||||
if (extension.serverAuth) usage.push("TLS Web Server Authentication");
|
||||
if (extension.clientAuth) usage.push("TLS Web Client Authentication");
|
||||
if (extension.codeSigning) usage.push("Code signing");
|
||||
if (extension.emailProtection) usage.push("E-mail Protection (S/MIME)");
|
||||
if (extension.timeStamping) usage.push("Trusted Timestamping");
|
||||
if (extension.msCodeInd) usage.push("Microsoft Individual Code Signing");
|
||||
if (extension.msCodeCom) usage.push("Microsoft Commercial Code Signing");
|
||||
if (extension.msCTLSign) usage.push("Microsoft Trust List Signing");
|
||||
if (extension.msSGC) usage.push("Microsoft Server Gated Crypto");
|
||||
if (extension.msEFS) usage.push("Microsoft Encrypted File System");
|
||||
if (extension.nsSGC) usage.push("Netscape Server Gated Crypto");
|
||||
|
||||
if (usage.length === 0) usage.push("(none)");
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings and add leading spaces to each line.
|
||||
* @param {*} n How many leading spaces
|
||||
* @param {*} parts Array of strings
|
||||
* @returns Joined and indented string.
|
||||
*/
|
||||
function indent(n, parts) {
|
||||
const fluff = " ".repeat(n);
|
||||
return fluff + parts.join("\n" + fluff) + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove last character from a string.
|
||||
* @param {*} s String
|
||||
* @returns Chopped string.
|
||||
*/
|
||||
function chop(s) {
|
||||
return s.substring(0, s.length - 1);
|
||||
}
|
||||
|
||||
export default ParseCSR;
|
|
@ -67,6 +67,10 @@ class RegularExpression extends Operation {
|
|||
name: "MAC address",
|
||||
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
|
||||
},
|
||||
{
|
||||
name: "UUID",
|
||||
value: "[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}"
|
||||
},
|
||||
{
|
||||
name: "Date (yyyy-mm-dd)",
|
||||
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
|
||||
|
@ -83,10 +87,6 @@ class RegularExpression extends Operation {
|
|||
name: "Strings",
|
||||
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
|
||||
},
|
||||
{
|
||||
name: "UUID (any version)",
|
||||
value: "[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}"
|
||||
},
|
||||
],
|
||||
"target": 1
|
||||
},
|
||||
|
|
|
@ -20,7 +20,7 @@ class RisonDecode extends Operation {
|
|||
super();
|
||||
|
||||
this.name = "Rison Decode";
|
||||
this.module = "Default";
|
||||
this.module = "Encodings";
|
||||
this.description = "Rison, a data serialization format optimized for compactness in URIs. Rison is a slight variation of JSON that looks vastly superior after URI encoding. Rison still expresses exactly the same set of data structures as JSON, so data can be translated back and forth without loss or guesswork.";
|
||||
this.infoURL = "https://github.com/Nanonid/rison";
|
||||
this.inputType = "string";
|
||||
|
@ -29,11 +29,7 @@ class RisonDecode extends Operation {
|
|||
{
|
||||
name: "Decode Option",
|
||||
type: "editableOption",
|
||||
value: [
|
||||
{ name: "Decode", value: "Decode", },
|
||||
{ name: "Decode Object", value: "Decode Object", },
|
||||
{ name: "Decode Array", value: "Decode Array", },
|
||||
]
|
||||
value: ["Decode", "Decode Object", "Decode Array"]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -52,8 +48,9 @@ class RisonDecode extends Operation {
|
|||
return rison.decode_object(input);
|
||||
case "Decode Array":
|
||||
return rison.decode_array(input);
|
||||
default:
|
||||
throw new OperationError("Invalid Decode option");
|
||||
}
|
||||
throw new OperationError("Invalid Decode option");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class RisonEncode extends Operation {
|
|||
super();
|
||||
|
||||
this.name = "Rison Encode";
|
||||
this.module = "Default";
|
||||
this.module = "Encodings";
|
||||
this.description = "Rison, a data serialization format optimized for compactness in URIs. Rison is a slight variation of JSON that looks vastly superior after URI encoding. Rison still expresses exactly the same set of data structures as JSON, so data can be translated back and forth without loss or guesswork.";
|
||||
this.infoURL = "https://github.com/Nanonid/rison";
|
||||
this.inputType = "Object";
|
||||
|
@ -28,13 +28,8 @@ class RisonEncode extends Operation {
|
|||
this.args = [
|
||||
{
|
||||
name: "Encode Option",
|
||||
type: "editableOption",
|
||||
value: [
|
||||
{ name: "Encode", value: "Encode", },
|
||||
{ name: "Encode Object", value: "Encode Object", },
|
||||
{ name: "Encode Array", value: "Encode Array", },
|
||||
{ name: "Encode URI", value: "Encode URI", }
|
||||
]
|
||||
type: "option",
|
||||
value: ["Encode", "Encode Object", "Encode Array", "Encode URI"]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -55,8 +50,9 @@ class RisonEncode extends Operation {
|
|||
return rison.encode_array(input);
|
||||
case "Encode URI":
|
||||
return rison.encode_uri(input);
|
||||
default:
|
||||
throw new OperationError("Invalid encode option");
|
||||
}
|
||||
throw new OperationError("Invalid encode option");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class Salsa20 extends Operation {
|
|||
super();
|
||||
|
||||
this.name = "Salsa20";
|
||||
this.module = "Default";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Salsa20 is a stream cipher designed by Daniel J. Bernstein and submitted to the eSTREAM project; Salsa20/8 and Salsa20/12 are round-reduced variants. It is closely related to the ChaCha stream cipher.<br><br><b>Key:</b> Salsa20 uses a key of 16 or 32 bytes (128 or 256 bits).<br><br><b>Nonce:</b> Salsa20 uses a nonce of 8 bytes (64 bits).<br><br><b>Counter:</b> Salsa uses a counter of 8 bytes (64 bits). The counter starts at zero at the start of the keystream, and is incremented at every 64 bytes.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Salsa20";
|
||||
this.inputType = "string";
|
||||
|
|
|
@ -43,7 +43,7 @@ class ToBase58 extends Operation {
|
|||
run(input, args) {
|
||||
input = new Uint8Array(input);
|
||||
let alphabet = args[0] || ALPHABET_OPTIONS[0].value,
|
||||
result = [0];
|
||||
result = [];
|
||||
|
||||
alphabet = Utils.expandAlphRange(alphabet).join("");
|
||||
|
||||
|
@ -60,11 +60,9 @@ class ToBase58 extends Operation {
|
|||
}
|
||||
|
||||
input.forEach(function(b) {
|
||||
let carry = (result[0] << 8) + b;
|
||||
result[0] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
let carry = b;
|
||||
|
||||
for (let i = 1; i < result.length; i++) {
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
carry += result[i] << 8;
|
||||
result[i] = carry % 58;
|
||||
carry = (carry / 58) | 0;
|
||||
|
|
80
src/core/operations/ToFloat.mjs
Normal file
80
src/core/operations/ToFloat.mjs
Normal file
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import ieee754 from "ieee754";
|
||||
import {DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||
|
||||
/**
|
||||
* To Float operation
|
||||
*/
|
||||
class ToFloat extends Operation {
|
||||
|
||||
/**
|
||||
* ToFloat constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "To Float";
|
||||
this.module = "Default";
|
||||
this.description = "Convert to IEEE754 Floating Point Numbers";
|
||||
this.infoURL = "https://wikipedia.org/wiki/IEEE_754";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Endianness",
|
||||
"type": "option",
|
||||
"value": [
|
||||
"Big Endian",
|
||||
"Little Endian"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Size",
|
||||
"type": "option",
|
||||
"value": [
|
||||
"Float (4 bytes)",
|
||||
"Double (8 bytes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [endianness, size, delimiterName] = args;
|
||||
const delim = Utils.charRep(delimiterName || "Space");
|
||||
const byteSize = size === "Double (8 bytes)" ? 8 : 4;
|
||||
const isLE = endianness === "Little Endian";
|
||||
const mLen = byteSize === 4 ? 23 : 52;
|
||||
|
||||
if (input.length % byteSize !== 0) {
|
||||
throw new OperationError(`Input is not a multiple of ${byteSize}`);
|
||||
}
|
||||
|
||||
const output = [];
|
||||
for (let i = 0; i < input.length; i+=byteSize) {
|
||||
output.push(ieee754.read(input, i, isLE, mLen, byteSize));
|
||||
}
|
||||
return output.join(delim);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ToFloat;
|
|
@ -22,7 +22,7 @@ class XSalsa20 extends Operation {
|
|||
super();
|
||||
|
||||
this.name = "XSalsa20";
|
||||
this.module = "Default";
|
||||
this.module = "Ciphers";
|
||||
this.description = "XSalsa20 is a variant of the Salsa20 stream cipher designed by Daniel J. Bernstein; XSalsa uses longer nonces.<br><br><b>Key:</b> XSalsa20 uses a key of 16 or 32 bytes (128 or 256 bits).<br><br><b>Nonce:</b> XSalsa20 uses a nonce of 24 bytes (192 bits).<br><br><b>Counter:</b> XSalsa uses a counter of 8 bytes (64 bits). The counter starts at zero at the start of the keystream, and is incremented at every 64 bytes.";
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/Salsa20#XSalsa20_with_192-bit_nonce";
|
||||
this.inputType = "string";
|
||||
|
|
182
src/core/operations/XXTEA.mjs
Normal file
182
src/core/operations/XXTEA.mjs
Normal file
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* @author devcydo [devcydo@gmail.com]
|
||||
* @author Ma Bingyao [mabingyao@gmail.com]
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import {toBase64} from "../lib/Base64.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* XXTEA Encrypt operation
|
||||
*/
|
||||
class XXTEAEncrypt extends Operation {
|
||||
|
||||
/**
|
||||
* XXTEAEncrypt constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "XXTEA";
|
||||
this.module = "Default";
|
||||
this.description = "Corrected Block TEA (often referred to as XXTEA) is a block cipher designed to correct weaknesses in the original Block TEA. XXTEA operates on variable-length blocks that are some arbitrary multiple of 32 bits in size (minimum 64 bits). The number of full cycles depends on the block size, but there are at least six (rising to 32 for small block sizes). The original Block TEA applies the XTEA round function to each word in the block and combines it additively with its leftmost neighbour. Slow diffusion rate of the decryption process was immediately exploited to break the cipher. Corrected Block TEA uses a more involved round function which makes use of both immediate neighbours in processing each word in the block.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/XXTEA";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
let key = args[0];
|
||||
|
||||
if (input === undefined || input === null || input.length === 0) {
|
||||
throw new OperationError("Invalid input length (0)");
|
||||
}
|
||||
|
||||
if (key === undefined || key === null || key.length === 0) {
|
||||
throw new OperationError("Invalid key length (0)");
|
||||
}
|
||||
|
||||
input = Utils.convertToByteString(input, "utf8");
|
||||
key = Utils.convertToByteString(key, "utf8");
|
||||
|
||||
input = this.convertToUint32Array(input, true);
|
||||
key = this.fixLength(this.convertToUint32Array(key, false));
|
||||
|
||||
let encrypted = this.encryptUint32Array(input, key);
|
||||
|
||||
encrypted = toBase64(this.toBinaryString(encrypted, false));
|
||||
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Uint32Array to binary string
|
||||
*
|
||||
* @param {Uint32Array} v
|
||||
* @param {Boolean} includeLength
|
||||
* @returns {string}
|
||||
*/
|
||||
toBinaryString(v, includeLENGTH) {
|
||||
const LENGTH = v.length;
|
||||
let n = LENGTH << 2;
|
||||
if (includeLENGTH) {
|
||||
const M = v[LENGTH - 1];
|
||||
n -= 4;
|
||||
if ((M < n - 3) || (M > n)) {
|
||||
return null;
|
||||
}
|
||||
n = M;
|
||||
}
|
||||
for (let i = 0; i < LENGTH; i++) {
|
||||
v[i] = String.fromCharCode(
|
||||
v[i] & 0xFF,
|
||||
v[i] >>> 8 & 0xFF,
|
||||
v[i] >>> 16 & 0xFF,
|
||||
v[i] >>> 24 & 0xFF
|
||||
);
|
||||
}
|
||||
const RESULT = v.join("");
|
||||
if (includeLENGTH) {
|
||||
return RESULT.substring(0, n);
|
||||
}
|
||||
return RESULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} sum
|
||||
* @param {number} y
|
||||
* @param {number} z
|
||||
* @param {number} p
|
||||
* @param {number} e
|
||||
* @param {number} k
|
||||
* @returns {number}
|
||||
*/
|
||||
mx(sum, y, z, p, e, k) {
|
||||
return ((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (k[p & 3 ^ e] ^ z));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encrypt Uint32Array
|
||||
*
|
||||
* @param {Uint32Array} v
|
||||
* @param {number} k
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
encryptUint32Array(v, k) {
|
||||
const LENGTH = v.length;
|
||||
const N = LENGTH - 1;
|
||||
let y, z, sum, e, p, q;
|
||||
z = v[N];
|
||||
sum = 0;
|
||||
for (q = Math.floor(6 + 52 / LENGTH) | 0; q > 0; --q) {
|
||||
sum = (sum + 0x9E3779B9) & 0xFFFFFFFF;
|
||||
e = sum >>> 2 & 3;
|
||||
for (p = 0; p < N; ++p) {
|
||||
y = v[p + 1];
|
||||
z = v[p] = (v[p] + this.mx(sum, y, z, p, e, k)) & 0xFFFFFFFF;
|
||||
}
|
||||
y = v[0];
|
||||
z = v[N] = (v[N] + this.mx(sum, y, z, N, e, k)) & 0xFFFFFFFF;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes the Uint32Array lenght to 4
|
||||
*
|
||||
* @param {Uint32Array} k
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
fixLength(k) {
|
||||
if (k.length < 4) {
|
||||
k.length = 4;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string to Uint32Array
|
||||
*
|
||||
* @param {string} bs
|
||||
* @param {Boolean} includeLength
|
||||
* @returns {Uint32Array}
|
||||
*/
|
||||
convertToUint32Array(bs, includeLength) {
|
||||
const LENGTH = bs.length;
|
||||
let n = LENGTH >> 2;
|
||||
if ((LENGTH & 3) !== 0) {
|
||||
++n;
|
||||
}
|
||||
let v;
|
||||
if (includeLength) {
|
||||
v = new Array(n + 1);
|
||||
v[n] = LENGTH;
|
||||
} else {
|
||||
v = new Array(n);
|
||||
}
|
||||
for (let i = 0; i < LENGTH; ++i) {
|
||||
v[i >> 2] |= bs.charCodeAt(i) << ((i & 3) << 3);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default XXTEAEncrypt;
|
2
src/core/vendor/DisassembleX86-64.mjs
vendored
2
src/core/vendor/DisassembleX86-64.mjs
vendored
|
@ -4054,7 +4054,7 @@ function DecodeImmediate( type, BySize, SizeSetting )
|
|||
|
||||
//Sign bit adjust.
|
||||
|
||||
if( V32 >= ( n >> 1 ) ) { V32 -= n; }
|
||||
if( V32 >= ( n / 2 ) ) { V32 -= n; }
|
||||
|
||||
//Add position.
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<!-- htmlmin:ignore --><!--
|
||||
CyberChef - The Cyber Swiss Army Knife
|
||||
|
||||
@copyright Crown Copyright 2016
|
||||
@copyright Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %>
|
||||
@license Apache-2.0
|
||||
|
||||
Copyright 2016 Crown Copyright
|
||||
Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %> Crown Copyright
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -25,7 +25,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<title>CyberChef</title>
|
||||
|
||||
<meta name="copyright" content="Crown Copyright 2016" />
|
||||
<meta name="copyright" content="Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %>" />
|
||||
<meta name="description" content="The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis" />
|
||||
<meta name="keywords" content="base64, hex, decode, encode, encrypt, decrypt, compress, decompress, regex, regular expressions, hash, crypt, hexadecimal, user agent, url, certificate, x.509, parser, JSON, gzip, md5, sha1, aes, des, blowfish, xor" />
|
||||
|
||||
|
@ -562,10 +562,10 @@
|
|||
<div class="modal-body">
|
||||
<img aria-hidden="true" class="about-img-left" src="<%- require('../static/images/cyberchef-128x128.png') %>" alt="CyberChef Logo"/>
|
||||
<p class="subtext">
|
||||
Version <%= htmlWebpackPlugin.options.version %><br>
|
||||
Version <%= htmlWebpackPlugin.options.version %><br>
|
||||
Compile time: <%= htmlWebpackPlugin.options.compileTime %>
|
||||
</p>
|
||||
<p>© Crown Copyright 2016.</p>
|
||||
<p>© Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %>.</p>
|
||||
<p>Released under the Apache Licence, Version 2.0.</p>
|
||||
<p><a href="https://gitter.im/gchq/CyberChef">
|
||||
<img src="<%- require('../static/images/gitter-badge.svg') %>">
|
||||
|
@ -861,7 +861,7 @@
|
|||
<ul>
|
||||
<li>Build time: <%= htmlWebpackPlugin.options.compileTime %></li>
|
||||
<li>The changelog for this version can be viewed <a href="https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md">here</a></li>
|
||||
<li>© Crown Copyright 2016</li>
|
||||
<li>© Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %></li>
|
||||
<li>Released under the Apache Licence, Version 2.0</li>
|
||||
<li>SHA256 hash: DOWNLOAD_HASH_PLACEHOLDER</li>
|
||||
</ul>
|
||||
|
|
|
@ -126,8 +126,8 @@ module.exports = {
|
|||
// testOp(browser, "Extract email addresses", "test input", "test_output");
|
||||
// testOp(browser, "Extract file paths", "test input", "test_output");
|
||||
testOpFile(browser, "Extract Files", "files/Hitchhikers_Guide.jpeg", ".card:last-child .collapsed", "extracted_at_0x3d38.zlib");
|
||||
testOpFile(browser, "Extract ID3", "files/mp3example.mp3", "tr:last-child td:last-child", "Kevin MacLeod");
|
||||
// testOp(browser, "Extract IP addresses", "test input", "test_output");
|
||||
// This test seems unreliable on GitHub Actions, not reproducible locally.
|
||||
// testOpFile(browser, "Extract ID3", "files/mp3example.mp3", "tr:last-child td:last-child", "Kevin MacLeod"); // testOp(browser, "Extract IP addresses", "test input", "test_output");
|
||||
// testOp(browser, "Extract LSB", "test input", "test_output");
|
||||
// testOp(browser, "Extract MAC addresses", "test input", "test_output");
|
||||
// testOp(browser, "Extract RGBA", "test input", "test_output");
|
||||
|
|
|
@ -432,7 +432,7 @@ color: white;
|
|||
it("Disassemble x86", () => {
|
||||
const result = chef.disassembleX86(chef.toBase64("one two three"));
|
||||
const expected = `0000000000000000 0000 ADD BYTE PTR [RAX],AL\r
|
||||
0000000000000002 0B250000000B OR ESP,DWORD PTR [0000000-F4FFFFF8]\r
|
||||
0000000000000002 0B250000000B OR ESP,DWORD PTR [000000000B000008]\r
|
||||
`;
|
||||
assert.strictEqual(result.toString(), expected);
|
||||
}),
|
||||
|
|
|
@ -62,6 +62,8 @@ import "./tests/DefangIP.mjs";
|
|||
import "./tests/ELFInfo.mjs";
|
||||
import "./tests/Enigma.mjs";
|
||||
import "./tests/ExtractEmailAddresses.mjs";
|
||||
import "./tests/ExtractHashes.mjs";
|
||||
import "./tests/Float.mjs";
|
||||
import "./tests/FileTree.mjs";
|
||||
import "./tests/FletcherChecksum.mjs";
|
||||
import "./tests/Fork.mjs";
|
||||
|
@ -147,6 +149,7 @@ import "./tests/Typex.mjs";
|
|||
import "./tests/UnescapeString.mjs";
|
||||
import "./tests/Unicode.mjs";
|
||||
import "./tests/YARA.mjs";
|
||||
import "./tests/ParseCSR.mjs";
|
||||
|
||||
const testStatus = {
|
||||
allTestsPassing: true,
|
||||
|
|
|
@ -53,6 +53,28 @@ TestRegister.addTests([
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base58 all null",
|
||||
input: "\0\0\0\0\0\0",
|
||||
expectedOutput: "111111",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "To Base58",
|
||||
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "From Base58 all null",
|
||||
input: "111111",
|
||||
expectedOutput: "\0\0\0\0\0\0",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Base58",
|
||||
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Base58 with null prefix and suffix",
|
||||
input: "\0\0\0Hello\0\0\0",
|
||||
|
|
|
@ -58,6 +58,25 @@ ChaCha uses a nonce of 8 or 12 bytes (64 or 96 bits).`,
|
|||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ChaCha: RFC8439 Raw output",
|
||||
input: "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.",
|
||||
expectedOutput: "6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 87 4d",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "ChaCha",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f"},
|
||||
{"option": "Hex", "string": "00:00:00:00:00:00:00:4a:00:00:00:00"},
|
||||
1, "20", "Raw", "Raw",
|
||||
]
|
||||
},
|
||||
{
|
||||
"op": "To Hex",
|
||||
"args": []
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ChaCha: draft-strombergson-chacha-test-vectors-01 TC7.1",
|
||||
input: "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
||||
|
|
|
@ -21,13 +21,16 @@ TestRegister.addTests([
|
|||
],
|
||||
},
|
||||
{
|
||||
// input taken from https://ciphersaber.gurus.org/
|
||||
name: "CipherSaber2 Decrypt",
|
||||
input: "\x5d\xd9\x7f\xeb\x77\x3c\x42\x9d\xfe\x9c\x3b\x21\x63\xbd\x53\x38\x18\x7c\x36\x37",
|
||||
expectedOutput: "helloworld",
|
||||
input: "\x6f\x6d\x0b\xab\xf3\xaa\x67\x19\x03\x15\x30\xed\xb6\x77" +
|
||||
"\xca\x74\xe0\x08\x9d\xd0\xe7\xb8\x85\x43\x56\xbb\x14\x48\xe3" +
|
||||
"\x7c\xdb\xef\xe7\xf3\xa8\x4f\x4f\x5f\xb3\xfd",
|
||||
expectedOutput: "This is a test of CipherSaber.",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "CipherSaber2 Decrypt",
|
||||
args: [{ "option": "Latin1", "string": "test" }, 20],
|
||||
args: [{ "option": "Latin1", "string": "asdfg" }, 1],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -1948,4 +1948,38 @@ DES uses a key length of 8 bytes (64 bits).`,
|
|||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Blowfish Encrypt with variable key length: CBC, ASCII, 4 bytes",
|
||||
input: "The quick brown fox jumps over the lazy dog.",
|
||||
expectedOutput: "823f337a53ecf121aa9ec1b111bd5064d1d7586abbdaaa0c8fd0c6cc43c831c88bf088ee3e07287e3f36cf2e45f9c7e6",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Blowfish Encrypt",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00112233"}, // Key
|
||||
{"option": "Hex", "string": "0000000000000000"}, // IV
|
||||
"CBC", // Mode
|
||||
"Raw", // Input
|
||||
"Hex" // Output
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Blowfish Encrypt with variable key length: CBC, ASCII, 42 bytes",
|
||||
input: "The quick brown fox jumps over the lazy dog.",
|
||||
expectedOutput: "19f5a68145b34321cfba72226b0f33922ce44dd6e7869fe328db64faae156471216f12ed2a37fd0bdd7cebf867b3cff0",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Blowfish Encrypt",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"}, // Key
|
||||
{"option": "Hex", "string": "0000000000000000"}, // IV
|
||||
"CBC", // Mode
|
||||
"Raw", // Input
|
||||
"Hex" // Output
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
|
|
|
@ -31,4 +31,26 @@ TestRegister.addTests([
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "DateTime Delta Positive",
|
||||
input: "20/02/2024 13:36:00",
|
||||
expectedOutput: "20/02/2024 13:37:00",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "DateTime Delta",
|
||||
args: ["Standard date and time", "DD/MM/YYYY HH:mm:ss", "Add", 0, 0, 1, 0],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "DateTime Delta Negative",
|
||||
input: "20/02/2024 14:37:00",
|
||||
expectedOutput: "20/02/2024 13:37:00",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "DateTime Delta",
|
||||
args: ["Standard date and time", "DD/MM/YYYY HH:mm:ss", "Subtract", 0, 1, 0, 0],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
|
77
tests/operations/tests/ExtractHashes.mjs
Normal file
77
tests/operations/tests/ExtractHashes.mjs
Normal file
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* ExtractHashes tests.
|
||||
*
|
||||
* @author mshwed [m@ttshwed.com]
|
||||
* @copyright Crown Copyright 2024
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Extract MD5 hash",
|
||||
input: "The quick brown fox jumps over the lazy dog\n\nMD5: 9e107d9d372bb6826bd81d3542a419d6",
|
||||
expectedOutput: "9e107d9d372bb6826bd81d3542a419d6",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract hashes",
|
||||
"args": [32, false, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract SHA1 hash",
|
||||
input: "The quick brown fox jumps over the lazy dog\n\nSHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
|
||||
expectedOutput: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract hashes",
|
||||
"args": [40, false, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract SHA256 hash",
|
||||
input: "The quick brown fox jumps over the lazy dog\n\nSHA256: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
expectedOutput: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract hashes",
|
||||
"args": [64, false, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract SHA512 hash",
|
||||
input: "The quick brown fox jumps over the lazy dog\n\nSHA512: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6",
|
||||
expectedOutput: "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract hashes",
|
||||
"args": [128, false, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract all hashes",
|
||||
input: "The quick brown fox jumps over the lazy dog\n\nMD5: 9e107d9d372bb6826bd81d3542a419d6\nSHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\nSHA256: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
expectedOutput: "9e107d9d372bb6826bd81d3542a419d6\n2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\nd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract hashes",
|
||||
"args": [0, true, false]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Extract hashes with total count",
|
||||
input: "The quick brown fox jumps over the lazy dog\n\nMD5: 9e107d9d372bb6826bd81d3542a419d6\nSHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\nSHA256: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
expectedOutput: "Total Results: 3\n\n9e107d9d372bb6826bd81d3542a419d6\n2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\nd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Extract hashes",
|
||||
"args": [0, true, true]
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
164
tests/operations/tests/Float.mjs
Normal file
164
tests/operations/tests/Float.mjs
Normal file
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Float tests.
|
||||
*
|
||||
* @author tcode2k16 [tcode2k16@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Float: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["Auto"]
|
||||
},
|
||||
{
|
||||
op: "To Float",
|
||||
args: ["Big Endian", "Float (4 bytes)", "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "To Float (Big Endian, 4 bytes): 0.5",
|
||||
input: "3f0000003f000000",
|
||||
expectedOutput: "0.5 0.5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["Auto"]
|
||||
},
|
||||
{
|
||||
op: "To Float",
|
||||
args: ["Big Endian", "Float (4 bytes)", "Space"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "To Float (Little Endian, 4 bytes): 0.5",
|
||||
input: "0000003f0000003f",
|
||||
expectedOutput: "0.5 0.5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["Auto"]
|
||||
},
|
||||
{
|
||||
op: "To Float",
|
||||
args: ["Little Endian", "Float (4 bytes)", "Space"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "To Float (Big Endian, 8 bytes): 0.5",
|
||||
input: "3fe00000000000003fe0000000000000",
|
||||
expectedOutput: "0.5 0.5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["Auto"]
|
||||
},
|
||||
{
|
||||
op: "To Float",
|
||||
args: ["Big Endian", "Double (8 bytes)", "Space"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "To Float (Little Endian, 8 bytes): 0.5",
|
||||
input: "000000000000e03f000000000000e03f",
|
||||
expectedOutput: "0.5 0.5",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["Auto"]
|
||||
},
|
||||
{
|
||||
op: "To Float",
|
||||
args: ["Little Endian", "Double (8 bytes)", "Space"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Float: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Float",
|
||||
args: ["Big Endian", "Float (4 bytes)", "Space"]
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: ["None"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Float (Big Endian, 4 bytes): 0.5",
|
||||
input: "0.5 0.5",
|
||||
expectedOutput: "3f0000003f000000",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Float",
|
||||
args: ["Big Endian", "Float (4 bytes)", "Space"]
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: ["None"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Float (Little Endian, 4 bytes): 0.5",
|
||||
input: "0.5 0.5",
|
||||
expectedOutput: "0000003f0000003f",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Float",
|
||||
args: ["Little Endian", "Float (4 bytes)", "Space"]
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: ["None"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Float (Big Endian, 8 bytes): 0.5",
|
||||
input: "0.5 0.5",
|
||||
expectedOutput: "3fe00000000000003fe0000000000000",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Float",
|
||||
args: ["Big Endian", "Double (8 bytes)", "Space"]
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: ["None"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Float (Little Endian, 8 bytes): 0.5",
|
||||
input: "0.5 0.5",
|
||||
expectedOutput: "000000000000e03f000000000000e03f",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Float",
|
||||
args: ["Little Endian", "Double (8 bytes)", "Space"]
|
||||
},
|
||||
{
|
||||
op: "To Hex",
|
||||
args: ["None"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
215
tests/operations/tests/ParseCSR.mjs
Normal file
215
tests/operations/tests/ParseCSR.mjs
Normal file
|
@ -0,0 +1,215 @@
|
|||
/**
|
||||
* Parse CSR tests.
|
||||
*
|
||||
* @author jkataja
|
||||
* @copyright Crown Copyright 2023
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
// openssl req -newkey rsa:1024 -keyout test-rsa-1024.key -out test-rsa-1024.csr \
|
||||
// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \
|
||||
// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \
|
||||
// -addext "basicConstraints = critical,CA:FALSE" \
|
||||
// -addext "keyUsage = critical,digitalSignature,keyEncipherment" \
|
||||
// -addext "extendedKeyUsage = serverAuth"
|
||||
const IN_EXAMPLE_COM_RSA_1024 = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICHzCCAYgCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G
|
||||
A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE
|
||||
ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEF
|
||||
AAOBjQAwgYkCgYEArrTrLI6FkzjX8FZfclt2ox1Dz7KRwt5f6ffZic7twLAKJ4ao
|
||||
/H3APjwoFVUXGjiNj/XF2RlId4UxB1b6CgWjujBb9W51rTdvfWLyAHsrLcptpVz+
|
||||
V9Y8X9kEFCRGGDyG5+X+Nu6COzTpUPDj4bIIX/uPk3fDYDEqLClVy8/VS48CAwEA
|
||||
AaBtMGsGCSqGSIb3DQEJDjFeMFwwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3
|
||||
dy5leGFtcGxlLmNvbTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDATBgNV
|
||||
HSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOBgQB0mUlPgt6pt/kjD0pz
|
||||
OUNk5e9nBFQYQGuGIHGYbPX3mi4Wd9vUCdPixtPSTunHWs2cxX2nM8+MdcNTY+7Q
|
||||
NFgFNIvSXhbqMYoHAAApMHJOxiWpBFdYKp3tESnlgh2lUh7lQtmOjD4a1dzfU8PU
|
||||
oViyp+UJGasN2WRd+4VtaPw64w==
|
||||
-----END CERTIFICATE REQUEST-----`;
|
||||
|
||||
const OUT_EXAMPLE_COM_RSA_1024 = `Version: 1 (0x00)
|
||||
Subject
|
||||
C = CH
|
||||
ST = Zurich
|
||||
L = Zurich
|
||||
O = Example RE
|
||||
OU = IT Department
|
||||
CN = example.com
|
||||
Subject Alternative Names
|
||||
DNS: example.com
|
||||
DNS: www.example.com
|
||||
Public Key
|
||||
Algorithm: RSA
|
||||
Length: 1024 bits
|
||||
Modulus: ae:b4:eb:2c:8e:85:93:38:d7:f0:56:5f:72:5b:76:a3:
|
||||
1d:43:cf:b2:91:c2:de:5f:e9:f7:d9:89:ce:ed:c0:b0:
|
||||
0a:27:86:a8:fc:7d:c0:3e:3c:28:15:55:17:1a:38:8d:
|
||||
8f:f5:c5:d9:19:48:77:85:31:07:56:fa:0a:05:a3:ba:
|
||||
30:5b:f5:6e:75:ad:37:6f:7d:62:f2:00:7b:2b:2d:ca:
|
||||
6d:a5:5c:fe:57:d6:3c:5f:d9:04:14:24:46:18:3c:86:
|
||||
e7:e5:fe:36:ee:82:3b:34:e9:50:f0:e3:e1:b2:08:5f:
|
||||
fb:8f:93:77:c3:60:31:2a:2c:29:55:cb:cf:d5:4b:8f
|
||||
Exponent: 65537 (0x10001)
|
||||
Signature
|
||||
Algorithm: sha256WithRSAEncryption
|
||||
Signature: 74:99:49:4f:82:de:a9:b7:f9:23:0f:4a:73:39:43:64:
|
||||
e5:ef:67:04:54:18:40:6b:86:20:71:98:6c:f5:f7:9a:
|
||||
2e:16:77:db:d4:09:d3:e2:c6:d3:d2:4e:e9:c7:5a:cd:
|
||||
9c:c5:7d:a7:33:cf:8c:75:c3:53:63:ee:d0:34:58:05:
|
||||
34:8b:d2:5e:16:ea:31:8a:07:00:00:29:30:72:4e:c6:
|
||||
25:a9:04:57:58:2a:9d:ed:11:29:e5:82:1d:a5:52:1e:
|
||||
e5:42:d9:8e:8c:3e:1a:d5:dc:df:53:c3:d4:a1:58:b2:
|
||||
a7:e5:09:19:ab:0d:d9:64:5d:fb:85:6d:68:fc:3a:e3
|
||||
Extensions
|
||||
basicConstraints CRITICAL:
|
||||
CA = false
|
||||
keyUsage CRITICAL:
|
||||
Digital signature
|
||||
Key encipherment
|
||||
extKeyUsage:
|
||||
TLS Web Server Authentication`;
|
||||
|
||||
// openssl req -newkey rsa:2048 -keyout test-rsa-2048.key -out test-rsa-2048.csr \
|
||||
// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \
|
||||
// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \
|
||||
// -addext "basicConstraints = critical,CA:FALSE" \
|
||||
// -addext "keyUsage = critical,digitalSignature,keyEncipherment" \
|
||||
// -addext "extendedKeyUsage = serverAuth"
|
||||
const IN_EXAMPLE_COM_RSA_2048 = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIDJDCCAgwCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G
|
||||
A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE
|
||||
ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAKPogLmWPuK/IGdct2v/3MFKVaVeKp2Hl5at/zDFLCAe
|
||||
51bwh7BqNVJEci4ApwlXA1WVmQPBFBJlYwQZVjz5UAN2CmNHxud5nV03YmZ2/Iml
|
||||
RzpKcZMPqU+liJCC04L+XIbOdx+Vz52dF++Cc+FuSFq803yW+qefK8JsJNO9KuPx
|
||||
RLYKSAADa9MIJisru1PzcBAOcimOmNnFWuo+LKsd4lU30OExDdKHwtyt62Mj1c3o
|
||||
lO1JjvkjtWWjwHI+0EgTjvkeXlcUYZvvLlysdKERMRozvMTGqqoHWCgWl+Rq9Z6P
|
||||
TgNsRO4CKug1Zwmh8y6acZ7sYb/dar8HOeqJnc0pCv8CAwEAAaBtMGsGCSqGSIb3
|
||||
DQEJDjFeMFwwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNv
|
||||
bTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF
|
||||
BQcDATANBgkqhkiG9w0BAQsFAAOCAQEAG0cjfRBY1pBzu+jf7yMQrK5mQrh72air
|
||||
VuXHmochmyUxyt0G7ovnNhKEr+X9snShJLi5qlyvnb2roiwlCmuwGIZxErN1svQL
|
||||
Z3kQNZgH+Vyu5IRL2DlPs5AAxVmzPpbnbXNhMHyAK/ziLcU031O1PoCpxwfvPsjW
|
||||
HWOCjbZUVaJnxdp8AHqImoGAiVhJwc37feFvb2UQlLedUypQkPg/poNWduaRDoj8
|
||||
m9cpVxuxGLtONBnohzohnFECytSXWEXPIj8L9SpYK97G02nJYYCAcb5BF11Alfux
|
||||
sNxtsr6zgPaLRrvOBT11WxJVKerbhfezAJ3naem1eM3VLxCGWwMwxg==
|
||||
-----END CERTIFICATE REQUEST-----`;
|
||||
|
||||
const OUT_EXAMPLE_COM_RSA_2048 = `Version: 1 (0x00)
|
||||
Subject
|
||||
C = CH
|
||||
ST = Zurich
|
||||
L = Zurich
|
||||
O = Example RE
|
||||
OU = IT Department
|
||||
CN = example.com
|
||||
Subject Alternative Names
|
||||
DNS: example.com
|
||||
DNS: www.example.com
|
||||
Public Key
|
||||
Algorithm: RSA
|
||||
Length: 2048 bits
|
||||
Modulus: a3:e8:80:b9:96:3e:e2:bf:20:67:5c:b7:6b:ff:dc:c1:
|
||||
4a:55:a5:5e:2a:9d:87:97:96:ad:ff:30:c5:2c:20:1e:
|
||||
e7:56:f0:87:b0:6a:35:52:44:72:2e:00:a7:09:57:03:
|
||||
55:95:99:03:c1:14:12:65:63:04:19:56:3c:f9:50:03:
|
||||
76:0a:63:47:c6:e7:79:9d:5d:37:62:66:76:fc:89:a5:
|
||||
47:3a:4a:71:93:0f:a9:4f:a5:88:90:82:d3:82:fe:5c:
|
||||
86:ce:77:1f:95:cf:9d:9d:17:ef:82:73:e1:6e:48:5a:
|
||||
bc:d3:7c:96:fa:a7:9f:2b:c2:6c:24:d3:bd:2a:e3:f1:
|
||||
44:b6:0a:48:00:03:6b:d3:08:26:2b:2b:bb:53:f3:70:
|
||||
10:0e:72:29:8e:98:d9:c5:5a:ea:3e:2c:ab:1d:e2:55:
|
||||
37:d0:e1:31:0d:d2:87:c2:dc:ad:eb:63:23:d5:cd:e8:
|
||||
94:ed:49:8e:f9:23:b5:65:a3:c0:72:3e:d0:48:13:8e:
|
||||
f9:1e:5e:57:14:61:9b:ef:2e:5c:ac:74:a1:11:31:1a:
|
||||
33:bc:c4:c6:aa:aa:07:58:28:16:97:e4:6a:f5:9e:8f:
|
||||
4e:03:6c:44:ee:02:2a:e8:35:67:09:a1:f3:2e:9a:71:
|
||||
9e:ec:61:bf:dd:6a:bf:07:39:ea:89:9d:cd:29:0a:ff
|
||||
Exponent: 65537 (0x10001)
|
||||
Signature
|
||||
Algorithm: sha256WithRSAEncryption
|
||||
Signature: 1b:47:23:7d:10:58:d6:90:73:bb:e8:df:ef:23:10:ac:
|
||||
ae:66:42:b8:7b:d9:a8:ab:56:e5:c7:9a:87:21:9b:25:
|
||||
31:ca:dd:06:ee:8b:e7:36:12:84:af:e5:fd:b2:74:a1:
|
||||
24:b8:b9:aa:5c:af:9d:bd:ab:a2:2c:25:0a:6b:b0:18:
|
||||
86:71:12:b3:75:b2:f4:0b:67:79:10:35:98:07:f9:5c:
|
||||
ae:e4:84:4b:d8:39:4f:b3:90:00:c5:59:b3:3e:96:e7:
|
||||
6d:73:61:30:7c:80:2b:fc:e2:2d:c5:34:df:53:b5:3e:
|
||||
80:a9:c7:07:ef:3e:c8:d6:1d:63:82:8d:b6:54:55:a2:
|
||||
67:c5:da:7c:00:7a:88:9a:81:80:89:58:49:c1:cd:fb:
|
||||
7d:e1:6f:6f:65:10:94:b7:9d:53:2a:50:90:f8:3f:a6:
|
||||
83:56:76:e6:91:0e:88:fc:9b:d7:29:57:1b:b1:18:bb:
|
||||
4e:34:19:e8:87:3a:21:9c:51:02:ca:d4:97:58:45:cf:
|
||||
22:3f:0b:f5:2a:58:2b:de:c6:d3:69:c9:61:80:80:71:
|
||||
be:41:17:5d:40:95:fb:b1:b0:dc:6d:b2:be:b3:80:f6:
|
||||
8b:46:bb:ce:05:3d:75:5b:12:55:29:ea:db:85:f7:b3:
|
||||
00:9d:e7:69:e9:b5:78:cd:d5:2f:10:86:5b:03:30:c6
|
||||
Extensions
|
||||
basicConstraints CRITICAL:
|
||||
CA = false
|
||||
keyUsage CRITICAL:
|
||||
Digital signature
|
||||
Key encipherment
|
||||
extKeyUsage:
|
||||
TLS Web Server Authentication`;
|
||||
|
||||
// openssl genpkey -genparam -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out test-ec-param.pem
|
||||
// openssl req -newkey ec:test-ec-param.pem -keyout test-ec.key -out test-ec.csr \
|
||||
// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \
|
||||
// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \
|
||||
// -addext "basicConstraints = critical,CA:FALSE" \
|
||||
// -addext "keyUsage = critical,digitalSignature,keyEncipherment" \
|
||||
// -addext "extendedKeyUsage = serverAuth"
|
||||
const IN_EXAMPLE_COM_EC = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBmzCCAUECAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G
|
||||
A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE
|
||||
ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqG
|
||||
SM49AwEHA0IABAmpYXNh+L9E0Q3sLhrO+MF1XgKCfqJntrOyIkrGwoiQftHbJWTA
|
||||
6duxQhU/3d9B+SN/ibeKY+xeiNBrs2eTYZ6gbTBrBgkqhkiG9w0BCQ4xXjBcMCcG
|
||||
A1UdEQQgMB6CC2V4YW1wbGUuY29tgg93d3cuZXhhbXBsZS5jb20wDAYDVR0TAQH/
|
||||
BAIwADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZI
|
||||
zj0EAwIDSAAwRQIgQkum/qaLzE3QZ3WD00uLpalUn113FObd7rM5Mr3HQwQCIQCr
|
||||
7OjzYI9v7qIJp/E9N16XfJN87G2ZVIZ4FuPXVjokCQ==
|
||||
-----END CERTIFICATE REQUEST-----`;
|
||||
|
||||
const OUT_EXAMPLE_COM_EC = `Parse CSR - Cannot read public key. OID is not RSA.`;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Parse CSR: Example Certificate Signing Request (CSR) with RSA 1024",
|
||||
input: IN_EXAMPLE_COM_RSA_1024,
|
||||
expectedOutput: OUT_EXAMPLE_COM_RSA_1024,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse CSR",
|
||||
"args": ["PEM", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Parse CSR: Example Certificate Signing Request (CSR) with RSA 2048",
|
||||
input: IN_EXAMPLE_COM_RSA_2048,
|
||||
expectedOutput: OUT_EXAMPLE_COM_RSA_2048,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse CSR",
|
||||
"args": ["PEM", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
// RSA algorithm is the only one supported for CSR in node-forge as of 1.3.1
|
||||
{
|
||||
name: "Parse CSR: Example Certificate Signing Request (CSR) with EC 256",
|
||||
input: IN_EXAMPLE_COM_EC,
|
||||
expectedError: true,
|
||||
expectedOutput: OUT_EXAMPLE_COM_EC,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse CSR",
|
||||
"args": ["PEM", true]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
62
tests/operations/tests/XXTEA.mjs
Normal file
62
tests/operations/tests/XXTEA.mjs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Base64 tests.
|
||||
*
|
||||
* @author devcydo [devcydo@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "XXTEA",
|
||||
input: "Hello World! 你好,中国!",
|
||||
expectedOutput: "QncB1C0rHQoZ1eRiPM4dsZtRi9pNrp7sqvX76cFXvrrIHXL6",
|
||||
reecipeConfig: [
|
||||
{
|
||||
args: "1234567890"
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "XXTEA",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "PbWjnbFmP8Apu2MKOGNbjeW/72IZLlLMS/g82ozLxwE=",
|
||||
reecipeConfig: [
|
||||
{
|
||||
args: "1234567890"
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "XXTEA",
|
||||
input: "ნუ პანიკას",
|
||||
expectedOutput: "dHrOJ4ClIx6gH33NPSafYR2GG7UqsazY6Xfb0iekBY4=",
|
||||
reecipeConfig: [
|
||||
{
|
||||
args: "ll3kj209d2"
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "XXTEA",
|
||||
input: "",
|
||||
expectedOutput: "Invalid input length (0)",
|
||||
reecipeConfig: [
|
||||
{
|
||||
args: "1234567890"
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "XXTEA",
|
||||
input: "",
|
||||
expectedOutput: "Invalid input length (0)",
|
||||
reecipeConfig: [
|
||||
{
|
||||
args: ""
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
Loading…
Add table
Add a link
Reference in a new issue