UNPKG

@hpke/common

Version:

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

234 lines (233 loc) 8.82 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; 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 = new Uint8Array([72, 80, 75, 69, 45, 118, 49]); 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(); if (salt.byteLength === 0) { salt = new ArrayBuffer(this.hashSize); } if (salt.byteLength !== this.hashSize) { throw new errors_js_1.InvalidParamError("The salt length must be the same as the hashSize"); } const key = await this._api.importKey("raw", salt, this.algHash, false, [ "sign", ]); return await this._api.sign("HMAC", key, ikm); } async expand(prk, info, len) { await this._setup(); const key = await this._api.importKey("raw", prk, this.algHash, false, [ "sign", ]); const okm = new ArrayBuffer(len); const p = new Uint8Array(okm); let prev = consts_js_1.EMPTY; const mid = new Uint8Array(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 < p.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 (p.length - cur >= prev.length) { p.set(prev, cur); cur += prev.length; } else { p.set(prev.slice(0, p.length - cur), cur); cur += p.length - cur; } } return okm; } async extractAndExpand(salt, ikm, info, len) { await this._setup(); const baseKey = await this._api.importKey("raw", ikm, "HKDF", false, ["deriveBits"]); return await this._api.deriveBits({ name: "HKDF", hash: this.algHash.hash, salt: salt, info: info, }, baseKey, len * 8); } async labeledExtract(salt, label, ikm) { return await this.extract(salt, this.buildLabeledIkm(label, ikm).buffer); } async labeledExpand(prk, label, info, len) { return await this.expand(prk, this.buildLabeledInfo(label, info, len).buffer, 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; });