cyberchef 9.52.1 → 9.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/src/core/config/Categories.json +4 -1
- package/src/core/config/OperationConfig.json +155 -0
- package/src/core/config/modules/Ciphers.mjs +6 -0
- package/src/core/operations/AESKeyUnwrap.mjs +128 -0
- package/src/core/operations/AESKeyWrap.mjs +115 -0
- package/src/core/operations/Rabbit.mjs +247 -0
- package/src/core/operations/index.mjs +6 -0
- package/src/node/index.mjs +15 -0
- package/tests/operations/index.mjs +2 -0
- package/tests/operations/tests/AESKeyWrap.mjs +324 -0
- package/tests/operations/tests/Rabbit.mjs +177 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author mikecat
|
|
3
|
+
* @copyright Crown Copyright 2022
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Operation from "../Operation.mjs";
|
|
8
|
+
import Utils from "../Utils.mjs";
|
|
9
|
+
import { toHexFast } from "../lib/Hex.mjs";
|
|
10
|
+
import OperationError from "../errors/OperationError.mjs";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Rabbit operation
|
|
14
|
+
*/
|
|
15
|
+
class Rabbit extends Operation {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rabbit constructor
|
|
19
|
+
*/
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
|
|
23
|
+
this.name = "Rabbit";
|
|
24
|
+
this.module = "Ciphers";
|
|
25
|
+
this.description = "Rabbit is a high-speed stream cipher introduced in 2003 and defined in RFC 4503.<br><br>The cipher uses a 128-bit key and an optional 64-bit initialization vector (IV).<br><br>big-endian: based on RFC4503 and RFC3447<br>little-endian: compatible with Crypto++";
|
|
26
|
+
this.infoURL = "https://wikipedia.org/wiki/Rabbit_(cipher)";
|
|
27
|
+
this.inputType = "string";
|
|
28
|
+
this.outputType = "string";
|
|
29
|
+
this.args = [
|
|
30
|
+
{
|
|
31
|
+
"name": "Key",
|
|
32
|
+
"type": "toggleString",
|
|
33
|
+
"value": "",
|
|
34
|
+
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "IV",
|
|
38
|
+
"type": "toggleString",
|
|
39
|
+
"value": "",
|
|
40
|
+
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "Endianness",
|
|
44
|
+
"type": "option",
|
|
45
|
+
"value": ["Big", "Little"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "Input",
|
|
49
|
+
"type": "option",
|
|
50
|
+
"value": ["Raw", "Hex"]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "Output",
|
|
54
|
+
"type": "option",
|
|
55
|
+
"value": ["Raw", "Hex"]
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} input
|
|
62
|
+
* @param {Object[]} args
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
65
|
+
run(input, args) {
|
|
66
|
+
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
|
67
|
+
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
|
68
|
+
endianness = args[2],
|
|
69
|
+
inputType = args[3],
|
|
70
|
+
outputType = args[4];
|
|
71
|
+
|
|
72
|
+
const littleEndian = endianness === "Little";
|
|
73
|
+
|
|
74
|
+
if (key.length !== 16) {
|
|
75
|
+
throw new OperationError(`Invalid key length: ${key.length} bytes (expected: 16)`);
|
|
76
|
+
}
|
|
77
|
+
if (iv.length !== 0 && iv.length !== 8) {
|
|
78
|
+
throw new OperationError(`Invalid IV length: ${iv.length} bytes (expected: 0 or 8)`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Inner State
|
|
82
|
+
const X = new Uint32Array(8), C = new Uint32Array(8);
|
|
83
|
+
let b = 0;
|
|
84
|
+
|
|
85
|
+
// Counter System
|
|
86
|
+
const A = [
|
|
87
|
+
0x4d34d34d, 0xd34d34d3, 0x34d34d34, 0x4d34d34d,
|
|
88
|
+
0xd34d34d3, 0x34d34d34, 0x4d34d34d, 0xd34d34d3
|
|
89
|
+
];
|
|
90
|
+
const counterUpdate = function() {
|
|
91
|
+
for (let j = 0; j < 8; j++) {
|
|
92
|
+
const temp = C[j] + A[j] + b;
|
|
93
|
+
b = (temp / ((1 << 30) * 4)) >>> 0;
|
|
94
|
+
C[j] = temp;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Next-State Function
|
|
99
|
+
const g = function(u, v) {
|
|
100
|
+
const uv = (u + v) >>> 0;
|
|
101
|
+
const upper = uv >>> 16, lower = uv & 0xffff;
|
|
102
|
+
const upperUpper = upper * upper;
|
|
103
|
+
const upperLower2 = 2 * upper * lower;
|
|
104
|
+
const lowerLower = lower * lower;
|
|
105
|
+
const mswTemp = upperUpper + ((upperLower2 / (1 << 16)) >>> 0);
|
|
106
|
+
const lswTemp = lowerLower + (upperLower2 & 0xffff) * (1 << 16);
|
|
107
|
+
const msw = mswTemp + ((lswTemp / ((1 << 30) * 4)) >>> 0);
|
|
108
|
+
const lsw = lswTemp >>> 0;
|
|
109
|
+
return lsw ^ msw;
|
|
110
|
+
};
|
|
111
|
+
const leftRotate = function(value, width) {
|
|
112
|
+
return (value << width) | (value >>> (32 - width));
|
|
113
|
+
};
|
|
114
|
+
const nextStateHelper1 = function(v0, v1, v2) {
|
|
115
|
+
return v0 + leftRotate(v1, 16) + leftRotate(v2, 16);
|
|
116
|
+
};
|
|
117
|
+
const nextStateHelper2 = function(v0, v1, v2) {
|
|
118
|
+
return v0 + leftRotate(v1, 8) + v2;
|
|
119
|
+
};
|
|
120
|
+
const G = new Uint32Array(8);
|
|
121
|
+
const nextState = function() {
|
|
122
|
+
for (let j = 0; j < 8; j++) {
|
|
123
|
+
G[j] = g(X[j], C[j]);
|
|
124
|
+
}
|
|
125
|
+
X[0] = nextStateHelper1(G[0], G[7], G[6]);
|
|
126
|
+
X[1] = nextStateHelper2(G[1], G[0], G[7]);
|
|
127
|
+
X[2] = nextStateHelper1(G[2], G[1], G[0]);
|
|
128
|
+
X[3] = nextStateHelper2(G[3], G[2], G[1]);
|
|
129
|
+
X[4] = nextStateHelper1(G[4], G[3], G[2]);
|
|
130
|
+
X[5] = nextStateHelper2(G[5], G[4], G[3]);
|
|
131
|
+
X[6] = nextStateHelper1(G[6], G[5], G[4]);
|
|
132
|
+
X[7] = nextStateHelper2(G[7], G[6], G[5]);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Key Setup Scheme
|
|
136
|
+
const K = new Uint16Array(8);
|
|
137
|
+
if (littleEndian) {
|
|
138
|
+
for (let i = 0; i < 8; i++) {
|
|
139
|
+
K[i] = (key[1 + 2 * i] << 8) | key[2 * i];
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
for (let i = 0; i < 8; i++) {
|
|
143
|
+
K[i] = (key[14 - 2 * i] << 8) | key[15 - 2 * i];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (let j = 0; j < 8; j++) {
|
|
147
|
+
if (j % 2 === 0) {
|
|
148
|
+
X[j] = (K[(j + 1) % 8] << 16) | K[j];
|
|
149
|
+
C[j] = (K[(j + 4) % 8] << 16) | K[(j + 5) % 8];
|
|
150
|
+
} else {
|
|
151
|
+
X[j] = (K[(j + 5) % 8] << 16) | K[(j + 4) % 8];
|
|
152
|
+
C[j] = (K[j] << 16) | K[(j + 1) % 8];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (let i = 0; i < 4; i++) {
|
|
156
|
+
counterUpdate();
|
|
157
|
+
nextState();
|
|
158
|
+
}
|
|
159
|
+
for (let j = 0; j < 8; j++) {
|
|
160
|
+
C[j] = C[j] ^ X[(j + 4) % 8];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// IV Setup Scheme
|
|
164
|
+
if (iv.length === 8) {
|
|
165
|
+
const getIVValue = function(a, b, c, d) {
|
|
166
|
+
if (littleEndian) {
|
|
167
|
+
return (iv[a] << 24) | (iv[b] << 16) |
|
|
168
|
+
(iv[c] << 8) | iv[d];
|
|
169
|
+
} else {
|
|
170
|
+
return (iv[7 - a] << 24) | (iv[7 - b] << 16) |
|
|
171
|
+
(iv[7 - c] << 8) | iv[7 - d];
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
C[0] = C[0] ^ getIVValue(3, 2, 1, 0);
|
|
175
|
+
C[1] = C[1] ^ getIVValue(7, 6, 3, 2);
|
|
176
|
+
C[2] = C[2] ^ getIVValue(7, 6, 5, 4);
|
|
177
|
+
C[3] = C[3] ^ getIVValue(5, 4, 1, 0);
|
|
178
|
+
C[4] = C[4] ^ getIVValue(3, 2, 1, 0);
|
|
179
|
+
C[5] = C[5] ^ getIVValue(7, 6, 3, 2);
|
|
180
|
+
C[6] = C[6] ^ getIVValue(7, 6, 5, 4);
|
|
181
|
+
C[7] = C[7] ^ getIVValue(5, 4, 1, 0);
|
|
182
|
+
for (let i = 0; i < 4; i++) {
|
|
183
|
+
counterUpdate();
|
|
184
|
+
nextState();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Extraction Scheme
|
|
189
|
+
const S = new Uint8Array(16);
|
|
190
|
+
const extract = function() {
|
|
191
|
+
let pos = 0;
|
|
192
|
+
const addPart = function(value) {
|
|
193
|
+
S[pos++] = value >>> 8;
|
|
194
|
+
S[pos++] = value & 0xff;
|
|
195
|
+
};
|
|
196
|
+
counterUpdate();
|
|
197
|
+
nextState();
|
|
198
|
+
addPart((X[6] >>> 16) ^ (X[1] & 0xffff));
|
|
199
|
+
addPart((X[6] & 0xffff) ^ (X[3] >>> 16));
|
|
200
|
+
addPart((X[4] >>> 16) ^ (X[7] & 0xffff));
|
|
201
|
+
addPart((X[4] & 0xffff) ^ (X[1] >>> 16));
|
|
202
|
+
addPart((X[2] >>> 16) ^ (X[5] & 0xffff));
|
|
203
|
+
addPart((X[2] & 0xffff) ^ (X[7] >>> 16));
|
|
204
|
+
addPart((X[0] >>> 16) ^ (X[3] & 0xffff));
|
|
205
|
+
addPart((X[0] & 0xffff) ^ (X[5] >>> 16));
|
|
206
|
+
if (littleEndian) {
|
|
207
|
+
for (let i = 0, j = S.length - 1; i < j;) {
|
|
208
|
+
const temp = S[i];
|
|
209
|
+
S[i] = S[j];
|
|
210
|
+
S[j] = temp;
|
|
211
|
+
i++;
|
|
212
|
+
j--;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const data = Utils.convertToByteString(input, inputType);
|
|
218
|
+
const result = new Uint8Array(data.length);
|
|
219
|
+
for (let i = 0; i <= data.length - 16; i += 16) {
|
|
220
|
+
extract();
|
|
221
|
+
for (let j = 0; j < 16; j++) {
|
|
222
|
+
result[i + j] = data.charCodeAt(i + j) ^ S[j];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (data.length % 16 !== 0) {
|
|
226
|
+
const offset = data.length - data.length % 16;
|
|
227
|
+
const length = data.length - offset;
|
|
228
|
+
extract();
|
|
229
|
+
if (littleEndian) {
|
|
230
|
+
for (let j = 0; j < length; j++) {
|
|
231
|
+
result[offset + j] = data.charCodeAt(offset + j) ^ S[j];
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
for (let j = 0; j < length; j++) {
|
|
235
|
+
result[offset + j] = data.charCodeAt(offset + j) ^ S[16 - length + j];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (outputType === "Hex") {
|
|
240
|
+
return toHexFast(result);
|
|
241
|
+
}
|
|
242
|
+
return Utils.byteArrayToChars(result);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export default Rabbit;
|
|
@@ -10,6 +10,8 @@ import A1Z26CipherEncode from "./A1Z26CipherEncode.mjs";
|
|
|
10
10
|
import ADD from "./ADD.mjs";
|
|
11
11
|
import AESDecrypt from "./AESDecrypt.mjs";
|
|
12
12
|
import AESEncrypt from "./AESEncrypt.mjs";
|
|
13
|
+
import AESKeyUnwrap from "./AESKeyUnwrap.mjs";
|
|
14
|
+
import AESKeyWrap from "./AESKeyWrap.mjs";
|
|
13
15
|
import AND from "./AND.mjs";
|
|
14
16
|
import AddLineNumbers from "./AddLineNumbers.mjs";
|
|
15
17
|
import AddTextToImage from "./AddTextToImage.mjs";
|
|
@@ -272,6 +274,7 @@ import RSADecrypt from "./RSADecrypt.mjs";
|
|
|
272
274
|
import RSAEncrypt from "./RSAEncrypt.mjs";
|
|
273
275
|
import RSASign from "./RSASign.mjs";
|
|
274
276
|
import RSAVerify from "./RSAVerify.mjs";
|
|
277
|
+
import Rabbit from "./Rabbit.mjs";
|
|
275
278
|
import RailFenceCipherDecode from "./RailFenceCipherDecode.mjs";
|
|
276
279
|
import RailFenceCipherEncode from "./RailFenceCipherEncode.mjs";
|
|
277
280
|
import RandomizeColourPalette from "./RandomizeColourPalette.mjs";
|
|
@@ -404,6 +407,8 @@ export {
|
|
|
404
407
|
ADD,
|
|
405
408
|
AESDecrypt,
|
|
406
409
|
AESEncrypt,
|
|
410
|
+
AESKeyUnwrap,
|
|
411
|
+
AESKeyWrap,
|
|
407
412
|
AND,
|
|
408
413
|
AddLineNumbers,
|
|
409
414
|
AddTextToImage,
|
|
@@ -666,6 +671,7 @@ export {
|
|
|
666
671
|
RSAEncrypt,
|
|
667
672
|
RSASign,
|
|
668
673
|
RSAVerify,
|
|
674
|
+
Rabbit,
|
|
669
675
|
RailFenceCipherDecode,
|
|
670
676
|
RailFenceCipherEncode,
|
|
671
677
|
RandomizeColourPalette,
|
package/src/node/index.mjs
CHANGED
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
ADD as core_ADD,
|
|
21
21
|
AESDecrypt as core_AESDecrypt,
|
|
22
22
|
AESEncrypt as core_AESEncrypt,
|
|
23
|
+
AESKeyUnwrap as core_AESKeyUnwrap,
|
|
24
|
+
AESKeyWrap as core_AESKeyWrap,
|
|
23
25
|
AND as core_AND,
|
|
24
26
|
AddLineNumbers as core_AddLineNumbers,
|
|
25
27
|
AddTextToImage as core_AddTextToImage,
|
|
@@ -273,6 +275,7 @@ import {
|
|
|
273
275
|
RSAEncrypt as core_RSAEncrypt,
|
|
274
276
|
RSASign as core_RSASign,
|
|
275
277
|
RSAVerify as core_RSAVerify,
|
|
278
|
+
Rabbit as core_Rabbit,
|
|
276
279
|
RailFenceCipherDecode as core_RailFenceCipherDecode,
|
|
277
280
|
RailFenceCipherEncode as core_RailFenceCipherEncode,
|
|
278
281
|
RandomizeColourPalette as core_RandomizeColourPalette,
|
|
@@ -414,6 +417,8 @@ function generateChef() {
|
|
|
414
417
|
"ADD": _wrap(core_ADD),
|
|
415
418
|
"AESDecrypt": _wrap(core_AESDecrypt),
|
|
416
419
|
"AESEncrypt": _wrap(core_AESEncrypt),
|
|
420
|
+
"AESKeyUnwrap": _wrap(core_AESKeyUnwrap),
|
|
421
|
+
"AESKeyWrap": _wrap(core_AESKeyWrap),
|
|
417
422
|
"AND": _wrap(core_AND),
|
|
418
423
|
"addLineNumbers": _wrap(core_AddLineNumbers),
|
|
419
424
|
"addTextToImage": _wrap(core_AddTextToImage),
|
|
@@ -667,6 +672,7 @@ function generateChef() {
|
|
|
667
672
|
"RSAEncrypt": _wrap(core_RSAEncrypt),
|
|
668
673
|
"RSASign": _wrap(core_RSASign),
|
|
669
674
|
"RSAVerify": _wrap(core_RSAVerify),
|
|
675
|
+
"rabbit": _wrap(core_Rabbit),
|
|
670
676
|
"railFenceCipherDecode": _wrap(core_RailFenceCipherDecode),
|
|
671
677
|
"railFenceCipherEncode": _wrap(core_RailFenceCipherEncode),
|
|
672
678
|
"randomizeColourPalette": _wrap(core_RandomizeColourPalette),
|
|
@@ -816,6 +822,8 @@ const A1Z26CipherEncode = chef.A1Z26CipherEncode;
|
|
|
816
822
|
const ADD = chef.ADD;
|
|
817
823
|
const AESDecrypt = chef.AESDecrypt;
|
|
818
824
|
const AESEncrypt = chef.AESEncrypt;
|
|
825
|
+
const AESKeyUnwrap = chef.AESKeyUnwrap;
|
|
826
|
+
const AESKeyWrap = chef.AESKeyWrap;
|
|
819
827
|
const AND = chef.AND;
|
|
820
828
|
const addLineNumbers = chef.addLineNumbers;
|
|
821
829
|
const addTextToImage = chef.addTextToImage;
|
|
@@ -1078,6 +1086,7 @@ const RSADecrypt = chef.RSADecrypt;
|
|
|
1078
1086
|
const RSAEncrypt = chef.RSAEncrypt;
|
|
1079
1087
|
const RSASign = chef.RSASign;
|
|
1080
1088
|
const RSAVerify = chef.RSAVerify;
|
|
1089
|
+
const rabbit = chef.rabbit;
|
|
1081
1090
|
const railFenceCipherDecode = chef.railFenceCipherDecode;
|
|
1082
1091
|
const railFenceCipherEncode = chef.railFenceCipherEncode;
|
|
1083
1092
|
const randomizeColourPalette = chef.randomizeColourPalette;
|
|
@@ -1212,6 +1221,8 @@ const operations = [
|
|
|
1212
1221
|
ADD,
|
|
1213
1222
|
AESDecrypt,
|
|
1214
1223
|
AESEncrypt,
|
|
1224
|
+
AESKeyUnwrap,
|
|
1225
|
+
AESKeyWrap,
|
|
1215
1226
|
AND,
|
|
1216
1227
|
addLineNumbers,
|
|
1217
1228
|
addTextToImage,
|
|
@@ -1474,6 +1485,7 @@ const operations = [
|
|
|
1474
1485
|
RSAEncrypt,
|
|
1475
1486
|
RSASign,
|
|
1476
1487
|
RSAVerify,
|
|
1488
|
+
rabbit,
|
|
1477
1489
|
railFenceCipherDecode,
|
|
1478
1490
|
railFenceCipherEncode,
|
|
1479
1491
|
randomizeColourPalette,
|
|
@@ -1612,6 +1624,8 @@ export {
|
|
|
1612
1624
|
ADD,
|
|
1613
1625
|
AESDecrypt,
|
|
1614
1626
|
AESEncrypt,
|
|
1627
|
+
AESKeyUnwrap,
|
|
1628
|
+
AESKeyWrap,
|
|
1615
1629
|
AND,
|
|
1616
1630
|
addLineNumbers,
|
|
1617
1631
|
addTextToImage,
|
|
@@ -1874,6 +1888,7 @@ export {
|
|
|
1874
1888
|
RSAEncrypt,
|
|
1875
1889
|
RSASign,
|
|
1876
1890
|
RSAVerify,
|
|
1891
|
+
rabbit,
|
|
1877
1892
|
railFenceCipherDecode,
|
|
1878
1893
|
railFenceCipherEncode,
|
|
1879
1894
|
randomizeColourPalette,
|
|
@@ -128,6 +128,8 @@ import "./tests/NTLM.mjs";
|
|
|
128
128
|
import "./tests/Shuffle.mjs";
|
|
129
129
|
import "./tests/FletcherChecksum.mjs";
|
|
130
130
|
import "./tests/CMAC.mjs";
|
|
131
|
+
import "./tests/AESKeyWrap.mjs";
|
|
132
|
+
import "./tests/Rabbit.mjs";
|
|
131
133
|
|
|
132
134
|
// Cannot test operations that use the File type yet
|
|
133
135
|
// import "./tests/SplitColourChannels.mjs";
|