@li0ard/magma
Version:
Magma cipher implementation in pure TypeScript
38 lines (37 loc) • 1.77 kB
JavaScript
import { xor } from "@li0ard/gost3413/dist/utils.js";
import { BLOCK_SIZE, keySequences, Magma, sboxes } from "../index.js";
import { mac as mac_, pad1 } from "@li0ard/gost3413";
/**
* Compute MAC with Magma cipher (GOST 28147-89)
* @param key Encryption key
* @param data Input data
* @param iv Initialization vector
* @param sbox Optional substitution box, defaults to `ID_GOST_28147_89_CRYPTO_PRO_A_PARAM_SET`
*/
export const mac_legacy = (key, data, iv = new Uint8Array(BLOCK_SIZE), sbox = sboxes.ID_GOST_28147_89_CRYPTO_PRO_A_PARAM_SET) => {
const split = (data) => [
(data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24) >>> 0,
(data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24) >>> 0
];
const join = (ns) => new Uint8Array([
(ns[1] >> 0) & 0xFF, (ns[1] >> 8) & 0xFF, (ns[1] >> 16) & 0xFF, (ns[1] >> 24) & 0xFF,
(ns[0] >> 0) & 0xFF, (ns[0] >> 8) & 0xFF, (ns[0] >> 16) & 0xFF, (ns[0] >> 24) & 0xFF
]);
const cipher = new Magma(Magma.reverseKey(key), sbox);
cipher.regenerateRoundKeys(keySequences.MAC);
const paddedData = pad1(data, BLOCK_SIZE);
let prev = split(iv).reverse();
for (let i = 0; i < paddedData.length; i += BLOCK_SIZE)
prev = split(Magma.reverseChunks(cipher.proceedBlock(Magma.reverseChunks(xor(paddedData.slice(i, i + BLOCK_SIZE), join(prev))), keySequences.MAC)));
return join(prev);
};
/**
* Compute MAC with Magma cipher
* @param key Encryption key
* @param data Input data
* @param sbox Optional substitution box, defaults to `ID_TC26_GOST_28147_PARAM_Z`
*/
export const mac = (key, data, sbox = sboxes.ID_TC26_GOST_28147_PARAM_Z) => {
const cipher = new Magma(key, sbox);
return mac_(cipher.encryptBlock.bind(cipher), BLOCK_SIZE, data);
};