This commit is contained in:
n1474335 2022-11-25 12:41:41 +00:00
commit 0fb3743b6d
4 changed files with 459 additions and 0 deletions

View File

@ -368,6 +368,7 @@
"Compare SSDEEP hashes",
"Compare CTPH hashes",
"HMAC",
"CMAC",
"Bcrypt",
"Bcrypt compare",
"Bcrypt parse",

View File

@ -0,0 +1,143 @@
/**
* @author mikecat
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import forge from "node-forge";
import { toHexFast } from "../lib/Hex.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* CMAC operation
*/
class CMAC extends Operation {
/**
* CMAC constructor
*/
constructor() {
super();
this.name = "CMAC";
this.module = "Crypto";
this.description = "CMAC is a block-cipher based message authentication code algorithm.<br><br>RFC4493 defines AES-CMAC that uses AES encryption with a 128-bit key.<br>NIST SP 800-38B suggests usages of AES with other key lengths and Triple DES.";
this.infoURL = "https://wikipedia.org/wiki/CMAC";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Encryption algorithm",
"type": "option",
"value": ["AES", "Triple DES"]
}
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const key = Utils.convertToByteString(args[0].string, args[0].option);
const info = (function() {
switch (args[1]) {
case "AES":
if (key.length !== 16 && key.length !== 24 && key.length !== 32) {
throw new OperationError("the key for AES must be either 16, 24, or 32 bytes (currently " + key.length + " bytes)");
}
return {
"algorithm": "AES-ECB",
"key": key,
"blockSize": 16,
"Rb": new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87]),
};
case "Triple DES":
if (key.length !== 16 && key.length !== 24) {
throw new OperationError("the key for Triple DES must be 16 or 24 bytes (currently " + key.length + " bytes)");
}
return {
"algorithm": "3DES-ECB",
"key": key.length === 16 ? key + key.substring(0, 8) : key,
"blockSize": 8,
"Rb": new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0x1b]),
};
default:
throw new OperationError("undefined encryption algorithm");
}
})();
const xor = function(a, b, out) {
if (!out) out = new Uint8Array(a.length);
for (let i = 0; i < a.length; i++) {
out[i] = a[i] ^ b[i];
}
return out;
};
const leftShift1 = function(a) {
const out = new Uint8Array(a.length);
let carry = 0;
for (let i = a.length - 1; i >= 0; i--) {
out[i] = (a[i] << 1) | carry;
carry = a[i] >> 7;
}
return out;
};
const cipher = forge.cipher.createCipher(info.algorithm, info.key);
const encrypt = function(a, out) {
if (!out) out = new Uint8Array(a.length);
cipher.start();
cipher.update(forge.util.createBuffer(a));
cipher.finish();
const cipherText = cipher.output.getBytes();
for (let i = 0; i < a.length; i++) {
out[i] = cipherText.charCodeAt(i);
}
return out;
};
const L = encrypt(new Uint8Array(info.blockSize));
const K1 = leftShift1(L);
if (L[0] & 0x80) xor(K1, info.Rb, K1);
const K2 = leftShift1(K1);
if (K1[0] & 0x80) xor(K2, info.Rb, K2);
const n = Math.ceil(input.byteLength / info.blockSize);
const lastBlock = (function() {
if (n === 0) {
const data = new Uint8Array(K2);
data[0] ^= 0x80;
return data;
}
const inputLast = new Uint8Array(input, info.blockSize * (n - 1));
if (inputLast.length === info.blockSize) {
return xor(inputLast, K1, inputLast);
} else {
const data = new Uint8Array(info.blockSize);
data.set(inputLast, 0);
data[inputLast.length] = 0x80;
return xor(data, K2, data);
}
})();
const X = new Uint8Array(info.blockSize);
const Y = new Uint8Array(info.blockSize);
for (let i = 0; i < n - 1; i++) {
xor(X, new Uint8Array(input, info.blockSize * i, info.blockSize), Y);
encrypt(Y, X);
}
xor(lastBlock, X, Y);
const T = encrypt(Y);
return toHexFast(T);
}
}
export default CMAC;

View File

@ -126,6 +126,7 @@ import "./tests/LZString.mjs";
import "./tests/NTLM.mjs";
import "./tests/Shuffle.mjs";
import "./tests/FletcherChecksum.mjs";
import "./tests/CMAC.mjs";
// Cannot test operations that use the File type yet
// import "./tests/SplitColourChannels.mjs";

