@hpke/common
Version:
A Hybrid Public Key Encryption (HPKE) internal-use common module for @hpke family modules.
145 lines (144 loc) • 5.45 kB
JavaScript
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "../utils/noble.js", "./hash.js"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hmac = exports._HMAC = void 0;
// deno-lint-ignore-file no-explicit-any
/**
* This file is based on noble-hashes (https://github.com/paulmillr/noble-hashes).
*
* noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com)
*
* The original file is located at:
* https://github.com/paulmillr/noble-hashes/blob/2e0c00e1aa134082ba1380bf3afb8b1641f60fed/src/hmac.ts
*/
/**
* HMAC: RFC2104 message authentication code.
* @module
*/
const noble_js_1 = require("../utils/noble.js");
const hash_js_1 = require("./hash.js");
class _HMAC {
constructor(hash, key) {
Object.defineProperty(this, "oHash", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "iHash", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "blockLen", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "outputLen", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "finished", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "destroyed", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
(0, hash_js_1.ahash)(hash);
(0, noble_js_1.abytes)(key, undefined, "key");
this.iHash = hash.create();
if (typeof this.iHash.update !== "function") {
throw new Error("Expected instance of class which extends utils.Hash");
}
this.blockLen = this.iHash.blockLen;
this.outputLen = this.iHash.outputLen;
const blockLen = this.blockLen;
const pad = new Uint8Array(blockLen);
// blockLen can be bigger than outputLen
pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
for (let i = 0; i < pad.length; i++)
pad[i] ^= 0x36;
this.iHash.update(pad);
// By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
this.oHash = hash.create();
// Undo internal XOR && apply outer XOR
for (let i = 0; i < pad.length; i++)
pad[i] ^= 0x36 ^ 0x5c;
this.oHash.update(pad);
(0, noble_js_1.clean)(pad);
}
update(buf) {
(0, noble_js_1.aexists)(this);
this.iHash.update(buf);
return this;
}
digestInto(out) {
(0, noble_js_1.aexists)(this);
(0, noble_js_1.abytes)(out, this.outputLen, "output");
this.finished = true;
this.iHash.digestInto(out);
this.oHash.update(out);
this.oHash.digestInto(out);
this.destroy();
}
digest() {
const out = new Uint8Array(this.oHash.outputLen);
this.digestInto(out);
return out;
}
_cloneInto(to) {
// Create new instance without calling constructor since key already in state and we don't know it.
to ||= Object.create(Object.getPrototypeOf(this), {});
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
to = to;
to.finished = finished;
to.destroyed = destroyed;
to.blockLen = blockLen;
to.outputLen = outputLen;
to.oHash = oHash._cloneInto(to.oHash);
to.iHash = iHash._cloneInto(to.iHash);
return to;
}
clone() {
return this._cloneInto();
}
destroy() {
this.destroyed = true;
this.oHash.destroy();
this.iHash.destroy();
}
}
exports._HMAC = _HMAC;
/**
* HMAC: RFC2104 message authentication code.
* @param hash - function that would be used e.g. sha256
* @param key - message key
* @param message - message data
* @example
* import { hmac } from '@noble/hashes/hmac';
* import { sha256 } from '@noble/hashes/sha2';
* const mac1 = hmac(sha256, 'key', 'message');
*/
const hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
exports.hmac = hmac;
exports.hmac.create = (hash, key) => new _HMAC(hash, key);
});