Compare commits

...

19 Commits

Author SHA1 Message Date
n1474335
4fee6cd5d8 6.3.2 2017-10-03 17:49:29 +00:00
n1474335
da63420d67 Added dependency badges to README 2017-10-03 17:49:19 +00:00
n1474335
72c79c684b Lint improvements 2017-10-03 17:14:40 +00:00
n1474335
a997ec0695 Updated dependencies 2017-10-03 16:56:37 +00:00
n1474335
e3be2a9531 Merge branch 'master' of github.com:gchq/CyberChef 2017-10-03 16:46:35 +00:00
n1474335
bd1790b692 6.3.1 2017-09-28 19:45:37 +00:00
n1474335
90763dee6a Added 'Register' example to FAQ 2017-09-28 19:45:29 +00:00
n1474335
16879a9190 Added 'Register' example 2017-09-28 20:43:07 +01:00
n1474335
2afd23fcf7 6.3.0 2017-09-28 19:33:01 +00:00
n1474335
39fd0f9b34 Merge branch 'feature-registers' 2017-09-28 19:31:59 +00:00
n1474335
ee57a92daa Improved register reference regex 2017-09-28 19:24:28 +00:00
n1474335
ab7cc878c3 Removed debug code 2017-09-28 18:40:29 +00:00
n1474335
877ab57f0a Multiple Register operations can now be called in a single recipe 2017-09-28 18:39:35 +00:00
n1474335
e2ac297102 Register values now displayed in the recipe 2017-09-28 17:35:52 +00:00
n1474335
b86dceb3c6 Added Register operation 2017-09-28 16:27:39 +00:00
n1474335
35c9dca955 6.2.1 2017-09-27 15:44:10 +00:00
n1474335
d54d7011d9 Removed excess auto-baking on input load from URI 2017-09-27 15:44:00 +00:00
n1474335
392652ed8e 6.2.0 2017-09-27 15:33:37 +00:00
n1474335
7557e1e9e5 Added Snefru hashing operation 2017-09-27 15:33:14 +00:00
20 changed files with 1221 additions and 794 deletions

View File