View File

@ -0,0 +1,314 @@
/**
* @author mikecat
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
// values in "NIST's CSRC" testcases are taken from here:
// https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
TestRegister.addTests([
{
"name": "CMAC-AES128 NIST's CSRC Example #1",
"input": "",
"expectedOutput": "bb1d6929e95937287fa37d129b756746",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
},
]
},
{
"name": "CMAC-AES128 NIST's CSRC Example #2",
"input": "6bc1bee22e409f96e93d7e117393172a",
"expectedOutput": "070a16b46b4d4144f79bdd9dd04a287c",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
},
]
},
{
"name": "CMAC-AES128 NIST's CSRC Example #3",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
"expectedOutput": "7d85449ea6ea19c823a7bf78837dfade",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
},
]
},
{
"name": "CMAC-AES128 NIST's CSRC Example #4",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
"expectedOutput": "51f0bebf7e3b9d92fc49741779363cfe",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "2b7e151628aed2a6abf7158809cf4f3c"}, "AES"]
},
]
},
{
"name": "CMAC-AES192 NIST's CSRC Example #1",
"input": "",
"expectedOutput": "d17ddf46adaacde531cac483de7a9367",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
},
]
},
{
"name": "CMAC-AES192 NIST's CSRC Example #2",
"input": "6bc1bee22e409f96e93d7e117393172a",
"expectedOutput": "9e99a7bf31e710900662f65e617c5184",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
},
]
},
{
"name": "CMAC-AES192 NIST's CSRC Example #3",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
"expectedOutput": "3d75c194ed96070444a9fa7ec740ecf8",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
},
]
},
{
"name": "CMAC-AES192 NIST's CSRC Example #4",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
"expectedOutput": "a1d5df0eed790f794d77589659f39a11",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"}, "AES"]
},
]
},
{
"name": "CMAC-AES256 NIST's CSRC Example #1",
"input": "",
"expectedOutput": "028962f61b7bf89efc6b551f4667d983",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
},
]
},
{
"name": "CMAC-AES256 NIST's CSRC Example #2",
"input": "6bc1bee22e409f96e93d7e117393172a",
"expectedOutput": "28a7023f452e8f82bd4bf28d8c37c35c",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
},
]
},
{
"name": "CMAC-AES256 NIST's CSRC Example #3",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
"expectedOutput": "156727dc0878944a023c1fe03bad6d93",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
},
]
},
{
"name": "CMAC-AES256 NIST's CSRC Example #4",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
"expectedOutput": "e1992190549f6ed5696a2c056c315410",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"}, "AES"]
},
]
},
{
"name": "CMAC-TDES (1) NIST's CSRC Sample #1",
"input": "",
"expectedOutput": "7db0d37df936c550",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (1) NIST's CSRC Sample #2",
"input": "6bc1bee22e409f96e93d7e117393172a",
"expectedOutput": "30239cf1f52e6609",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (1) NIST's CSRC Sample #3",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
"expectedOutput": "6c9f3ee4923f6be2",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (1) NIST's CSRC Sample #4",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
"expectedOutput": "99429bd0bf7904e5",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef01456789abcdef0123"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (2) NIST's CSRC Sample #1",
"input": "",
"expectedOutput": "79ce52a7f786a960",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (2) NIST's CSRC Sample #2",
"input": "6bc1bee22e409f96e93d7e117393172a",
"expectedOutput": "cc18a0b79af2413b",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (2) NIST's CSRC Sample #3",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a57",
"expectedOutput": "c06d377ecd101969",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
},
]
},
{
"name": "CMAC-TDES (2) NIST's CSRC Sample #4",
"input": "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
"expectedOutput": "9cd33580f9b64dfb",
"recipeConfig": [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "0123456789abcdef23456789abcdef010123456789abcdef"}, "Triple DES"]
},
]
},
{
"name": "CMAC-AES: invalid key length",
"input": "",
"expectedOutput": "the key for AES must be either 16, 24, or 32 bytes (currently 20 bytes)",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "00112233445566778899aabbccddeeff01234567"}, "AES"]
},
]
},
{
"name": "CMAC-TDES: invalid key length",
"input": "",
"expectedOutput": "the key for Triple DES must be 16 or 24 bytes (currently 20 bytes)",
"recipeConfig": [
{
"op": "CMAC",
"args": [{"option": "Hex", "string": "00112233445566778899aabbccddeeff01234567"}, "Triple DES"]
},
]
},
]);