mirror of
https://github.com/gchq/CyberChef.git
synced 2025-06-14 10:14:53 -04:00
Merge 25dcab0a52
into c57556f49f
This commit is contained in:
commit
7a027e776e
8 changed files with 449 additions and 80 deletions
|
@ -155,6 +155,8 @@
|
||||||
"Citrix CTX1 Decode",
|
"Citrix CTX1 Decode",
|
||||||
"AES Key Wrap",
|
"AES Key Wrap",
|
||||||
"AES Key Unwrap",
|
"AES Key Unwrap",
|
||||||
|
"AES Key Wrap With Padding",
|
||||||
|
"AES Key Unwrap With Padding",
|
||||||
"Pseudo-Random Number Generator",
|
"Pseudo-Random Number Generator",
|
||||||
"Enigma",
|
"Enigma",
|
||||||
"Bombe",
|
"Bombe",
|
||||||
|
|
99
src/core/lib/AESKeyWrap.mjs
Normal file
99
src/core/lib/AESKeyWrap.mjs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
* AES Key Wrap/Unwrap defined in RFC 3394
|
||||||
|
*
|
||||||
|
* @author aosterhage [aaron.osterhage@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Wrap algorithm defined in RFC 3394.
|
||||||
|
*
|
||||||
|
* @param {string} plaintext
|
||||||
|
* @param {string} kek
|
||||||
|
* @param {string} iv
|
||||||
|
* @returns {string} ciphertext
|
||||||
|
*/
|
||||||
|
export function aesKeyWrap(plaintext, kek, iv) {
|
||||||
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
|
||||||
|
let A = iv;
|
||||||
|
const R = [];
|
||||||
|
for (let i = 0; i < plaintext.length; i += 8) {
|
||||||
|
R.push(plaintext.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return A + R.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Unwrap algorithm defined in RFC 3394.
|
||||||
|
*
|
||||||
|
* @param {string} ciphertext
|
||||||
|
* @param {string} kek
|
||||||
|
* @returns {[string, string]} [plaintext, iv]
|
||||||
|
*/
|
||||||
|
export function aesKeyUnwrap(ciphertext, kek) {
|
||||||
|
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 = ciphertext.substring(0, 8);
|
||||||
|
const R = [];
|
||||||
|
for (let i = 8; i < ciphertext.length; i += 8) {
|
||||||
|
R.push(ciphertext.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [R.join(""), A];
|
||||||
|
}
|
|
@ -5,10 +5,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
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";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { aesKeyUnwrap } from "../lib/AESKeyWrap.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AES Key Unwrap operation
|
* AES Key Unwrap operation
|
||||||
|
@ -75,52 +75,13 @@ class AESKeyUnwrap extends Operation {
|
||||||
throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
|
throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)");
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
const [output, outputIv] = aesKeyUnwrap(inputData, kek);
|
||||||
cipher.start();
|
|
||||||
cipher.update(forge.util.createBuffer(""));
|
|
||||||
cipher.finish();
|
|
||||||
const paddingBlock = cipher.output.getBytes();
|
|
||||||
|
|
||||||
const decipher = forge.cipher.createDecipher("AES-ECB", kek);
|
if (outputIv !== iv) {
|
||||||
|
|
||||||
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");
|
throw new OperationError("IV mismatch");
|
||||||
}
|
}
|
||||||
const P = R.join("");
|
|
||||||
|
|
||||||
if (outputType === "Hex") {
|
return outputType === "Hex" ? toHexFast(Utils.strToArrayBuffer(output)) : output;
|
||||||
return toHexFast(Utils.strToArrayBuffer(P));
|
|
||||||
}
|
|
||||||
return P;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
98
src/core/operations/AESKeyUnwrapWithPadding.mjs
Normal file
98
src/core/operations/AESKeyUnwrapWithPadding.mjs
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/**
|
||||||
|
* @author aosterhage [aaron.osterhage@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import { aesKeyUnwrap } from "../lib/AESKeyWrap.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Unwrap With Padding operation
|
||||||
|
*/
|
||||||
|
class AESKeyUnwrapWithPadding extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AESKeyUnwrapWithPadding constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AES Key Unwrap With Padding";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "Decryptor for a key wrapping algorithm defined in RFC 3394 combined with a padding convention defined in RFC 5649.";
|
||||||
|
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": "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),
|
||||||
|
inputType = args[1],
|
||||||
|
outputType = args[2];
|
||||||
|
|
||||||
|
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)");
|
||||||
|
}
|
||||||
|
|
||||||
|
input = Utils.convertToByteString(input, inputType);
|
||||||
|
if (input.length % 8 !== 0 || input.length < 16) {
|
||||||
|
throw new OperationError("input must be 8n (n>=2) bytes (currently " + input.length + " bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const decipher = forge.cipher.createDecipher("AES-ECB", kek);
|
||||||
|
let output, aiv;
|
||||||
|
|
||||||
|
if (input.length === 16) {
|
||||||
|
// Special case where the unwrapped data is one 64-bit block.
|
||||||
|
decipher.start();
|
||||||
|
decipher.update(forge.util.createBuffer(input));
|
||||||
|
decipher.finish();
|
||||||
|
output = decipher.output.getBytes();
|
||||||
|
aiv = output.substring(0, 8);
|
||||||
|
output = output.substring(8, 16);
|
||||||
|
} else {
|
||||||
|
// Otherwise, follow the unwrapping process from RFC 3394 (AESKeyUnwrap operation).
|
||||||
|
[output, aiv] = aesKeyUnwrap(input, kek);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the unpadded length from the AIV (which is the MLI). Remove the padding from the output.
|
||||||
|
const unpaddedLength = Utils.byteArrayToInt(Utils.strToByteArray(aiv.substring(4, 8)), "big");
|
||||||
|
if (aiv.substring(0, 4) !== "\xa6\x59\x59\xa6" || unpaddedLength > output.length) {
|
||||||
|
throw new OperationError("invalid AIV found");
|
||||||
|
}
|
||||||
|
output = output.substring(0, unpaddedLength);
|
||||||
|
|
||||||
|
return outputType === "Hex" ? toHexFast(Utils.strToArrayBuffer(output)) : output;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AESKeyUnwrapWithPadding;
|
|
@ -5,10 +5,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
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";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import { aesKeyWrap } from "../lib/AESKeyWrap.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AES Key Wrap operation
|
* AES Key Wrap operation
|
||||||
|
@ -70,44 +70,15 @@ class AESKeyWrap extends Operation {
|
||||||
if (iv.length !== 8) {
|
if (iv.length !== 8) {
|
||||||
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)");
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputData = Utils.convertToByteString(input, inputType);
|
const inputData = Utils.convertToByteString(input, inputType);
|
||||||
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
if (inputData.length % 8 !== 0 || inputData.length < 16) {
|
||||||
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
|
throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)");
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
const output = aesKeyWrap(inputData, kek, iv);
|
||||||
|
|
||||||
let A = iv;
|
return outputType === "Hex" ? toHexFast(Utils.strToArrayBuffer(output)) : output;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
101
src/core/operations/AESKeyWrapWithPadding.mjs
Normal file
101
src/core/operations/AESKeyWrapWithPadding.mjs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/**
|
||||||
|
* @author aosterhage [aaron.osterhage@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import forge from "node-forge";
|
||||||
|
import { aesKeyWrap } from "../lib/AESKeyWrap.mjs";
|
||||||
|
import { toHexFast } from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES Key Wrap With Padding operation
|
||||||
|
*/
|
||||||
|
class AESKeyWrapWithPadding extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AESKeyWrapWithPadding constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "AES Key Wrap With Padding";
|
||||||
|
this.module = "Ciphers";
|
||||||
|
this.description = "A key wrapping algorithm defined in RFC 3394 combined with a padding convention defined in RFC 5649.<br><br>The padding convention defined in RFC 5649 eliminates the requirement that the length of the key to be wrapped be a multiple of 64 bits, allowing a key of any practical length to be wrapped.";
|
||||||
|
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": "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),
|
||||||
|
inputType = args[1],
|
||||||
|
outputType = args[2];
|
||||||
|
|
||||||
|
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)");
|
||||||
|
}
|
||||||
|
|
||||||
|
input = Utils.convertToByteString(input, inputType);
|
||||||
|
if (input.length <= 0) {
|
||||||
|
throw new OperationError("input must be > 0 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the "Alternative Initial Value" (AIV).
|
||||||
|
const aiv = "\xa6\x59\x59\xa6" + Utils.byteArrayToChars(Utils.intToByteArray(input.length, 4, "big"));;
|
||||||
|
|
||||||
|
// Pad the input as needed.
|
||||||
|
const isMultipleOf8 = (input.length % 8) === 0;
|
||||||
|
const paddedLength = input.length + (isMultipleOf8 ? 0 : (8 - (input.length % 8)));
|
||||||
|
input = input.padEnd(paddedLength, "\0");
|
||||||
|
|
||||||
|
let output;
|
||||||
|
|
||||||
|
if (paddedLength === 8) {
|
||||||
|
// Special case where the padded input is one 64-bit block.
|
||||||
|
|
||||||
|
// Get the cipher ready and disable PKCS#7 padding.
|
||||||
|
const cipher = forge.cipher.createCipher("AES-ECB", kek);
|
||||||
|
cipher.mode.pad = false;
|
||||||
|
|
||||||
|
cipher.start();
|
||||||
|
cipher.update(forge.util.createBuffer(aiv + input));
|
||||||
|
cipher.finish();
|
||||||
|
output = cipher.output.getBytes();
|
||||||
|
} else {
|
||||||
|
// Otherwise, follow the wrapping process from RFC 3394 (AESKeyWrap operation).
|
||||||
|
output = aesKeyWrap(input, kek, aiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputType === "Hex" ? toHexFast(Utils.strToArrayBuffer(output)) : output;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AESKeyWrapWithPadding;
|
|
@ -15,6 +15,7 @@ import { setLongTestFailure, logTestReport } from "../lib/utils.mjs";
|
||||||
|
|
||||||
import TestRegister from "../lib/TestRegister.mjs";
|
import TestRegister from "../lib/TestRegister.mjs";
|
||||||
import "./tests/AESKeyWrap.mjs";
|
import "./tests/AESKeyWrap.mjs";
|
||||||
|
import "./tests/AESKeyWrapWithPadding.mjs";
|
||||||
import "./tests/AlternatingCaps.mjs";
|
import "./tests/AlternatingCaps.mjs";
|
||||||
import "./tests/AvroToJSON.mjs";
|
import "./tests/AvroToJSON.mjs";
|
||||||
import "./tests/BaconCipher.mjs";
|
import "./tests/BaconCipher.mjs";
|
||||||
|
|
136
tests/operations/tests/AESKeyWrapWithPadding.mjs
Normal file
136
tests/operations/tests/AESKeyWrapWithPadding.mjs
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/**
|
||||||
|
* @author aosterhage [aaron.osterhage@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2025
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap With Padding: RFC Test Vector, 20 octets data, 192-bit KEK",
|
||||||
|
"input": "c37b7e6492584340bed12207808941155068f738",
|
||||||
|
"expectedOutput": "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap With Padding: RFC Test Vector, 7 octets data, 192-bit KEK",
|
||||||
|
"input": "466f7250617369",
|
||||||
|
"expectedOutput": "afbeb0f07dfbf5419200f2ccb50bb24f",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap With Padding: invalid KEK length",
|
||||||
|
"input": "00112233445566778899aabbccddeeff",
|
||||||
|
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00010203040506070809"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Wrap With Padding: input too short",
|
||||||
|
"input": "",
|
||||||
|
"expectedOutput": "input must be > 0 bytes",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Wrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap With Padding: RFC Test Vector, 20 octets data, 192-bit KEK",
|
||||||
|
"input": "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a",
|
||||||
|
"expectedOutput": "c37b7e6492584340bed12207808941155068f738",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap With Padding: RFC Test Vector, 7 octets data, 192-bit KEK",
|
||||||
|
"input": "afbeb0f07dfbf5419200f2ccb50bb24f",
|
||||||
|
"expectedOutput": "466f7250617369",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap With Padding: invalid KEK length",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5",
|
||||||
|
"expectedOutput": "KEK must be either 16, 24, or 32 bytes (currently 10 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "00010203040506070809"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap With Padding: input length not multiple of 8",
|
||||||
|
"input": "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5e621",
|
||||||
|
"expectedOutput": "input must be 8n (n>=2) bytes (currently 26 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "AES Key Unwrap With Padding: input too short",
|
||||||
|
"input": "1fa68b0a8112b447",
|
||||||
|
"expectedOutput": "input must be 8n (n>=2) bytes (currently 8 bytes)",
|
||||||
|
"recipeConfig": [
|
||||||
|
{
|
||||||
|
"op": "AES Key Unwrap With Padding",
|
||||||
|
"args": [
|
||||||
|
{"option": "Hex", "string": "000102030405060708090a0b0c0d0e0f"},
|
||||||
|
"Hex", "Hex"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
Loading…
Add table
Add a link
Reference in a new issue