UNPKG

@guarani/jose

Version:

Implementation of the RFCs of the JOSE Working Group.

121 lines (120 loc) 5.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EcKey = void 0; const crypto_1 = require("crypto"); const util_1 = require("util"); const invalid_json_web_key_exception_1 = require("../../../exceptions/invalid-json-web-key.exception"); const unsupported_algorithm_exception_1 = require("../../../exceptions/unsupported-algorithm.exception"); const unsupported_elliptic_curve_exception_1 = require("../../../exceptions/unsupported-elliptic-curve.exception"); const jsonwebkey_1 = require("../../jsonwebkey"); const elliptic_curves_registry_1 = require("./elliptic-curves-registry"); const generateKeyPairAsync = (0, util_1.promisify)(crypto_1.generateKeyPair); /** * Implementation of {@link https://www.rfc-editor.org/rfc/rfc7518.html#section-6.2 RFC 7518 Section 6.2}. */ class EcKey extends jsonwebkey_1.JsonWebKey { /** * Instantiates an Elliptic Curve JSON Web Key based on the provided Parameters. * * @param key Parameters of the Elliptic Curve JSON Web Key. * @param options Optional JSON Web Key Parameters. */ constructor(key, options = {}) { if (key instanceof EcKey) { return key; } const params = { ...key, ...options }; if (typeof params.kty !== 'string') { throw new invalid_json_web_key_exception_1.InvalidJsonWebKeyException('Invalid parameter "kty".'); } if (params.kty !== 'EC') { throw new unsupported_algorithm_exception_1.UnsupportedAlgorithmException(`Invalid JSON Web Key Type. Expected "EC", got "${params.kty}".`); } if (typeof params.crv !== 'string') { throw new invalid_json_web_key_exception_1.InvalidJsonWebKeyException('Invalid parameter "crv".'); } const curve = elliptic_curves_registry_1.ELLIPTIC_CURVES_REGISTRY.find((ellipticCurve) => ellipticCurve.id === params.crv); if (curve === undefined) { throw new unsupported_elliptic_curve_exception_1.UnsupportedEllipticCurveException(`Unsupported Elliptic Curve "${params.crv}".`); } if (typeof params.x !== 'string') { throw new invalid_json_web_key_exception_1.InvalidJsonWebKeyException('Invalid key parameter "x".'); } if (typeof params.y !== 'string') { throw new invalid_json_web_key_exception_1.InvalidJsonWebKeyException('Invalid key parameter "y".'); } if (params.d !== undefined) { if (typeof params.d !== 'string') { throw new invalid_json_web_key_exception_1.InvalidJsonWebKeyException('Invalid key parameter "d".'); } } super(params); } /** * Generates a new Elliptic Curve JSON Web Key. * * @param options Options for the generation of the Elliptic Curve JSON Web Key. * @param params Optional JSON Web Key Parameters. * @returns Generated Elliptic Curve JSON Web Key. */ static async generate(options, params = {}) { const { curve } = options; if (typeof curve !== 'string') { throw new TypeError('Invalid option "curve".'); } const curveMeta = elliptic_curves_registry_1.ELLIPTIC_CURVES_REGISTRY.find((ellipticCurve) => ellipticCurve.id === curve); if (curveMeta === undefined) { throw new unsupported_elliptic_curve_exception_1.UnsupportedEllipticCurveException(`Unsupported Elliptic Curve "${curve}".`); } const { privateKey } = await generateKeyPairAsync('ec', { namedCurve: curveMeta.name }); return new EcKey(privateKey.export({ format: 'jwk' }), params); } /** * Loads the provided JSON Web Key into a NodeJS Crypto Key. * * @param params Parameters of the JSON Web Key. * @returns NodeJS Crypto Key. */ loadCryptoKey(params) { const input = { format: 'jwk', key: params }; return params.d === undefined ? (0, crypto_1.createPublicKey)(input) : (0, crypto_1.createPrivateKey)(input); } /** * Exports the data of the Elliptic Curve JSON Web Key. * * @param options Options for exporting the data of the Elliptic Curve JSON Web Key. * @returns Encoded data of the Elliptic Curve JSON Web Key. */ export(options) { const { encoding, format, type } = options; if (encoding !== 'der' && encoding !== 'pem') { throw new TypeError('Invalid option "encoding".'); } if (format !== 'sec1' && format !== 'pkcs8' && format !== 'spki') { throw new TypeError('Invalid option "format".'); } if (type !== 'private' && type !== 'public') { throw new TypeError('Invalid option "type".'); } if (type === 'private' && format !== 'sec1' && format !== 'pkcs8') { throw new TypeError(`Unsupported format "${format}" for type "${type}".`); } if (type === 'public' && format !== 'spki') { throw new TypeError(`Unsupported format "${format}" for type "${type}".`); } if (this.cryptoKey.type === 'public' && type === 'private') { throw new TypeError('Cannot export private data from a public key.'); } let { cryptoKey } = this; const input = { format: encoding, type: format }; if (this.cryptoKey.type === 'private' && type === 'public') { cryptoKey = (0, crypto_1.createPublicKey)(cryptoKey); } let exported = cryptoKey.export(input); if (encoding === 'pem') { exported = exported.slice(0, -1); } return exported; } } exports.EcKey = EcKey;