@@ -1,8 +1,11 @@
# CyberChef
[![Build Status](https://travis-ci.org/gchq/CyberChef.svg?branch=master)](https://travis-ci.org/gchq/CyberChef)
[![npm](https://badge.fury.io/js/cyberchef.svg)](https://www.npmjs.com/package/cyberchef)
![](https://reposs.herokuapp.com/?path=gchq/CyberChef&color=brightgreen)
[![dependencies Status](https://david-dm.org/gchq/CyberChef/status.svg)](https://david-dm.org/gchq/CyberChef)
[![devDependencies Status](https://david-dm.org/gchq/CyberChef/dev-status.svg)](https://david-dm.org/gchq/CyberChef?type=dev)
[![npm](http://img.shields.io/npm/v/cyberchef.svg)](https://www.npmjs.com/package/cyberchef)
![](https://reposs.herokuapp.com/?path=gchq/CyberChef&color=blue)
[![](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/gchq/CyberChef/blob/master/LICENSE)
#### *The Cyber Swiss Army Knife*
@@ -36,6 +39,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- [Convert data from a hexdump, then decompress][5]
- [Display multiple timestamps as full dates][6]
- [Carry out different operations on data of different types][7]
- [Use parts of the input as arguments to operations][8]
## Features
@@ -56,7 +60,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Search
- If you know the name of the operation you want or a word associated with it, start typing it into the search field and any matching operations will immediately be shown.
- Highlighting
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][8]).
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][9]).
- Save to file and load from file
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field (note that files larger than about 500kb may cause your browser to hang or even crash due to the way that browsers handle large amounts of textual data).
- CyberChef is entirely client-side
@@ -94,4 +98,5 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
[5]: https://gchq.github.io/CyberChef/#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
[6]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
[8]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
[8]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ
[9]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4

1119
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "6.1.0",
"version": "6.3.2",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -35,8 +35,8 @@
"babel-preset-env": "^1.6.0",
"css-loader": "^0.28.7",
"exports-loader": "^0.6.4",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.2",
"extract-text-webpack-plugin": "^3.0.1",
"file-loader": "^1.1.4",
"grunt": ">=1.0.1",
"grunt-accessibility": "~5.0.0",
"grunt-chmod": "~1.1.1",
@@ -46,7 +46,7 @@
"grunt-eslint": "^20.1.0",
"grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.1.1",
"grunt-jsdoc": "^2.2.0",
"grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"imports-loader": "^0.7.1",
@@ -55,23 +55,23 @@
"less": "^2.7.2",
"less-loader": "^4.0.5",
"postcss-css-variables": "^0.8.0",
"postcss-import": "^10.0.0",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.6",
"style-loader": "^0.18.2",
"style-loader": "^0.19.0",
"url-loader": "^0.5.9",
"val-loader": "^1.0.2",
"web-resource-inliner": "^4.1.1",
"web-resource-inliner": "^4.2.0",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.8.2",
"webpack-dev-server": "^2.9.1",
"webpack-node-externals": "^1.6.0",
"worker-loader": "^0.8.0"
"worker-loader": "^1.0.0"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"bootstrap": "^3.3.7",
"bootstrap-colorpicker": "^2.5.1",
"bootstrap-colorpicker": "^2.5.2",
"bootstrap-switch": "^3.3.4",
"crypto-api": "^0.7.4",
"crypto-api": "^0.7.5",
"crypto-js": "^3.1.9-1",
"diff": "^3.3.1",
"escodegen": "^1.9.0",
@@ -84,7 +84,7 @@
"js-sha3": "^0.6.1",
"jsbn": "^1.1.0",
"jsonpath": "^0.2.12",
"jsrsasign": "8.0.3",
"jsrsasign": "8.0.4",
"lodash": "^4.17.4",
"moment": "^2.18.1",
"moment-timezone": "^0.5.13",

View File

@@ -92,7 +92,7 @@ async function bake(data) {
} catch (err) {
self.postMessage({
action: "bakeError",
data: err.message
data: err.message.split(":").slice(1).join(":").slice(1) // Cut off worker blurb
});
}
}
@@ -176,3 +176,22 @@ self.setOption = function(option, value) {
}
});
};
/**
* Send register values back to the app.
*
* @param {number} opIndex
* @param {number} numPrevRegisters
* @param {string[]} registers
*/
self.setRegisters = function(opIndex, numPrevRegisters, registers) {
self.postMessage({
action: "setRegisters",
data: {
opIndex: opIndex,
numPrevRegisters: numPrevRegisters,
registers: registers
}
});
};

View File

@@ -90,6 +90,74 @@ const FlowControl = {
},
/**
* Register operation.
*
* @param {Object} state - The current state of the recipe.
* @param {number} state.progress - The current position in the recipe.
* @param {Dish} state.dish - The Dish being operated on.
* @param {Operation[]} state.opList - The list of operations in the recipe.
* @returns {Object} The updated state of the recipe.
*/
runRegister: function(state) {
const ings = state.opList[state.progress].getIngValues(),
extractorStr = ings[0],
i = ings[1],
m = ings[2];
let modifiers = "";
if (i) modifiers += "i";
if (m) modifiers += "m";
const extractor = new RegExp(extractorStr, modifiers),
input = state.dish.get(Dish.STRING),
registers = input.match(extractor);
if (!registers) return state;
if (ENVIRONMENT_IS_WORKER()) {
self.setRegisters(state.progress, state.numRegisters, registers.slice(1));
}
/**
* Replaces references to registers (e.g. $R0) with the contents of those registers.
*
* @param {string} str
* @returns {string}
*/
function replaceRegister(str) {
// Replace references to registers ($Rn) with contents of registers
return str.replace(/(\\*)\$R(\d{1,2})/g, (match, slashes, regNum) => {
const index = parseInt(regNum, 10) + 1;
if (index <= state.numRegisters || index >= state.numRegisters + registers.length)
return match;
if (slashes.length % 2 !== 0) return match.slice(1); // Remove escape
return slashes + registers[index - state.numRegisters];
});
}
// Step through all subsequent ops and replace registers in args with extracted content
for (let i = state.progress + 1; i < state.opList.length; i++) {
if (state.opList[i].isDisabled()) continue;
let args = state.opList[i].getIngValues();
args = args.map(arg => {
if (typeof arg !== "string" && typeof arg !== "object") return arg;
if (typeof arg === "object" && arg.hasOwnProperty("string")) {
arg.string = replaceRegister(arg.string);
return arg;
}
return replaceRegister(arg);
});
state.opList[i].setIngValues(args);
}
state.numRegisters += registers.length - 1;
return state;
},
/**
* Jump operation.
*

View File

@@ -145,7 +145,7 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
*/
Recipe.prototype.execute = async function(dish, startFrom) {
startFrom = startFrom || 0;
let op, input, output, numJumps = 0;
let op, input, output, numJumps = 0, numRegisters = 0;
for (let i = startFrom; i < this.opList.length; i++) {
op = this.opList[i];
@@ -162,15 +162,17 @@ Recipe.prototype.execute = async function(dish, startFrom) {
if (op.isFlowControl()) {
// Package up the current state
let state = {
"progress": i,
"dish": dish,
"opList": this.opList,
"numJumps": numJumps
"progress": i,
"dish": dish,
"opList": this.opList,
"numJumps": numJumps,
"numRegisters": numRegisters
};
state = await op.run(state);
i = state.progress;
numJumps = state.numJumps;
numRegisters = state.numRegisters;
} else {
output = await op.run(input, op.getIngValues());
dish.set(output, op.outputType);

View File

@@ -409,7 +409,7 @@ const Utils = {
* Utils.strToCharcode("你好");
*/
strToCharcode: function(str) {
const charcode = new Array();
const charcode = [];
for (let i = 0; i < str.length; i++) {
let ord = str.charCodeAt(i);

View File

@@ -257,6 +257,7 @@ const Categories = [
"RIPEMD",
"HAS-160",
"Whirlpool",
"Snefru",
"HMAC",
"Fletcher-8 Checksum",
"Fletcher-16 Checksum",
@@ -316,6 +317,7 @@ const Categories = [
ops: [
"Fork",
"Merge",
"Register",
"Jump",
"Conditional Jump",
"Return",

View File

@@ -116,6 +116,30 @@ const OperationConfig = {
flowControl: true,
args: []
},
"Register": {
module: "Default",
description: "Extract data from the input and store it in registers which can then be passed into subsequent operations as arguments. Regular expression capture groups are used to select the data to extract.<br><br>To use registers in arguments, refer to them using the notation <code>$Rn</code> where n is the register number, starting at 0.<br><br>For example:<br>Input: <code>Test</code><br>Extractor: <code>(.*)</code><br>Argument: <code>$R0</code> becomes <code>Test</code><br><br>Registers can be escaped in arguments using a backslash. e.g. <code>\\$R0</code> would become <code>$R0</code> rather than <code>Test</code>.",
inputType: "string",
outputType: "string",
flowControl: true,
args: [
{
name: "Extractor",
type: "binaryString",
value: "([\\s\\S]*)"
},
{
name: "Case insensitive",
type: "boolean",
value: true
},
{
name: "Multiline matching",
type: "boolean",
value: false
},
]
},
"Jump": {
module: "Default",
description: "Jump forwards or backwards over the specified number of operations.",
@@ -3011,6 +3035,24 @@ const OperationConfig = {
}
]
},
"Snefru": {
module: "Hashing",
description: "Snefru is a cryptographic hash function invented by Ralph Merkle in 1990 while working at Xerox PARC. The function supports 128-bit and 256-bit output. It was named after the Egyptian Pharaoh Sneferu, continuing the tradition of the Khufu and Khafre block ciphers.<br><br>The original design of Snefru was shown to be insecure by Eli Biham and Adi Shamir who were able to use differential cryptanalysis to find hash collisions. The design was then modified by increasing the number of iterations of the main pass of the algorithm from two to eight.",
inputType: "string",
outputType: "string",
args: [
{
name: "Rounds",
type: "option",
value: Hash.SNEFRU_ROUNDS
},
{
name: "Size",
type: "option",
value: Hash.SNEFRU_SIZE
}
]
},
"HMAC": {
module: "Hashing",
description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.",

View File

@@ -154,6 +154,7 @@ OpModules.Default = {
"Generate HOTP": OTP.runHOTP,
"Fork": FlowControl.runFork,
"Merge": FlowControl.runMerge,
"Register": FlowControl.runRegister,
"Jump": FlowControl.runJump,
"Conditional Jump": FlowControl.runCondJump,
"Return": FlowControl.runReturn,

View File

@@ -33,6 +33,7 @@ OpModules.Hashing = {
"RIPEMD": Hash.runRIPEMD,
"HAS-160": Hash.runHAS,
"Whirlpool": Hash.runWhirlpool,
"Snefru": Hash.runSnefru,
"HMAC": Hash.runHMAC,
"Fletcher-8 Checksum": Checksum.runFletcher8,
"Fletcher-16 Checksum": Checksum.runFletcher16,

View File

@@ -192,268 +192,270 @@ const DateTime = {
/**
* @constant
*/
FORMAT_EXAMPLES: "Format string tokens:\n\n\
<table class='table table-striped table-hover table-condensed table-bordered' style='font-family: sans-serif'>\
<thead>\
<tr>\
<th>Category</th>\
<th>Token</th>\
<th>Output</th>\
</tr>\
</thead>\
<tbody>\
<tr>\
<td><b>Month</b></td>\
<td>M</td>\
<td>1 2 ... 11 12</td>\
</tr>\
<tr>\
<td></td>\
<td>Mo</td>\
<td>1st 2nd ... 11th 12th</td>\
</tr>\
<tr>\
<td></td>\
<td>MM</td>\
<td>01 02 ... 11 12</td>\
</tr>\
<tr>\
<td></td>\
<td>MMM</td>\
<td>Jan Feb ... Nov Dec</td>\
</tr>\
<tr>\
<td></td>\
<td>MMMM</td>\
<td>January February ... November December</td>\
</tr>\
<tr>\
<td><b>Quarter</b></td>\
<td>Q</td>\
<td>1 2 3 4</td>\
</tr>\
<tr>\
<td><b>Day of Month</b></td>\
<td>D</td>\
<td>1 2 ... 30 31</td>\
</tr>\
<tr>\
<td></td>\
<td>Do</td>\
<td>1st 2nd ... 30th 31st</td>\
</tr>\
<tr>\
<td></td>\
<td>DD</td>\
<td>01 02 ... 30 31</td>\
</tr>\
<tr>\
<td><b>Day of Year</b></td>\
<td>DDD</td>\
<td>1 2 ... 364 365</td>\
</tr>\
<tr>\
<td></td>\
<td>DDDo</td>\
<td>1st 2nd ... 364th 365th</td>\
</tr>\
<tr>\
<td></td>\
<td>DDDD</td>\
<td>001 002 ... 364 365</td>\
</tr>\
<tr>\
<td><b>Day of Week</b></td>\
<td>d</td>\
<td>0 1 ... 5 6</td>\
</tr>\
<tr>\
<td></td>\
<td>do</td>\
<td>0th 1st ... 5th 6th</td>\
</tr>\
<tr>\
<td></td>\
<td>dd</td>\
<td>Su Mo ... Fr Sa</td>\
</tr>\
<tr>\
<td></td>\
<td>ddd</td>\
<td>Sun Mon ... Fri Sat</td>\
</tr>\
<tr>\
<td></td>\
<td>dddd</td>\
<td>Sunday Monday ... Friday Saturday</td>\
</tr>\
<tr>\
<td><b>Day of Week (Locale)</b></td>\
<td>e</td>\
<td>0 1 ... 5 6</td>\
</tr>\
<tr>\
<td><b>Day of Week (ISO)</b></td>\
<td>E</td>\
<td>1 2 ... 6 7</td>\
</tr>\
<tr>\
<td><b>Week of Year</b></td>\
<td>w</td>\
<td>1 2 ... 52 53</td>\
</tr>\
<tr>\
<td></td>\
<td>wo</td>\
<td>1st 2nd ... 52nd 53rd</td>\
</tr>\
<tr>\
<td></td>\
<td>ww</td>\
<td>01 02 ... 52 53</td>\
</tr>\
<tr>\
<td><b>Week of Year (ISO)</b></td>\
<td>W</td>\
<td>1 2 ... 52 53</td>\
</tr>\
<tr>\
<td></td>\
<td>Wo</td>\
<td>1st 2nd ... 52nd 53rd</td>\
</tr>\
<tr>\
<td></td>\
<td>WW</td>\
<td>01 02 ... 52 53</td>\
</tr>\
<tr>\
<td><b>Year</b></td>\
<td>YY</td>\
<td>70 71 ... 29 30</td>\
</tr>\
<tr>\
<td></td>\
<td>YYYY</td>\
<td>1970 1971 ... 2029 2030</td>\
</tr>\
<tr>\
<td><b>Week Year</b></td>\
<td>gg</td>\
<td>70 71 ... 29 30</td>\
</tr>\
<tr>\
<td></td>\
<td>gggg</td>\
<td>1970 1971 ... 2029 2030</td>\
</tr>\
<tr>\
<td><b>Week Year (ISO)</b></td>\
<td>GG</td>\
<td>70 71 ... 29 30</td>\
</tr>\
<tr>\
<td></td>\
<td>GGGG</td>\
<td>1970 1971 ... 2029 2030</td>\
</tr>\
<tr>\
<td><b>AM/PM</b></td>\
<td>A</td>\
<td>AM PM</td>\
</tr>\
<tr>\
<td></td>\
<td>a</td>\
<td>am pm</td>\
</tr>\
<tr>\
<td><b>Hour</b></td>\
<td>H</td>\
<td>0 1 ... 22 23</td>\
</tr>\
<tr>\
<td></td>\
<td>HH</td>\
<td>00 01 ... 22 23</td>\
</tr>\
<tr>\
<td></td>\
<td>h</td>\
<td>1 2 ... 11 12</td>\
</tr>\
<tr>\
<td></td>\
<td>hh</td>\
<td>01 02 ... 11 12</td>\
</tr>\
<tr>\
<td><b>Minute</b></td>\
<td>m</td>\
<td>0 1 ... 58 59</td>\
</tr>\
<tr>\
<td></td>\
<td>mm</td>\
<td>00 01 ... 58 59</td>\
</tr>\
<tr>\
<td><b>Second</b></td>\
<td>s</td>\
<td>0 1 ... 58 59</td>\
</tr>\
<tr>\
<td></td>\
<td>ss</td>\
<td>00 01 ... 58 59</td>\
</tr>\
<tr>\
<td><b>Fractional Second</b></td>\
<td>S</td>\
<td>0 1 ... 8 9</td>\
</tr>\
<tr>\
<td></td>\
<td>SS</td>\
<td>00 01 ... 98 99</td>\
</tr>\
<tr>\
<td></td>\
<td>SSS</td>\
<td>000 001 ... 998 999</td>\
</tr>\
<tr>\
<td></td>\
<td>SSSS ... SSSSSSSSS</td>\
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>\
</tr>\
<tr>\
<td><b>Timezone</b></td>\
<td>z or zz</td>\
<td>EST CST ... MST PST</td>\
</tr>\
<tr>\
<td></td>\
<td>Z</td>\
<td>-07:00 -06:00 ... +06:00 +07:00</td>\
</tr>\
<tr>\
<td></td>\
<td>ZZ</td>\
<td>-0700 -0600 ... +0600 +0700</td>\
</tr>\
<tr>\
<td><b>Unix Timestamp</b></td>\
<td>X</td>\
<td>1360013296</td>\
</tr>\
<tr>\
<td><b>Unix Millisecond Timestamp</b></td>\
<td>x</td>\
<td>1360013296123</td>\
</tr>\
</tbody>\
</table>",
FORMAT_EXAMPLES: `Format string tokens:
<table class="table table-striped table-hover table-condensed table-bordered" style="font-family: sans-serif">
<thead>
<tr>
<th>Category</th>
<th>Token</th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr>
<td><b>Month</b></td>
<td>M</td>
<td>1 2 ... 11 12</td>
</tr>
<tr>
<td></td>
<td>Mo</td>
<td>1st 2nd ... 11th 12th</td>
</tr>
<tr>
<td></td>
<td>MM</td>
<td>01 02 ... 11 12</td>
</tr>
<tr>
<td></td>
<td>MMM</td>
<td>Jan Feb ... Nov Dec</td>
</tr>
<tr>
<td></td>
<td>MMMM</td>
<td>January February ... November December</td>
</tr>
<tr>
<td><b>Quarter</b></td>
<td>Q</td>
<td>1 2 3 4</td>
</tr>
<tr>
<td><b>Day of Month</b></td>
<td>D</td>
<td>1 2 ... 30 31</td>
</tr>
<tr>
<td></td>
<td>Do</td>
<td>1st 2nd ... 30th 31st</td>
</tr>
<tr>
<td></td>
<td>DD</td>
<td>01 02 ... 30 31</td>
</tr>
<tr>
<td><b>Day of Year</b></td>
<td>DDD</td>
<td>1 2 ... 364 365</td>
</tr>
<tr>
<td></td>
<td>DDDo</td>
<td>1st 2nd ... 364th 365th</td>
</tr>
<tr>
<td></td>
<td>DDDD</td>
<td>001 002 ... 364 365</td>
</tr>
<tr>
<td><b>Day of Week</b></td>
<td>d</td>
<td>0 1 ... 5 6</td>
</tr>
<tr>
<td></td>
<td>do</td>
<td>0th 1st ... 5th 6th</td>
</tr>
<tr>
<td></td>
<td>dd</td>
<td>Su Mo ... Fr Sa</td>
</tr>
<tr>
<td></td>
<td>ddd</td>
<td>Sun Mon ... Fri Sat</td>
</tr>
<tr>
<td></td>
<td>dddd</td>
<td>Sunday Monday ... Friday Saturday</td>
</tr>
<tr>
<td><b>Day of Week (Locale)</b></td>
<td>e</td>
<td>0 1 ... 5 6</td>
</tr>
<tr>
<td><b>Day of Week (ISO)</b></td>
<td>E</td>
<td>1 2 ... 6 7</td>
</tr>
<tr>
<td><b>Week of Year</b></td>
<td>w</td>
<td>1 2 ... 52 53</td>
</tr>
<tr>
<td></td>
<td>wo</td>
<td>1st 2nd ... 52nd 53rd</td>
</tr>
<tr>
<td></td>
<td>ww</td>
<td>01 02 ... 52 53</td>
</tr>
<tr>
<td><b>Week of Year (ISO)</b></td>
<td>W</td>
<td>1 2 ... 52 53</td>
</tr>
<tr>
<td></td>
<td>Wo</td>
<td>1st 2nd ... 52nd 53rd</td>
</tr>
<tr>
<td></td>
<td>WW</td>
<td>01 02 ... 52 53</td>
</tr>
<tr>
<td><b>Year</b></td>
<td>YY</td>
<td>70 71 ... 29 30</td>
</tr>
<tr>
<td></td>
<td>YYYY</td>
<td>1970 1971 ... 2029 2030</td>
</tr>
<tr>
<td><b>Week Year</b></td>
<td>gg</td>
<td>70 71 ... 29 30</td>
</tr>
<tr>
<td></td>
<td>gggg</td>
<td>1970 1971 ... 2029 2030</td>
</tr>
<tr>
<td><b>Week Year (ISO)</b></td>
<td>GG</td>
<td>70 71 ... 29 30</td>
</tr>
<tr>
<td></td>
<td>GGGG</td>
<td>1970 1971 ... 2029 2030</td>
</tr>
<tr>
<td><b>AM/PM</b></td>
<td>A</td>
<td>AM PM</td>
</tr>
<tr>
<td></td>
<td>a</td>
<td>am pm</td>
</tr>
<tr>
<td><b>Hour</b></td>
<td>H</td>
<td>0 1 ... 22 23</td>
</tr>
<tr>
<td></td>
<td>HH</td>
<td>00 01 ... 22 23</td>
</tr>
<tr>
<td></td>
<td>h</td>
<td>1 2 ... 11 12</td>
</tr>
<tr>
<td></td>
<td>hh</td>
<td>01 02 ... 11 12</td>
</tr>
<tr>
<td><b>Minute</b></td>
<td>m</td>
<td>0 1 ... 58 59</td>
</tr>
<tr>
<td></td>
<td>mm</td>
<td>00 01 ... 58 59</td>
</tr>
<tr>
<td><b>Second</b></td>
<td>s</td>
<td>0 1 ... 58 59</td>
</tr>
<tr>
<td></td>
<td>ss</td>
<td>00 01 ... 58 59</td>
</tr>
<tr>
<td><b>Fractional Second</b></td>
<td>S</td>
<td>0 1 ... 8 9</td>
</tr>
<tr>
<td></td>
<td>SS</td>
<td>00 01 ... 98 99</td>
</tr>
<tr>
<td></td>
<td>SSS</td>
<td>000 001 ... 998 999</td>
</tr>
<tr>
<td></td>
<td>SSSS ... SSSSSSSSS</td>
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>
</tr>
<tr>
<td><b>Timezone</b></td>
<td>z or zz</td>
<td>EST CST ... MST PST</td>
</tr>
<tr>
<td></td>
<td>Z</td>
<td>-07:00 -06:00 ... +06:00 +07:00</td>
</tr>
<tr>
<td></td>
<td>ZZ</td>
<td>-0700 -0600 ... +0600 +0700</td>
</tr>
<tr>
<td><b>Unix Timestamp</b></td>
<td>X</td>
<td>1360013296</td>
</tr>
<tr>
<td><b>Unix Millisecond Timestamp</b></td>
<td>x</td>
<td>1360013296123</td>
</tr>
</tbody>
</table>`,
};

View File

@@ -225,26 +225,26 @@ const HTML = {
cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")";
// Generate output
return "<div id='colorpicker' style='display: inline-block'></div>" +
"Hex: " + hex + "\n" +
"RGB: " + rgb + "\n" +
"RGBA: " + rgba + "\n" +
"HSL: " + hsl + "\n" +
"HSLA: " + hsla + "\n" +
"CMYK: " + cmyk +
"<script>\
$('#colorpicker').colorpicker({\
format: 'rgba',\
color: '" + rgba + "',\
container: true,\
inline: true,\
}).on('changeColor', function(e) {\
var color = e.color.toRGB();\
document.getElementById('input-text').value = 'rgba(' +\
color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';\
window.app.autoBake();\
});\
</script>";
return `<div id="colorpicker" style="display: inline-block"></div>
Hex: ${hex}
RGB: ${rgb}
RGBA: ${rgba}
HSL: ${hsl}
HSLA: ${hsla}
CMYK: ${cmyk}
<script>
$('#colorpicker').colorpicker({
format: 'rgba',
color: '${rgba}',
container: true,
inline: true,
}).on('changeColor', function(e) {
var color = e.color.toRGB();
document.getElementById('input-text').value = 'rgba(' +
color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';
window.app.autoBake();
});
</script>`;
},

View File

@@ -294,6 +294,31 @@ const Hash = {
},
/**
* @constant
* @default
*/
SNEFRU_ROUNDS: ["8", "4", "2"],
/**
* @constant
* @default
*/
SNEFRU_SIZE: ["256", "128"],
/**
* Snefru operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSnefru: function (input, args) {
const rounds = args[0],
size = args[1];
return CryptoApi.hash(`snefru-${rounds}-${size}`, input, {}).stringify("hex");
},
/**
* @constant
* @default

View File

@@ -402,10 +402,14 @@ App.prototype.loadURIParams = function() {
// Read in input data from URI params
if (this.uriParams.input) {
this.autoBakePause = true;
try {
const inputData = Utils.fromBase64(this.uriParams.input);
this.setInput(inputData);
} catch (err) {}
} catch (err) {
} finally {
this.autoBakePause = false;
}
}
this.autoBake();

View File

@@ -1,5 +1,6 @@
import HTMLOperation from "./HTMLOperation.js";
import Sortable from "sortablejs";
import Utils from "../core/Utils.js";
/**
@@ -435,4 +436,30 @@ RecipeWaiter.prototype.opRemove = function(e) {
window.dispatchEvent(this.manager.statechange);
};
/**
* Sets register values.
*
* @param {number} opIndex
* @param {number} numPrevRegisters
* @param {string[]} registers
*/
RecipeWaiter.prototype.setRegisters = function(opIndex, numPrevRegisters, registers) {
const op = document.querySelector(`#rec-list .operation:nth-child(${opIndex + 1})`),
prevRegList = op.querySelector(".register-list");
// Remove previous div
if (prevRegList) prevRegList.remove();
let registerList = [];
for (let i = 0; i < registers.length; i++) {
registerList.push(`$R${numPrevRegisters + i} = ${Utils.escapeHtml(Utils.truncate(Utils.printable(registers[i]), 100))}`);
}
const registerListEl = `<div class="register-list">
${registerList.join("<br>")}
</div>`;
op.insertAdjacentHTML("beforeend", registerListEl);
};
export default RecipeWaiter;

View File

@@ -61,6 +61,9 @@ WorkerWaiter.prototype.handleChefMessage = function(e) {
case "optionUpdate":
this.app.options[r.data.option] = r.data.value;
break;
case "setRegisters":
this.manager.recipe.setRegisters(r.data.opIndex, r.data.numPrevRegisters, r.data.registers);
break;
case "highlightsCalculated":
this.manager.highlighter.displayHighlights(r.data.pos, r.data.direction);
break;

View File

@@ -414,6 +414,7 @@
<li><a href="#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
<li><a href="#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ">Use parts of the input as arguments to operations</a></li>
</ul>
</div>
<blockquote>

View File

@@ -124,6 +124,12 @@ button.dropdown-toggle {
background-color: var(--secondary-background-colour);
}
.register-list {
background-color: var(--fc-operation-border-colour);
font-family: var(--fixed-width-font-family);
padding: 10px;
}
.op-icon {
float: right;
margin-left: 10px;
@@ -195,3 +201,13 @@ button.dropdown-toggle {
background-color: var(--disabled-bg-colour) !important;
border-color: var(--disabled-border-colour) !important;
}
.break .register-list {
color: var(--fc-breakpoint-operation-font-colour) !important;
background-color: var(--fc-breakpoint-operation-border-colour) !important;
}
.disabled .register-list {
color: var(--disabled-font-colour) !important;
background-color: var(--disabled-border-colour) !important;
}

View File

@@ -338,6 +338,72 @@ TestRegister.addTests([
}
]
},
{
name: "Snefru 2 128",
input: "Hello, World!",
expectedOutput: "a4ad2b8848580511d0884fb4233a7e7a",
recipeConfig: [
{
"op": "Snefru",
"args": ["2", "128"]
}
]
},
{
name: "Snefru 4 128",
input: "Hello, World!",
expectedOutput: "d154eae2c9ffbcd2e1bdaf0b84736126",
recipeConfig: [
{
"op": "Snefru",
"args": ["4", "128"]
}
]
},
{
name: "Snefru 8 128",
input: "Hello, World!",
expectedOutput: "6f3d55b69557abb0a3c4e9de9d29ba5d",
recipeConfig: [
{
"op": "Snefru",
"args": ["8", "128"]
}
]
},
{
name: "Snefru 2 256",
input: "Hello, World!",
expectedOutput: "65736daba648de28ef4c4a316b4684584ecf9f22ddb5c457729e6bf0f40113c4",
recipeConfig: [
{
"op": "Snefru",
"args": ["2", "256"]
}
]
},
{
name: "Snefru 4 256",
input: "Hello, World!",
expectedOutput: "71b0ea4b3e33f2e58bcc67c8a8de060b99ec0107355bbfdc18d8f65f0194ffcc",
recipeConfig: [
{
"op": "Snefru",
"args": ["4", "256"]
}
]
},
{
name: "Snefru 8 256",
input: "Hello, World!",
expectedOutput: "255cd401414c79588cf689e8d5ff0536a2cfab83fcae36e654f202b09bc4b8a7",
recipeConfig: [
{
"op": "Snefru",
"args": ["8", "256"]
}
]
},
{
name: "HMAC SHA256",
input: "Hello, World!",