Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba12ad8e7c | ||
|
|
249af2ded1 | ||
|
|
7403666a11 | ||
|
|
1cc8b150f3 | ||
|
|
faa25ee662 | ||
|
|
aa981ccd4a | ||
|
|
04378c1f91 | ||
|
|
53179a158e | ||
|
|
7ecde9fd2a | ||
|
|
320f79fe0d | ||
|
|
157346b055 | ||
|
|
f84c11f63d | ||
|
|
2bcfb693b7 | ||
|
|
897d2bef6e | ||
|
|
0a3d219ad5 | ||
|
|
ba0dfe91c3 | ||
|
|
bf4e62b4b7 | ||
|
|
d77f8ba747 | ||
|
|
78d35ecec3 | ||
|
|
c79bf5caaf | ||
|
|
66cbc6908a | ||
|
|
c6b79cd1c6 | ||
|
|
d23b88e2b8 | ||
|
|
3ac2ed20d2 |
@@ -13,6 +13,12 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
## Details
|
||||
|
||||
### [9.54.0] - 2022-11-25
|
||||
- Added 'Rabbit' operation [@mikecat] | [#1450]
|
||||
|
||||
### [9.53.0] - 2022-11-25
|
||||
- Added 'AES Key Wrap' and 'AES Key Unwrap' operations [@mikecat] | [#1456]
|
||||
|
||||
### [9.52.0] - 2022-11-25
|
||||
- Added 'ChaCha' operation [@joostrijneveld] | [#1466]
|
||||
|
||||
@@ -333,6 +339,8 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
|
||||
|
||||
[9.54.0]: https://github.com/gchq/CyberChef/releases/tag/v9.54.0
|
||||
[9.53.0]: https://github.com/gchq/CyberChef/releases/tag/v9.53.0
|
||||
[9.52.0]: https://github.com/gchq/CyberChef/releases/tag/v9.52.0
|
||||
[9.51.0]: https://github.com/gchq/CyberChef/releases/tag/v9.51.0
|
||||
[9.50.0]: https://github.com/gchq/CyberChef/releases/tag/v9.50.0
|
||||
@@ -584,4 +592,6 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#1472]: https://github.com/gchq/CyberChef/pull/1472
|
||||
[#1457]: https://github.com/gchq/CyberChef/pull/1457
|
||||
[#1466]: https://github.com/gchq/CyberChef/pull/1466
|
||||
[#1456]: https://github.com/gchq/CyberChef/pull/1456
|
||||
[#1450]: https://github.com/gchq/CyberChef/pull/1450
|
||||
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.52.0",
|
||||
"version": "9.54.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cyberchef",
|
||||
"version": "9.52.0",
|
||||
"version": "9.54.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.52.0",
|
||||
"version": "9.54.0",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
|
||||
@@ -27,6 +27,7 @@ class Ingredient {
|
||||
this.toggleValues = [];
|
||||
this.target = null;
|
||||
this.defaultIndex = 0;
|
||||
this.maxLength = null;
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
this.step = 1;
|
||||
@@ -53,6 +54,7 @@ class Ingredient {
|
||||
this.toggleValues = ingredientConfig.toggleValues;
|
||||
this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null;
|
||||
this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0;
|
||||
this.maxLength = ingredientConfig.maxLength || null;
|
||||
this.min = ingredientConfig.min;
|
||||
this.max = ingredientConfig.max;
|
||||
this.step = ingredientConfig.step;
|
||||
|
||||
@@ -184,6 +184,7 @@ class Operation {
|
||||
if (ing.disabled) conf.disabled = ing.disabled;
|
||||
if (ing.target) conf.target = ing.target;
|
||||
if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex;
|
||||
if (ing.maxLength) conf.maxLength = ing.maxLength;
|
||||
if (typeof ing.min === "number") conf.min = ing.min;
|
||||
if (typeof ing.max === "number") conf.max = ing.max;
|
||||
if (ing.step) conf.step = ing.step;
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
"AES Decrypt",
|
||||
"Blowfish Encrypt",
|
||||
"Blowfish Decrypt",
|
||||
"ChaCha",
|
||||
"DES Encrypt",
|
||||
"DES Decrypt",
|
||||
"Triple DES Encrypt",
|
||||
@@ -86,6 +85,8 @@
|
||||
"RC2 Decrypt",
|
||||
"RC4",
|
||||
"RC4 Drop",
|
||||
"ChaCha",
|
||||
"Rabbit",
|
||||
"SM4 Encrypt",
|
||||
"SM4 Decrypt",
|
||||
"ROT13",
|
||||
@@ -125,6 +126,8 @@
|
||||
"JWT Decode",
|
||||
"Citrix CTX1 Encode",
|
||||
"Citrix CTX1 Decode",
|
||||
"AES Key Wrap",
|
||||
"AES Key Unwrap",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Enigma",
|
||||
"Bombe",
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* @author mikecat
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { toHexFast } from "../lib/Hex.mjs";
|
||||
import forge from "node-forge";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
* AES Key Unwrap operation
|
||||
*/
|
||||
class AESKeyUnwrap extends Operation {
|
||||
|
||||
/**
|
||||
* AESKeyUnwrap constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "AES Key Unwrap";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Decryptor for a key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to decrypt 64-bit blocks.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key (KEK)",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "IV",
|
||||
"type": "toggleString",
|
||||
"value": "a6a6a6a6a6a6a6a6",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "Input",
|
||||
"type": "option",
|
||||
"value": ["Hex", "Raw"]
|
||||
},
|
||||
{
|
||||
"name": "Output",
|
||||
"type": "option",
|
||||
"value": ["Hex", "Raw"]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const kek = Utils.convertToByteString(args[0].string, args[0].option),
|
||||
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||
inputType = args[2],
|
||||
outputType = args[3];
|
||||
|
||||
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||
}
|
||||
if (iv.length !== 8) {
|
||||
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||
}
|
||||
const inputData = Utils.convertToByteString(input, inputType);
|
||||
if (inputData.length % 8 !== 0 || inputData.length < 24) {
|
||||
throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
|
||||
}
|
||||
|
||||
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||
cipher.start();
|
||||
cipher.update(forge.util.createBuffer(""));
|
||||
cipher.finish();
|
||||
const paddingBlock = cipher.output.getBytes();
|
||||
|
||||
const decipher = forge.cipher.createDecipher("AES-ECB", kek);
|
||||
|
||||
let A = inputData.substring(0, 8);
|
||||
const R = [];
|
||||
for (let i = 8; i < inputData.length; i += 8) {
|
||||
R.push(inputData.substring(i, i + 8));
|
||||
}
|
||||
let cntLower = R.length >>> 0;
|
||||
let cntUpper = (R.length / ((1 << 30) * 4)) >>> 0;
|
||||
cntUpper = cntUpper * 6 + ((cntLower * 6 / ((1 << 30) * 4)) >>> 0);
|
||||
cntLower = cntLower * 6 >>> 0;
|
||||
for (let j = 5; j >= 0; j--) {
|
||||
for (let i = R.length - 1; i >= 0; i--) {
|
||||
const aBuffer = Utils.strToArrayBuffer(A);
|
||||
const aView = new DataView(aBuffer);
|
||||
aView.setUint32(0, aView.getUint32(0) ^ cntUpper);
|
||||
aView.setUint32(4, aView.getUint32(4) ^ cntLower);
|
||||
A = Utils.arrayBufferToStr(aBuffer, false);
|
||||
decipher.start();
|
||||
decipher.update(forge.util.createBuffer(A + R[i] + paddingBlock));
|
||||
decipher.finish();
|
||||
const B = decipher.output.getBytes();
|
||||
A = B.substring(0, 8);
|
||||
R[i] = B.substring(8, 16);
|
||||
cntLower--;
|
||||
if (cntLower < 0) {
|
||||
cntUpper--;
|
||||
cntLower = 0xffffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (A !== iv) {
|
||||
throw new OperationError("IV mismatch");
|
||||
}
|
||||
const P = R.join("");
|
||||
|
||||
if (outputType === "Hex") {
|
||||
return toHexFast(Utils.strToArrayBuffer(P));
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default AESKeyUnwrap;
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @author mikecat
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { toHexFast } from "../lib/Hex.mjs";
|
||||
import forge from "node-forge";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
* AES Key Wrap operation
|
||||
*/
|
||||
class AESKeyWrap extends Operation {
|
||||
|
||||
/**
|
||||
* AESKeyWrap constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "AES Key Wrap";
|
||||
this.module = "Ciphers";
|
||||
this.description = "A key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.<br><br>This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to encrypt 64-bit blocks.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Key_wrap";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key (KEK)",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "IV",
|
||||
"type": "toggleString",
|
||||
"value": "a6a6a6a6a6a6a6a6",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "Input",
|
||||
"type": "option",
|
||||
"value": ["Hex", "Raw"]
|
||||
},
|
||||
{
|
||||
"name": "Output",
|
||||
"type": "option",
|
||||
"value": ["Hex", "Raw"]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const kek = Utils.convertToByteString(args[0].string, args[0].option),
|
||||
iv = Utils.convertToByteString(args[1].string, args[1].option),
|
||||
inputType = args[2],
|
||||
outputType = args[3];
|
||||
|
||||
if (kek.length !== 16 && kek.length !== 24 && kek.length !== 32) {
|
||||
throw new OperationError("KEK must be either 16, 24, or 32 bytes (currently " + kek.length + " bytes)");
|
||||
}
|
||||
if (iv.length !== 8) {
|
||||
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||
}
|
||||
const inputData = Utils.convertToByteString(input, inputType);
|
||||
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
||||
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
|
||||
}
|
||||
|
||||
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||
|
||||
let A = iv;
|
||||
const R = [];
|
||||
for (let i = 0; i < inputData.length; i += 8) {
|
||||
R.push(inputData.substring(i, i + 8));
|
||||
}
|
||||
let cntLower = 1, cntUpper = 0;
|
||||
for (let j = 0; j < 6; j++) {
|
||||
for (let i = 0; i < R.length; i++) {
|
||||
cipher.start();
|
||||
cipher.update(forge.util.createBuffer(A + R[i]));
|
||||
cipher.finish();
|
||||
const B = cipher.output.getBytes();
|
||||
const msbBuffer = Utils.strToArrayBuffer(B.substring(0, 8));
|
||||
const msbView = new DataView(msbBuffer);
|
||||
msbView.setUint32(0, msbView.getUint32(0) ^ cntUpper);
|
||||
msbView.setUint32(4, msbView.getUint32(4) ^ cntLower);
|
||||
A = Utils.arrayBufferToStr(msbBuffer, false);
|
||||
R[i] = B.substring(8, 16);
|
||||
cntLower++;
|
||||
if (cntLower > 0xffffffff) {
|
||||
cntUpper++;
|
||||
cntLower = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
const C = A + R.join("");
|
||||
|
||||
if (outputType === "Hex") {
|
||||
return toHexFast(Utils.strToArrayBuffer(C));
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default AESKeyWrap;
|
||||
@@ -7,7 +7,7 @@
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85.mjs";
|
||||
import {ALPHABET_OPTIONS} from "../lib/Base85.mjs";
|
||||
|
||||
/**
|
||||
* From Base85 operation
|
||||
@@ -37,6 +37,12 @@ class FromBase85 extends Operation {
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "All-zero group char",
|
||||
type: "binaryShortString",
|
||||
value: "z",
|
||||
maxLength: 1
|
||||
}
|
||||
];
|
||||
this.checks = [
|
||||
{
|
||||
@@ -76,8 +82,8 @@ class FromBase85 extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
||||
encoding = alphabetName(alphabet),
|
||||
removeNonAlphChars = args[1],
|
||||
allZeroGroupChar = typeof args[2] === "string" ? args[2].slice(0, 1) : "",
|
||||
result = [];
|
||||
|
||||
if (alphabet.length !== 85 ||
|
||||
@@ -85,14 +91,21 @@ class FromBase85 extends Operation {
|
||||
throw new OperationError("Alphabet must be of length 85");
|
||||
}
|
||||
|
||||
if (allZeroGroupChar && alphabet.includes(allZeroGroupChar)) {
|
||||
throw new OperationError("The all-zero group char cannot appear in the alphabet");
|
||||
}
|
||||
|
||||
// Remove delimiters if present
|
||||
const matches = input.match(/^<~(.+?)~>$/);
|
||||
if (matches !== null) input = matches[1];
|
||||
|
||||
// Remove non-alphabet characters
|
||||
if (removeNonAlphChars) {
|
||||
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||
const re = new RegExp("[^~" + allZeroGroupChar +alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
// Remove delimiters again if present (incase of non-alphabet characters in front/behind delimiters)
|
||||
const matches = input.match(/^<~(.+?)~>$/);
|
||||
if (matches !== null) input = matches[1];
|
||||
}
|
||||
|
||||
if (input.length === 0) return [];
|
||||
@@ -100,7 +113,7 @@ class FromBase85 extends Operation {
|
||||
let i = 0;
|
||||
let block, blockBytes;
|
||||
while (i < input.length) {
|
||||
if (encoding === "Standard" && input[i] === "z") {
|
||||
if (input[i] === allZeroGroupChar) {
|
||||
result.push(0, 0, 0, 0);
|
||||
i++;
|
||||
} else {
|
||||
@@ -110,7 +123,7 @@ class FromBase85 extends Operation {
|
||||
.split("")
|
||||
.map((chr, idx) => {
|
||||
const digit = alphabet.indexOf(chr);
|
||||
if (digit < 0 || digit > 84) {
|
||||
if ((digit < 0 || digit > 84) && chr !== allZeroGroupChar) {
|
||||
throw `Invalid character '${chr}' at index ${i + idx}`;
|
||||
}
|
||||
return digit;
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
* @author mikecat
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { toHexFast } from "../lib/Hex.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
* Rabbit operation
|
||||
*/
|
||||
class Rabbit extends Operation {
|
||||
|
||||
/**
|
||||
* Rabbit constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Rabbit";
|
||||
this.module = "Ciphers";
|
||||
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++";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Rabbit_(cipher)";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Key",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "IV",
|
||||
"type": "toggleString",
|
||||
"value": "",
|
||||
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
|
||||
},
|
||||
{
|
||||
"name": "Endianness",
|
||||
"type": "option",
|
||||
"value": ["Big", "Little"]
|
||||
},
|
||||
{
|
||||
"name": "Input",
|
||||
"type": "option",
|
||||
"value": ["Raw", "Hex"]
|
||||
},
|
||||
{
|
||||
"name": "Output",
|
||||
"type": "option",
|
||||
"value": ["Raw", "Hex"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const key = Utils.convertToByteArray(args[0].string, args[0].option),
|
||||
iv = Utils.convertToByteArray(args[1].string, args[1].option),
|
||||
endianness = args[2],
|
||||
inputType = args[3],
|
||||
outputType = args[4];
|
||||
|
||||
const littleEndian = endianness === "Little";
|
||||
|
||||
if (key.length !== 16) {
|
||||
throw new OperationError(`Invalid key length: ${key.length} bytes (expected: 16)`);
|
||||
}
|
||||
if (iv.length !== 0 && iv.length !== 8) {
|
||||
throw new OperationError(`Invalid IV length: ${iv.length} bytes (expected: 0 or 8)`);
|
||||
}
|
||||
|
||||
// Inner State
|
||||
const X = new Uint32Array(8), C = new Uint32Array(8);
|
||||
let b = 0;
|
||||
|
||||
// Counter System
|
||||
const A = [
|
||||
0x4d34d34d, 0xd34d34d3, 0x34d34d34, 0x4d34d34d,
|
||||
0xd34d34d3, 0x34d34d34, 0x4d34d34d, 0xd34d34d3
|
||||
];
|
||||
const counterUpdate = function() {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
const temp = C[j] + A[j] + b;
|
||||
b = (temp / ((1 << 30) * 4)) >>> 0;
|
||||
C[j] = temp;
|
||||
}
|
||||
};
|
||||
|
||||
// Next-State Function
|
||||
const g = function(u, v) {
|
||||
const uv = (u + v) >>> 0;
|
||||
const upper = uv >>> 16, lower = uv & 0xffff;
|
||||
const upperUpper = upper * upper;
|
||||
const upperLower2 = 2 * upper * lower;
|
||||
const lowerLower = lower * lower;
|
||||
const mswTemp = upperUpper + ((upperLower2 / (1 << 16)) >>> 0);
|
||||
const lswTemp = lowerLower + (upperLower2 & 0xffff) * (1 << 16);
|
||||
const msw = mswTemp + ((lswTemp / ((1 << 30) * 4)) >>> 0);
|
||||
const lsw = lswTemp >>> 0;
|
||||
return lsw ^ msw;
|
||||
};
|
||||
const leftRotate = function(value, width) {
|
||||
return (value << width) | (value >>> (32 - width));
|
||||
};
|
||||
const nextStateHelper1 = function(v0, v1, v2) {
|
||||
return v0 + leftRotate(v1, 16) + leftRotate(v2, 16);
|
||||
};
|
||||
const nextStateHelper2 = function(v0, v1, v2) {
|
||||
return v0 + leftRotate(v1, 8) + v2;
|
||||
};
|
||||
const G = new Uint32Array(8);
|
||||
const nextState = function() {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
G[j] = g(X[j], C[j]);
|
||||
}
|
||||
X[0] = nextStateHelper1(G[0], G[7], G[6]);
|
||||
X[1] = nextStateHelper2(G[1], G[0], G[7]);
|
||||
X[2] = nextStateHelper1(G[2], G[1], G[0]);
|
||||
X[3] = nextStateHelper2(G[3], G[2], G[1]);
|
||||
X[4] = nextStateHelper1(G[4], G[3], G[2]);
|
||||
X[5] = nextStateHelper2(G[5], G[4], G[3]);
|
||||
X[6] = nextStateHelper1(G[6], G[5], G[4]);
|
||||
X[7] = nextStateHelper2(G[7], G[6], G[5]);
|
||||
};
|
||||
|
||||
// Key Setup Scheme
|
||||
const K = new Uint16Array(8);
|
||||
if (littleEndian) {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
K[i] = (key[1 + 2 * i] << 8) | key[2 * i];
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
K[i] = (key[14 - 2 * i] << 8) | key[15 - 2 * i];
|
||||
}
|
||||
}
|
||||
for (let j = 0; j < 8; j++) {
|
||||
if (j % 2 === 0) {
|
||||
X[j] = (K[(j + 1) % 8] << 16) | K[j];
|
||||
C[j] = (K[(j + 4) % 8] << 16) | K[(j + 5) % 8];
|
||||
} else {
|
||||
X[j] = (K[(j + 5) % 8] << 16) | K[(j + 4) % 8];
|
||||
C[j] = (K[j] << 16) | K[(j + 1) % 8];
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < 4; i++) {
|
||||
counterUpdate();
|
||||
nextState();
|
||||
}
|
||||
for (let j = 0; j < 8; j++) {
|
||||
C[j] = C[j] ^ X[(j + 4) % 8];
|
||||
}
|
||||
|
||||
// IV Setup Scheme
|
||||
if (iv.length === 8) {
|
||||
const getIVValue = function(a, b, c, d) {
|
||||
if (littleEndian) {
|
||||
return (iv[a] << 24) | (iv[b] << 16) |
|
||||
(iv[c] << 8) | iv[d];
|
||||
} else {
|
||||
return (iv[7 - a] << 24) | (iv[7 - b] << 16) |
|
||||
(iv[7 - c] << 8) | iv[7 - d];
|
||||
}
|
||||
};
|
||||
C[0] = C[0] ^ getIVValue(3, 2, 1, 0);
|
||||
C[1] = C[1] ^ getIVValue(7, 6, 3, 2);
|
||||
C[2] = C[2] ^ getIVValue(7, 6, 5, 4);
|
||||
C[3] = C[3] ^ getIVValue(5, 4, 1, 0);
|
||||
C[4] = C[4] ^ getIVValue(3, 2, 1, 0);
|
||||
C[5] = C[5] ^ getIVValue(7, 6, 3, 2);
|
||||
C[6] = C[6] ^ getIVValue(7, 6, 5, 4);
|
||||
C[7] = C[7] ^ getIVValue(5, 4, 1, 0);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
counterUpdate();
|
||||
nextState();
|
||||
}
|
||||
}
|
||||
|
||||
// Extraction Scheme
|
||||
const S = new Uint8Array(16);
|
||||
const extract = function() {
|
||||
let pos = 0;
|
||||
const addPart = function(value) {
|
||||
S[pos++] = value >>> 8;
|
||||
S[pos++] = value & 0xff;
|
||||
};
|
||||
counterUpdate();
|
||||
nextState();
|
||||
addPart((X[6] >>> 16) ^ (X[1] & 0xffff));
|
||||
addPart((X[6] & 0xffff) ^ (X[3] >>> 16));
|
||||
addPart((X[4] >>> 16) ^ (X[7] & 0xffff));
|
||||
addPart((X[4] & 0xffff) ^ (X[1] >>> 16));
|
||||
addPart((X[2] >>> 16) ^ (X[5] & 0xffff));
|
||||
addPart((X[2] & 0xffff) ^ (X[7] >>> 16));
|
||||
addPart((X[0] >>> 16) ^ (X[3] & 0xffff));
|
||||
addPart((X[0] & 0xffff) ^ (X[5] >>> 16));
|
||||
if (littleEndian) {
|
||||
for (let i = 0, j = S.length - 1; i < j;) {
|
||||
const temp = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = temp;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const data = Utils.convertToByteString(input, inputType);
|
||||
const result = new Uint8Array(data.length);
|
||||
for (let i = 0; i <= data.length - 16; i += 16) {
|
||||
extract();
|
||||
for (let j = 0; j < 16; j++) {
|
||||
result[i + j] = data.charCodeAt(i + j) ^ S[j];
|
||||
}
|
||||
}
|
||||
if (data.length % 16 !== 0) {
|
||||
const offset = data.length - data.length % 16;
|
||||
const length = data.length - offset;
|
||||
extract();
|
||||
if (littleEndian) {
|
||||
for (let j = 0; j < length; j++) {
|
||||
result[offset + j] = data.charCodeAt(offset + j) ^ S[j];
|
||||
}
|
||||
} else {
|
||||
for (let j = 0; j < length; j++) {
|
||||
result[offset + j] = data.charCodeAt(offset + j) ^ S[16 - length + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outputType === "Hex") {
|
||||
return toHexFast(result);
|
||||
}
|
||||
return Utils.byteArrayToChars(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Rabbit;
|
||||
@@ -30,6 +30,7 @@ class HTMLIngredient {
|
||||
this.rows = config.rows || false;
|
||||
this.target = config.target;
|
||||
this.defaultIndex = config.defaultIndex || 0;
|
||||
this.maxLength = config.maxLength || null;
|
||||
this.toggleValues = config.toggleValues;
|
||||
this.ingId = this.app.nextIngId();
|
||||
this.id = "ing-" + this.ingId;
|
||||
@@ -63,7 +64,8 @@ class HTMLIngredient {
|
||||
tabindex="${this.tabIndex}"
|
||||
arg-name="${this.name}"
|
||||
value="${this.value}"
|
||||
${this.disabled ? "disabled" : ""}>
|
||||
${this.disabled ? "disabled" : ""}
|
||||
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||
</div>`;
|
||||
break;
|
||||
case "shortString":
|
||||
@@ -78,7 +80,8 @@ class HTMLIngredient {
|
||||
tabindex="${this.tabIndex}"
|
||||
arg-name="${this.name}"
|
||||
value="${this.value}"
|
||||
${this.disabled ? "disabled" : ""}>
|
||||
${this.disabled ? "disabled" : ""}
|
||||
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||
</div>`;
|
||||
break;
|
||||
case "toggleString":
|
||||
@@ -93,7 +96,8 @@ class HTMLIngredient {
|
||||
tabindex="${this.tabIndex}"
|
||||
arg-name="${this.name}"
|
||||
value="${this.value}"
|
||||
${this.disabled ? "disabled" : ""}>
|
||||
${this.disabled ? "disabled" : ""}
|
||||
${this.maxLength ? `maxlength="${this.maxLength}"` : ""}>
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${this.toggleValues[0]}</button>
|
||||
|
||||
@@ -128,6 +128,8 @@ import "./tests/NTLM.mjs";
|
||||
import "./tests/Shuffle.mjs";
|
||||
import "./tests/FletcherChecksum.mjs";
|
||||
import "./tests/CMAC.mjs";
|
||||
import "./tests/AESKeyWrap.mjs";
|
||||
import "./tests/Rabbit.mjs";
|
||||
|
||||
// Cannot test operations that use the File type yet
|
||||
// import "./tests/SplitColourChannels.mjs";
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
/**
|
||||
* @author mikecat
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 128-bit KEK",
|
||||
"input": "00112233445566778899aabbccddeeff",
|
||||
"expectedOutput": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 192-bit KEK",
|
||||
"input": "00112233445566778899aabbccddeeff",
|
||||
"expectedOutput": "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: RFC Test Vector, 128-bit data, 256-bit KEK",
|
||||
"input": "00112233445566778899aabbccddeeff",
|
||||
"expectedOutput": "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: RFC Test Vector, 192-bit data, 192-bit KEK",
|
||||
"input": "00112233445566778899aabbccddeeff0001020304050607",
|
||||
"expectedOutput": "031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: RFC Test Vector, 192-bit data, 256-bit KEK",
|
||||
"input": "00112233445566778899aabbccddeeff0001020304050607",
|
||||
"expectedOutput": "a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: RFC Test Vector, 256-bit data, 256-bit KEK",
|
||||
"input": "00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f",
|
||||
"expectedOutput": "28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 128-bit KEK",
|
||||
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 192-bit KEK",
|
||||
"input": "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d",
|
||||
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: RFC Test Vector, 128-bit data, 256-bit KEK",
|
||||
"input": "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7",
|
||||
"expectedOutput": "00112233445566778899aabbccddeeff",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: RFC Test Vector, 192-bit data, 192-bit KEK",
|
||||
"input": "031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2",
|
||||
"expectedOutput": "00112233445566778899aabbccddeeff0001020304050607",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f1011121314151617"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: RFC Test Vector, 192-bit data, 256-bit KEK",
|
||||
"input": "a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1",
|
||||
"expectedOutput": "00112233445566778899aabbccddeeff0001020304050607",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: RFC Test Vector, 256-bit data, 256-bit KEK",
|
||||
"input": "28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21",
|
||||
"expectedOutput": "00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: invalid KEK length",
|
||||
"input": "00112233445566778899aabbccddeeff",
|
||||
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00010203040506070809"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: invalid IV length",
|
||||
"input": "00112233445566778899aabbccddeeff",
|
||||
"expectedOutput": "IV must be 8 bytes (currently 6 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: input length not multiple of 8",
|
||||
"input": "00112233445566778899aabbccddeeff0102",
|
||||
"expectedOutput": "input must be 8n (n>=2) bytes (currently 18 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Wrap: input too short",
|
||||
"input": "0011223344556677",
|
||||
"expectedOutput": "input must be 8n (n>=2) bytes (currently 8 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Wrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: invalid KEK length",
|
||||
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00010203040506070809"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: invalid IV length",
|
||||
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||
"expectedOutput": "IV must be 8 bytes (currently 6 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: input length not multiple of 8",
|
||||
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5e621",
|
||||
"expectedOutput": "input must be 8n (n>=3) bytes (currently 26 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: input too short",
|
||||
"input": "1fa68b0a8112b447aef34bd8fb5a7b82",
|
||||
"expectedOutput": "input must be 8n (n>=3) bytes (currently 16 bytes)",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "AES Key Unwrap: corrupted input",
|
||||
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe6",
|
||||
"expectedOutput": "IV mismatch",
|
||||
"recipeConfig": [
|
||||
{
|
||||
"op": "AES Key Unwrap",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||
{"option": "Hex", "string": "a6a6a6a6a6a6a6a6"},
|
||||
"Hex", "Hex"
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -16,6 +16,10 @@ DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(\
|
||||
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
||||
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
||||
|
||||
const allZeroExample = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
|
||||
|
||||
const allZeroOutput = "zz!!*-'\"9eu7#RLhG$k3[W&.oNg'GVB\"(`=52*$$(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cEH9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbNG^4U^I!pHnJ:W<)KS>/9Ll%\"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TUnsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg\"GZd*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq\"ad`r;HWp";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Base85",
|
||||
@@ -45,4 +49,22 @@ TestRegister.addTests([
|
||||
"args": ["!-u", false] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "To Base85",
|
||||
input: allZeroExample,
|
||||
expectedOutput: allZeroOutput,
|
||||
recipeConfig: [
|
||||
{ "op": "To Base85",
|
||||
"args": ["!-u"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Base85",
|
||||
input: allZeroOutput,
|
||||
expectedOutput: allZeroExample,
|
||||
recipeConfig: [
|
||||
{ "op": "From Base85",
|
||||
"args": ["!-u", true, "z"] }
|
||||
]
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @author mikecat
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Rabbit: RFC Test vector, without IV 1",
|
||||
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "b15754f036a5d6ecf56b45261c4af70288e8d815c59c0c397b696c4789c68aa7f416a1c3700cd451da68d1881673d696",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: RFC Test vector, without IV 2",
|
||||
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "3d2df3c83ef627a1e97fc38487e2519cf576cd61f4405b8896bf53aa8554fc19e5547473fbdb43508ae53b20204d4c5e",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "912813292e3d36fe3bfc62f1dc51c3ac"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: RFC Test vector, without IV 3",
|
||||
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "0cb10dcda041cdac32eb5cfd02d0609b95fc9fca0f17015a7b7092114cff3ead9649e5de8bfc7f3f924147ad3a947428",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "8395741587e0c733e9e9ab01c09b0043"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: RFC Test vector, with IV 1",
|
||||
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "c6a7275ef85495d87ccd5d376705b7ed5f29a6ac04f5efd47b8f293270dc4a8d2ade822b29de6c1ee52bdb8a47bf8f66",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": "0000000000000000"},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: RFC Test vector, with IV 2",
|
||||
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "1fcd4eb9580012e2e0dccc9222017d6da75f4e10d12125017b2499ffed936f2eebc112c393e738392356bdd012029ba7",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": "c373f575c1267e59"},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: RFC Test vector, with IV 3",
|
||||
input: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
expectedOutput: "445ad8c805858dbf70b6af23a151104d96c8f27947f42c5baeae67c6acc35b039fcbfc895fa71c17313df034f01551cb",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": "a6eb561ad2f41727"},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: generated stream should be XORed with the input",
|
||||
input: "cedda96c054e3ddd93da7ed05e2a4b7bdb0c00fe214f03502e2708b2c2bfc77aa2311b0b9af8aa78d119f92b26db0a6b",
|
||||
expectedOutput: "7f8afd9c33ebeb3166b13bf64260bc7953e4d8ebe4d30f69554e64f54b794ddd5627bac8eaf47e290b7128a330a8dcfd",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: least significant bits should be used for the last block",
|
||||
input: "0000000000000000",
|
||||
expectedOutput: "f56b45261c4af702",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: invalid key length",
|
||||
input: "",
|
||||
expectedOutput: "Invalid key length: 8 bytes (expected: 16)",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "0000000000000000"},
|
||||
{"option": "Hex", "string": ""},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Rabbit: invalid IV length",
|
||||
input: "",
|
||||
expectedOutput: "Invalid IV length: 4 bytes (expected: 0 or 8)",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "00000000000000000000000000000000"},
|
||||
{"option": "Hex", "string": "00000000"},
|
||||
"Big", "Hex", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
// this testcase is taken from the first example on Crypto++ Wiki
|
||||
// https://www.cryptopp.com/wiki/Rabbit
|
||||
name: "Rabbit: little-endian mode (Crypto++ compatible)",
|
||||
input: "Rabbit stream cipher test",
|
||||
expectedOutput: "1ae2d4edcf9b6063b00fd6fda0b223aded157e77031cf0440b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Rabbit",
|
||||
"args": [
|
||||
{"option": "Hex", "string": "23c2731e8b5469fd8dabb5bc592a0f3a"},
|
||||
{"option": "Hex", "string": "712906405ef03201"},
|
||||
"Little", "Raw", "Hex"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
]);
|
||||
Reference in New Issue
Block a user