@li0ard/magma
Version:
Magma cipher implementation in pure TypeScript
44 lines (43 loc) • 1.87 kB
JavaScript
import { xor } from "@li0ard/gost3413/dist/utils";
import { BLOCK_SIZE, keySequences, Magma, sboxes } from "../";
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) => {
return [
(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) => {
return 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
]);
};
let cipher = new Magma(Magma.reverseKey(key), sbox);
cipher.regenerateRoundKeys(keySequences.MAC);
let 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);
const encrypter = (buf) => cipher.encryptBlock(buf);
return mac_(encrypter, BLOCK_SIZE, data);
};