@li0ard/kupyna
Version:
Kupyna (DSTU 7564:2014) hash function in pure TypeScript
50 lines (49 loc) • 1.54 kB
JavaScript
import { dpad } from "../const";
import { uint64sToBytes } from "../utils";
/** Abstract class for Kupyna KMAC */
export class KupynaKMAC {
key;
outputLen;
blockLen;
threshold;
h;
ik;
len;
constructor(hash, kpad, key) {
this.key = key;
this.len = 0n;
this.h = hash();
this.outputLen = this.h.outputLen;
this.blockLen = this.h.blockLen;
if (key.length != this.h.outputLen)
throw new Error("Invalid key length");
this.h.update(key);
this.h.update(kpad);
this.ik = new Uint8Array(key.length);
for (let i = 0; i < key.length; i++)
this.ik[i] = ~key[i] & 0xFF;
this.threshold = this.blockLen - 12;
}
/** Update hash buffer */
update(data) {
this.len += BigInt(data.length);
this.h.update(data);
return this;
}
/** Finalize hash computation and return result as Uint8Array */
digest() { return this.clone().final(); }
final() {
let n = this.len;
let pad_size;
if (n < BigInt(this.threshold))
pad_size = (BigInt(this.threshold) - 1n) - n;
else
pad_size = (BigInt(this.blockLen) - 1n) - ((n - BigInt(this.threshold)) % BigInt(this.blockLen));
n *= 8n;
this.h.update(dpad.slice(0, Number(pad_size + 1n)));
this.h.update(uint64sToBytes(new BigUint64Array([n])));
this.h.update(dpad.slice(16, 20));
this.h.update(this.ik);
return this.h.digest();
}
}