UNPKG

@hpke/common

Version:

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

192 lines (191 loc) 7.83 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", "../../kdfs/hkdf.js", "../../interfaces/dhkemPrimitives.js", "../../utils/misc.js", "../../xCryptoKey.js"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.XCurveDhkemPrimitives = void 0; const consts_js_1 = require("../../consts.js"); const errors_js_1 = require("../../errors.js"); const hkdf_js_1 = require("../../kdfs/hkdf.js"); const dhkemPrimitives_js_1 = require("../../interfaces/dhkemPrimitives.js"); const misc_js_1 = require("../../utils/misc.js"); const xCryptoKey_js_1 = require("../../xCryptoKey.js"); /** * Base DhkemPrimitives implementation for Montgomery curves (X25519/X448). * * Subclasses pass curve-specific parameters (algorithm name, key size, curve) * and optionally add extra methods (e.g., raw derive for X25519). */ class XCurveDhkemPrimitives { constructor(algName, keySize, curve, hkdf) { Object.defineProperty(this, "_algName", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_curve", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_hkdf", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_nPk", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_nSk", { enumerable: true, configurable: true, writable: true, value: void 0 }); this._algName = algName; this._nPk = keySize; this._nSk = keySize; this._curve = curve; this._hkdf = hkdf; } serializePublicKey(key) { try { return Promise.resolve(key.key.buffer); } catch (e) { return Promise.reject(new errors_js_1.SerializeError(e)); } } async deserializePublicKey(key) { try { return await this._importRawKey((0, hkdf_js_1.toArrayBuffer)(key), true); } catch (e) { throw new errors_js_1.DeserializeError(e); } } serializePrivateKey(key) { try { return Promise.resolve(key.key.buffer); } catch (e) { return Promise.reject(new errors_js_1.SerializeError(e)); } } async deserializePrivateKey(key) { try { return await this._importRawKey((0, hkdf_js_1.toArrayBuffer)(key), false); } catch (e) { throw new errors_js_1.DeserializeError(e); } } async importKey(format, key, isPublic) { try { if (format === "raw") { return await this._importRawKey(key, isPublic); } // jwk if (key instanceof ArrayBuffer) { throw new Error("Invalid jwk key format"); } return await this._importJWK(key, isPublic); } catch (e) { throw new errors_js_1.DeserializeError(e); } } async generateKeyPair() { try { const rawSk = await this._curve.utils.randomSecretKey(); const sk = new xCryptoKey_js_1.XCryptoKey(this._algName, rawSk, "private", dhkemPrimitives_js_1.KEM_USAGES); const pk = await this.derivePublicKey(sk); return { publicKey: pk, privateKey: sk }; } catch (e) { throw new errors_js_1.NotSupportedError(e); } } async deriveKeyPair(ikm) { try { const rawIkm = (0, hkdf_js_1.toArrayBuffer)(ikm); const dkpPrk = await this._hkdf.labeledExtract(consts_js_1.EMPTY.buffer, dhkemPrimitives_js_1.LABEL_DKP_PRK, new Uint8Array(rawIkm)); const rawSk = await this._hkdf.labeledExpand(dkpPrk, dhkemPrimitives_js_1.LABEL_SK, consts_js_1.EMPTY, this._nSk); const sk = new xCryptoKey_js_1.XCryptoKey(this._algName, new Uint8Array(rawSk), "private", dhkemPrimitives_js_1.KEM_USAGES); return { privateKey: sk, publicKey: await this.derivePublicKey(sk), }; } catch (e) { throw new errors_js_1.DeriveKeyPairError(e); } } derivePublicKey(key) { try { const pk = this._curve.getPublicKey(key.key); return Promise.resolve(new xCryptoKey_js_1.XCryptoKey(this._algName, pk, "public")); } catch (e) { return Promise.reject(new errors_js_1.DeserializeError(e)); } } dh(sk, pk) { try { return Promise.resolve(this._curve.getSharedSecret(sk.key, pk.key).buffer); } catch (e) { return Promise.reject(new errors_js_1.SerializeError(e)); } } _importRawKey(key, isPublic) { return new Promise((resolve, reject) => { if (isPublic && key.byteLength !== this._nPk) { reject(new Error("Invalid length of the key")); } if (!isPublic && key.byteLength !== this._nSk) { reject(new Error("Invalid length of the key")); } resolve(new xCryptoKey_js_1.XCryptoKey(this._algName, new Uint8Array(key), isPublic ? "public" : "private", isPublic ? [] : dhkemPrimitives_js_1.KEM_USAGES)); }); } _importJWK(key, isPublic) { return new Promise((resolve, reject) => { if (key.kty !== "OKP") { reject(new Error(`Invalid kty: ${key.kty}`)); } if (key.crv !== this._algName) { reject(new Error(`Invalid crv: ${key.crv}`)); } if (isPublic) { if (typeof key.d !== "undefined") { reject(new Error("Invalid key: `d` should not be set")); } if (typeof key.x !== "string") { reject(new Error("Invalid key: `x` not found")); } resolve(new xCryptoKey_js_1.XCryptoKey(this._algName, (0, misc_js_1.base64UrlToBytes)(key.x), "public")); } else { if (typeof key.d !== "string") { reject(new Error("Invalid key: `d` not found")); } resolve(new xCryptoKey_js_1.XCryptoKey(this._algName, (0, misc_js_1.base64UrlToBytes)(key.d), "private", dhkemPrimitives_js_1.KEM_USAGES)); } }); } } exports.XCurveDhkemPrimitives = XCurveDhkemPrimitives; });