UNPKG

@hpke/common

Version:

A Hybrid Public Key Encryption (HPKE) internal-use common module for @hpke family modules.

260 lines (259 loc) 9.67 kB
(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", "../consts.js", "../errors.js", "../identifiers.js", "../algorithm.js"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HkdfSha512Native = exports.HkdfSha384Native = exports.HkdfSha256Native = exports.HkdfNative = void 0; exports.toUint8Array = toUint8Array; exports.toArrayBuffer = toArrayBuffer; const consts_js_1 = require("../consts.js"); const errors_js_1 = require("../errors.js"); const identifiers_js_1 = require("../identifiers.js"); const algorithm_js_1 = require("../algorithm.js"); // b"HPKE-v1" const HPKE_VERSION = /* @__PURE__ */ new Uint8Array([ 72, 80, 75, 69, 45, 118, 49, ]); function toUint8Array(input) { return new Uint8Array(toArrayBuffer(input)); } function toArrayBuffer(input) { if (input instanceof ArrayBuffer) { return input; } if (ArrayBuffer.isView(input)) { return new Uint8Array(input.buffer, input.byteOffset, input.byteLength) .slice().buffer; } return new Uint8Array(input).slice().buffer; } class HkdfNative extends algorithm_js_1.NativeAlgorithm { constructor() { super(); Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: identifiers_js_1.KdfId.HkdfSha256 }); Object.defineProperty(this, "hashSize", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "_suiteId", { enumerable: true, configurable: true, writable: true, value: consts_js_1.EMPTY }); Object.defineProperty(this, "algHash", { enumerable: true, configurable: true, writable: true, value: { name: "HMAC", hash: "SHA-256", length: 256, } }); } init(suiteId) { this._suiteId = suiteId; } buildLabeledIkm(label, ikm) { this._checkInit(); const ret = new Uint8Array(7 + this._suiteId.byteLength + label.byteLength + ikm.byteLength); ret.set(HPKE_VERSION, 0); ret.set(this._suiteId, 7); ret.set(label, 7 + this._suiteId.byteLength); ret.set(ikm, 7 + this._suiteId.byteLength + label.byteLength); return ret; } buildLabeledInfo(label, info, len) { this._checkInit(); const ret = new Uint8Array(9 + this._suiteId.byteLength + label.byteLength + info.byteLength); ret.set(new Uint8Array([0, len]), 0); ret.set(HPKE_VERSION, 2); ret.set(this._suiteId, 9); ret.set(label, 9 + this._suiteId.byteLength); ret.set(info, 9 + this._suiteId.byteLength + label.byteLength); return ret; } async extract(salt, ikm) { await this._setup(); const saltBuf = salt.byteLength === 0 ? new ArrayBuffer(this.hashSize) : toArrayBuffer(salt); if (saltBuf.byteLength !== this.hashSize) { throw new errors_js_1.InvalidParamError("The salt length must be the same as the hashSize"); } const ikmBuf = toArrayBuffer(ikm); const key = await this._api.importKey("raw", saltBuf, this.algHash, false, [ "sign", ]); return await this._api.sign("HMAC", key, ikmBuf); } async expand(prk, info, len) { await this._setup(); const prkBuf = toArrayBuffer(prk); const key = await this._api.importKey("raw", prkBuf, this.algHash, false, [ "sign", ]); const okm = new ArrayBuffer(len); const okmBytes = new Uint8Array(okm); let prev = consts_js_1.EMPTY; const mid = toUint8Array(info); const tail = new Uint8Array(1); if (len > 255 * this.hashSize) { throw new Error("Entropy limit reached"); } const tmp = new Uint8Array(this.hashSize + mid.length + 1); for (let i = 1, cur = 0; cur < okmBytes.length; i++) { tail[0] = i; tmp.set(prev, 0); tmp.set(mid, prev.length); tmp.set(tail, prev.length + mid.length); prev = new Uint8Array(await this._api.sign("HMAC", key, tmp.slice(0, prev.length + mid.length + 1))); if (okmBytes.length - cur >= prev.length) { okmBytes.set(prev, cur); cur += prev.length; } else { okmBytes.set(prev.slice(0, okmBytes.length - cur), cur); cur += okmBytes.length - cur; } } return okm; } async extractAndExpand(salt, ikm, info, len) { await this._setup(); const ikmBuf = toArrayBuffer(ikm); const baseKey = await this._api.importKey("raw", ikmBuf, "HKDF", false, ["deriveBits"]); return await this._api.deriveBits({ name: "HKDF", hash: this.algHash.hash, salt: toArrayBuffer(salt), info: toArrayBuffer(info), }, baseKey, len * 8); } async labeledExtract(salt, label, ikm) { return await this.extract(salt, this.buildLabeledIkm(label, ikm)); } async labeledExpand(prk, label, info, len) { return await this.expand(prk, this.buildLabeledInfo(label, info, len), len); } _checkInit() { if (this._suiteId === consts_js_1.EMPTY) { throw new Error("Not initialized. Call init()"); } } } exports.HkdfNative = HkdfNative; class HkdfSha256Native extends HkdfNative { constructor() { super(...arguments); /** KdfId.HkdfSha256 (0x0001) */ Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: identifiers_js_1.KdfId.HkdfSha256 }); /** 32 */ Object.defineProperty(this, "hashSize", { enumerable: true, configurable: true, writable: true, value: 32 }); /** The parameters for Web Cryptography API */ Object.defineProperty(this, "algHash", { enumerable: true, configurable: true, writable: true, value: { name: "HMAC", hash: "SHA-256", length: 256, } }); } } exports.HkdfSha256Native = HkdfSha256Native; class HkdfSha384Native extends HkdfNative { constructor() { super(...arguments); /** KdfId.HkdfSha384 (0x0002) */ Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: identifiers_js_1.KdfId.HkdfSha384 }); /** 48 */ Object.defineProperty(this, "hashSize", { enumerable: true, configurable: true, writable: true, value: 48 }); /** The parameters for Web Cryptography API */ Object.defineProperty(this, "algHash", { enumerable: true, configurable: true, writable: true, value: { name: "HMAC", hash: "SHA-384", length: 384, } }); } } exports.HkdfSha384Native = HkdfSha384Native; class HkdfSha512Native extends HkdfNative { constructor() { super(...arguments); /** KdfId.HkdfSha512 (0x0003) */ Object.defineProperty(this, "id", { enumerable: true, configurable: true, writable: true, value: identifiers_js_1.KdfId.HkdfSha512 }); /** 64 */ Object.defineProperty(this, "hashSize", { enumerable: true, configurable: true, writable: true, value: 64 }); /** The parameters for Web Cryptography API */ Object.defineProperty(this, "algHash", { enumerable: true, configurable: true, writable: true, value: { name: "HMAC", hash: "SHA-512", length: 512, } }); } } exports.HkdfSha512Native = HkdfSha512Native; });