UNPKG

react-native-quick-crypto

Version:

A fast implementation of Node's `crypto` module written in C/C++ JSI

202 lines (193 loc) 7.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rsa = void 0; exports.rsa_generateKeyPair = rsa_generateKeyPair; exports.rsa_generateKeyPairNode = rsa_generateKeyPairNode; exports.rsa_generateKeyPairNodeSync = rsa_generateKeyPairNodeSync; var _reactNativeNitroModules = require("react-native-nitro-modules"); var _keys = require("./keys"); var _utils = require("./utils"); class Rsa { constructor(modulusLength, publicExponent, hashAlgorithm) { this.native = _reactNativeNitroModules.NitroModules.createHybridObject('RsaKeyPair'); this.native.setModulusLength(modulusLength); this.native.setPublicExponent(publicExponent.buffer.slice(publicExponent.byteOffset, publicExponent.byteOffset + publicExponent.byteLength)); this.native.setHashAlgorithm(hashAlgorithm); } async generateKeyPair() { await this.native.generateKeyPair(); return { publicKey: this.native.getPublicKey(), privateKey: this.native.getPrivateKey() }; } generateKeyPairSync() { this.native.generateKeyPairSync(); return { publicKey: this.native.getPublicKey(), privateKey: this.native.getPrivateKey() }; } } // Node API exports.Rsa = Rsa; async function rsa_generateKeyPair(algorithm, extractable, keyUsages) { const { name, modulusLength, publicExponent, hash } = algorithm; // Validate parameters first if (!modulusLength || modulusLength < 256) { throw (0, _utils.lazyDOMException)('Invalid key length', 'OperationError'); } if (!publicExponent || publicExponent.length === 0) { throw (0, _utils.lazyDOMException)('Invalid public exponent', 'OperationError'); } // Validate hash algorithm using existing validation function let hashName; try { const normalizedHash = (0, _utils.normalizeHashName)(hash); hashName = typeof hash === 'string' ? hash : hash?.name || normalizedHash; } catch { throw (0, _utils.lazyDOMException)('Invalid Hash Algorithm', 'NotSupportedError'); } // Validate usages are not empty if (keyUsages.length === 0) { throw (0, _utils.lazyDOMException)('Usages cannot be empty', 'SyntaxError'); } // Usage validation based on algorithm type switch (name) { case 'RSASSA-PKCS1-v1_5': if ((0, _utils.hasAnyNotIn)(keyUsages, ['sign', 'verify'])) { throw (0, _utils.lazyDOMException)(`Unsupported key usage for a ${name} key`, 'SyntaxError'); } break; case 'RSA-PSS': if ((0, _utils.hasAnyNotIn)(keyUsages, ['sign', 'verify'])) { throw (0, _utils.lazyDOMException)(`Unsupported key usage for a ${name} key`, 'SyntaxError'); } break; case 'RSA-OAEP': if ((0, _utils.hasAnyNotIn)(keyUsages, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'])) { throw (0, _utils.lazyDOMException)(`Unsupported key usage for a ${name} key`, 'SyntaxError'); } break; default: throw (0, _utils.lazyDOMException)('The algorithm is not supported', 'NotSupportedError'); } // Split usages between public and private keys let publicUsages = []; let privateUsages = []; switch (name) { case 'RSASSA-PKCS1-v1_5': case 'RSA-PSS': publicUsages = (0, _utils.getUsagesUnion)(keyUsages, 'verify'); privateUsages = (0, _utils.getUsagesUnion)(keyUsages, 'sign'); break; case 'RSA-OAEP': publicUsages = (0, _utils.getUsagesUnion)(keyUsages, 'encrypt', 'wrapKey'); privateUsages = (0, _utils.getUsagesUnion)(keyUsages, 'decrypt', 'unwrapKey'); break; } // Validate that private key has usages for CryptoKeyPair if (privateUsages.length === 0) { throw (0, _utils.lazyDOMException)('Usages cannot be empty', 'SyntaxError'); } const rsa = new Rsa(modulusLength, publicExponent, hashName); await rsa.generateKeyPair(); const keyAlgorithm = { name, modulusLength, publicExponent, hash: { name: hashName } }; // Create KeyObject instances using the standard createKeyObject method const publicKeyData = rsa.native.getPublicKey(); const pub = _keys.KeyObject.createKeyObject('public', publicKeyData); const publicKey = new _keys.CryptoKey(pub, keyAlgorithm, publicUsages, true); const privateKeyData = rsa.native.getPrivateKey(); const priv = _keys.KeyObject.createKeyObject('private', privateKeyData); const privateKey = new _keys.CryptoKey(priv, keyAlgorithm, privateUsages, extractable); return { publicKey, privateKey }; } function rsa_prepareKeyGenParams(_type, options) { if (!options) { throw new Error('Options are required for RSA key generation'); } const { modulusLength, publicExponent, hash = 'sha256' } = options; if (!modulusLength || modulusLength < 256) { throw new Error('Invalid modulus length'); } const pubExp = publicExponent || 65537; const pubExpBytes = new Uint8Array([pubExp >> 16 & 0xff, pubExp >> 8 & 0xff, pubExp & 0xff]); const hashName = typeof hash === 'string' ? hash : hash; return new Rsa(modulusLength, pubExpBytes, hashName); } function rsa_formatKeyPairOutput(rsa, encoding) { const { publicFormat, publicType, privateFormat, privateType, cipher, passphrase } = encoding; const publicKeyData = rsa.native.getPublicKey(); const privateKeyData = rsa.native.getPrivateKey(); const pub = _keys.KeyObject.createKeyObject('public', publicKeyData); const priv = _keys.KeyObject.createKeyObject('private', privateKeyData); let publicKey; let privateKey; if (publicFormat === -1) { publicKey = pub; } else { const format = publicFormat === _utils.KFormatType.PEM ? _utils.KFormatType.PEM : _utils.KFormatType.DER; const keyEncoding = publicType === _utils.KeyEncoding.SPKI ? _utils.KeyEncoding.SPKI : _utils.KeyEncoding.PKCS1; const exported = pub.handle.exportKey(format, keyEncoding); if (format === _utils.KFormatType.PEM) { publicKey = Buffer.from(new Uint8Array(exported)).toString('utf-8'); } else { publicKey = exported; } } if (privateFormat === -1) { privateKey = priv; } else { const format = privateFormat === _utils.KFormatType.PEM ? _utils.KFormatType.PEM : _utils.KFormatType.DER; const keyEncoding = privateType === _utils.KeyEncoding.PKCS8 ? _utils.KeyEncoding.PKCS8 : _utils.KeyEncoding.PKCS1; const exported = priv.handle.exportKey(format, keyEncoding, cipher, passphrase); if (format === _utils.KFormatType.PEM) { privateKey = Buffer.from(new Uint8Array(exported)).toString('utf-8'); } else { privateKey = exported; } } return { publicKey, privateKey }; } async function rsa_generateKeyPairNode(type, options, encoding) { const rsa = rsa_prepareKeyGenParams(type, options); await rsa.generateKeyPair(); return rsa_formatKeyPairOutput(rsa, encoding); } function rsa_generateKeyPairNodeSync(type, options, encoding) { const rsa = rsa_prepareKeyGenParams(type, options); rsa.generateKeyPairSync(); return rsa_formatKeyPairOutput(rsa, encoding); } //# sourceMappingURL=rsa.js.map