UNPKG

js-crypto-key-utils

Version:

Universal Module for Cryptographic Key Utilities in JavaScript, including PEM-JWK converters

192 lines 9.96 kB
"use strict"; /** * asn1rsa.js */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.toJwk = exports.fromJwk = void 0; var asn1_js_1 = __importDefault(require("asn1.js")); var js_encoding_utils_1 = __importDefault(require("js-encoding-utils")); var BufferMod = __importStar(require("buffer")); var Buffer = BufferMod.Buffer; var params = __importStar(require("./params")); var util_1 = require("./util"); /** * Encode RSA JWK key to ASN.1 DER or PEM of SPKI/OneAsymmetricKey. * @param {JsonWebKey} jwk - A key object in JWK format to be encoded. * @param {PublicOrPrivate} type - 'public' or 'private'. * @returns {DecodedAsn1Key} - Parsed object of ASN.1 encoded key object. */ var fromJwk = function (jwk, type) { var publicKeyAlgorithmOid = params.publicKeyAlgorithms['RSA'].oid; // Parameters is always null Ox0500 in ASN.1 as shown in the Section 2.3.1 https://tools.ietf.org/html/rfc3279 var parameters = Buffer.from([0x05, 0x00]); var algorithm = { algorithm: publicKeyAlgorithmOid, parameters: parameters }; // to append leading zeros (pruned when making JWK) in order to make binary of intended bit length // https://tools.ietf.org/html/rfc7518#section-6.3 var modulusBytes = js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.n); var nLen = modulusBytes.length; var modulusLength = (nLen % 128 === 0) ? nLen : nLen + (128 - (nLen % 128)); var modulus = new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(modulusBytes, modulusLength)); // JWA RFC var publicExponent = new asn1_js_1.default.bignum(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.e)); var decoded = {}; if (type === 'public') { // SPKI decoded.subjectPublicKey = { unused: 0, data: RSAPublicKey.encode({ modulus: modulus, publicExponent: publicExponent }, 'der') }; decoded.algorithm = algorithm; } else if (type === 'private') { // PKCS8 decoded.version = 0; // no public key presents for v2 (0) decoded.privateKeyAlgorithm = algorithm; decoded.privateKey = RSAPrivateKey.encode({ version: 0, modulus: modulus, publicExponent: publicExponent, privateExponent: new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.d), modulusLength)), prime1: new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.p), modulusLength)), prime2: new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.q), modulusLength)), exponent1: new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.dp), modulusLength)), exponent2: new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.dq), modulusLength)), coefficient: new asn1_js_1.default.bignum((0, util_1.appendLeadingZeros)(js_encoding_utils_1.default.encoder.decodeBase64Url(jwk.qi), modulusLength)) }, 'der'); } return decoded; }; exports.fromJwk = fromJwk; /** * Convert RSA spki/pkcs8 public/private keys to JWK * @param {Object} decoded - Parsed object of RSA key to be encoded. * @param {PublicOrPrivate} type - 'public' or 'private' * @return {JsonWebKey} - Encoded RSA key object in JWK format. */ var toJwk = function (decoded, type) { if (type === 'public') { // SPKI // algorithm.algorithm.parameters is always null Ox0500 in ASN.1 // as shown in the Section 2.3.1 https://tools.ietf.org/html/rfc3279 // overwrite nested binary object as parsed object decoded.subjectPublicKey.data = RSAPublicKey.decode(decoded.subjectPublicKey.data, 'der'); var modulus = decoded.subjectPublicKey.data.modulus; var publicExponent = decoded.subjectPublicKey.data.publicExponent; // convert n and e from BN // modulus n var nLen = modulus.byteLength(); var len = (nLen % 128 === 0) ? nLen : nLen + (128 - (nLen % 128)); modulus = new Uint8Array(modulus.toArray('be', len)); // // publicExponent e; publicExponent = new Uint8Array(publicExponent.toArray('be', publicExponent.byteLength())); return { kty: 'RSA', n: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(modulus)), e: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(publicExponent)) }; } else { // type === 'private', PKCS8 // privateKeyAlgorithm.algorithm.parameters is always null Ox0500 in ASN.1 // as shown in the Section 2.3.1 https://tools.ietf.org/html/rfc3279 // overwrite nested binary object as parsed object decoded.privateKey = RSAPrivateKey.decode(decoded.privateKey, 'der'); var privateKeyElems_1 = {}; // work around privateKeyElems_1.modulus = decoded.privateKey.modulus; // calculate key length from modulus n var nLen = privateKeyElems_1.modulus.byteLength(); var len_1 = (nLen % 128 === 0) ? nLen : nLen + (128 - (nLen % 128)); // this is actual key length, e.g., 256 bytes // convert BN to Uint8Array privateKeyElems_1.modulus = new Uint8Array(privateKeyElems_1.modulus.toArray('be', len_1)); // n of length len privateKeyElems_1.publicExponent = new Uint8Array(decoded.privateKey.publicExponent.toArray('be', decoded.privateKey.publicExponent.byteLength())); // e of arbitrary small length privateKeyElems_1.privateExponent = new Uint8Array(decoded.privateKey.privateExponent.toArray('be', len_1)); // d of length len var keys = ['prime1', 'prime2', 'exponent1', 'exponent2', 'coefficient']; // elements of length len/2 keys.forEach(function (key) { privateKeyElems_1[key] = new Uint8Array(decoded.privateKey[key].toArray('be', (len_1 >> 1))); }); // prune leading zeros JWW RSA private key: https://tools.ietf.org/html/rfc7517 return { kty: 'RSA', n: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.modulus)), e: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.publicExponent)), d: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.privateExponent)), p: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.prime1)), q: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.prime2)), dp: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.exponent1)), dq: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.exponent2)), qi: js_encoding_utils_1.default.encoder.encodeBase64Url((0, util_1.pruneLeadingZeros)(privateKeyElems_1.coefficient)) }; } }; exports.toJwk = toJwk; /////////// // https://tools.ietf.org/html/rfc3447 var RSAPublicKey = asn1_js_1.default.define('RSAPublicKey', function () { // @ts-ignore this.seq().obj( // @ts-ignore this.key('modulus').int(), // n // @ts-ignore this.key('publicExponent').int() // e ); }); var RSAPrivateKey = asn1_js_1.default.define('RSAPrivateKey', function () { // @ts-ignore this.seq().obj( // @ts-ignore this.key('version').int(), // 0 // @ts-ignore this.key('modulus').int(), // n // @ts-ignore this.key('publicExponent').int(), // e // @ts-ignore this.key('privateExponent').int(), // d // @ts-ignore this.key('prime1').int(), // p // @ts-ignore this.key('prime2').int(), // q // @ts-ignore this.key('exponent1').int(), // d mod (p-1) // @ts-ignore this.key('exponent2').int(), // d mod (q-1) // @ts-ignore this.key('coefficient').int(), // (inverse of q) mod p // @ts-ignore this.key('otherPrimeInfos').optional().use(OtherPrimeInfos)); }); var OtherPrimeInfos = asn1_js_1.default.define('OtherPrimeInfos', function () { // @ts-ignore this.seqof(OtherPrimeInfo); }); var OtherPrimeInfo = asn1_js_1.default.define('OtherPrimeInfo', function () { // @ts-ignore this.seq().obj( // @ts-ignore this.key('prime').int(), // @ts-ignore this.key('exponent').int(), // @ts-ignore this.key('coefficient').int()); }); //# sourceMappingURL=asn1rsa.js.map