functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
61 lines (60 loc) • 1.96 kB
JavaScript
/**
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
*
* https://en.wikipedia.org/wiki/HMAC
*
* @module
*
* @example
*
* ```ts
* import { vec } from '../../types/bit_vec/module.f.ts'
* import { msbUtf8 } from '../../text/module.f.ts'
* import { sha256 } from '../sha2/module.f.ts'
*
* const r = hmac(sha256)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'))
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
* ```
*/
import { length } from "../../types/bit_vec/module.f.js";
import { empty, msb, vec, vec8 } from "../../types/bit_vec/module.f.js";
import { flip } from "../../types/function/module.f.js";
import { repeat } from "../../types/monoid/module.f.js";
import { computeSync } from "../sha2/module.f.js";
const { concat } = msb;
/**
* Outer padding.
*/
const oPad = vec8(0x5cn);
/**
* Inner padding.
*/
const iPad = vec8(0x36n);
/**
* Repeats a vector to create a padded block of the desired length.
*/
const padRepeat = repeat({ identity: empty, operation: concat });
/**
* Generates an HMAC (Hash-based Message Authentication Code) using the specified SHA-2 hash function.
*
* @param sha2 - The SHA-2 hash function implementation to use.
* @returns - A function that takes a key and returns another function
* that takes a message and computes the HMAC.
*/
export const hmac = (sha2) => {
const { blockLength } = sha2;
const p = flip(padRepeat)(blockLength >> 3n);
const ip = p(iPad);
const op = p(oPad);
const c = computeSync(sha2);
const vbl = vec(blockLength);
const xor = (a) => (b) => vbl(a ^ b);
return k => m => {
const k1 = length(k) > blockLength ? c([k]) : k;
const k2 = concat(k1)(vec(blockLength - length(k1))(0n));
const xk2 = xor(k2);
const f = (p, msg) => c([xk2(p), msg]);
const m1 = f(ip, m);
return f(op, m1);
};
};