UNPKG

@hpke/dhkem-x448

Version:

A Hybrid Public Key Encryption (HPKE) module extension for X448

198 lines (197 loc) 7.14 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", "@noble/curves/ed448", "@hpke/common"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.X448 = void 0; const ed448_1 = require("@noble/curves/ed448"); const common_1 = require("@hpke/common"); const ALG_NAME = "X448"; class X448 { constructor(hkdf) { 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._hkdf = hkdf; this._nPk = 56; this._nSk = 56; } async serializePublicKey(key) { try { return await this._serializePublicKey(key); } catch (e) { throw new common_1.SerializeError(e); } } async deserializePublicKey(key) { try { return await this._importRawKey(key, true); } catch (e) { throw new common_1.DeserializeError(e); } } async serializePrivateKey(key) { try { return await this._serializePrivateKey(key); } catch (e) { throw new common_1.SerializeError(e); } } async deserializePrivateKey(key) { try { return await this._importRawKey(key, false); } catch (e) { throw new common_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 common_1.DeserializeError(e); } } async generateKeyPair() { try { const rawSk = ed448_1.x448.utils.randomPrivateKey(); const sk = new common_1.XCryptoKey(ALG_NAME, rawSk, "private", common_1.KEM_USAGES); const pk = await this.derivePublicKey(sk); return { publicKey: pk, privateKey: sk }; } catch (e) { throw new common_1.NotSupportedError(e); } } async deriveKeyPair(ikm) { try { const dkpPrk = await this._hkdf.labeledExtract(common_1.EMPTY.buffer, common_1.LABEL_DKP_PRK, new Uint8Array(ikm)); const rawSk = await this._hkdf.labeledExpand(dkpPrk, common_1.LABEL_SK, common_1.EMPTY, this._nSk); const sk = new common_1.XCryptoKey(ALG_NAME, new Uint8Array(rawSk), "private", common_1.KEM_USAGES); return { privateKey: sk, publicKey: await this.derivePublicKey(sk), }; } catch (e) { throw new common_1.DeriveKeyPairError(e); } } async derivePublicKey(key) { try { return await this._derivePublicKey(key); } catch (e) { throw new common_1.DeserializeError(e); } } async dh(sk, pk) { try { return await this._dh(sk, pk); } catch (e) { throw new common_1.SerializeError(e); } } _serializePublicKey(k) { return new Promise((resolve) => { resolve(k.key.buffer); }); } _serializePrivateKey(k) { return new Promise((resolve) => { resolve(k.key.buffer); }); } _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 common_1.XCryptoKey(ALG_NAME, new Uint8Array(key), isPublic ? "public" : "private", isPublic ? [] : common_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 !== "X448") { 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 common_1.XCryptoKey(ALG_NAME, (0, common_1.base64UrlToBytes)(key.x), "public")); } else { if (typeof key.d !== "string") { reject(new Error("Invalid key: `d` not found")); } resolve(new common_1.XCryptoKey(ALG_NAME, (0, common_1.base64UrlToBytes)(key.d), "private", common_1.KEM_USAGES)); } }); } _derivePublicKey(k) { return new Promise((resolve, reject) => { try { const pk = ed448_1.x448.getPublicKey(k.key); resolve(new common_1.XCryptoKey(ALG_NAME, pk, "public")); } catch (e) { reject(e); } }); } _dh(sk, pk) { return new Promise((resolve, reject) => { try { resolve(ed448_1.x448.getSharedSecret(sk.key, pk.key).buffer); } catch (e) { reject(e); } }); } } exports.X448 = X448; });