UNPKG

react-native-quick-crypto

Version:

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

280 lines (272 loc) 9.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SecretKeyObject = exports.PublicKeyObject = exports.PrivateKeyObject = exports.KeyObject = exports.CryptoKey = exports.AsymmetricKeyObject = void 0; var _reactNativeBuffer = require("@craftzdog/react-native-buffer"); var _reactNativeNitroModules = require("react-native-nitro-modules"); var _utils = require("../utils"); var _utils2 = require("./utils"); class CryptoKey { get [Symbol.toStringTag]() { return 'CryptoKey'; } constructor(keyObject, keyAlgorithm, keyUsages, keyExtractable) { this.keyObject = keyObject; this.keyAlgorithm = keyAlgorithm; // Frozen so external code can't mutate `key.usages` (per WebCrypto spec). this.keyUsages = Object.freeze((0, _utils.getSortedUsages)(keyUsages)); this.keyExtractable = keyExtractable; } // eslint-disable-next-line @typescript-eslint/no-unused-vars inspect(_depth, _options) { throw new Error('CryptoKey.inspect is not implemented'); // if (depth < 0) return this; // const opts = { // ...options, // depth: options.depth == null ? null : options.depth - 1, // }; // return `CryptoKey ${inspect( // { // type: this.type, // extractable: this.extractable, // algorithm: this.algorithm, // usages: this.usages, // }, // opts // )}`; } get type() { // if (!(this instanceof CryptoKey)) throw new Error('Invalid CryptoKey'); return this.keyObject.type; } get extractable() { return this.keyExtractable; } get algorithm() { return this.keyAlgorithm; } get usages() { return this.keyUsages; } } exports.CryptoKey = CryptoKey; class KeyObject { get [Symbol.toStringTag]() { return 'KeyObject'; } // eslint-disable-next-line @typescript-eslint/no-unused-vars export(_options) { // This is a placeholder and should be overridden by subclasses. throw new Error('export() must be implemented by subclasses'); } equals(otherKeyObject) { if (!(otherKeyObject instanceof KeyObject)) { throw new TypeError('otherKeyObject must be a KeyObject'); } return this.handle.keyEquals(otherKeyObject.handle); } constructor(type, handleOrKey) { if (type !== 'secret' && type !== 'public' && type !== 'private') throw new Error(`invalid KeyObject type: ${type}`); if (handleOrKey instanceof ArrayBuffer) { this.handle = _reactNativeNitroModules.NitroModules.createHybridObject('KeyObjectHandle'); let keyType; switch (type) { case 'public': keyType = _utils.KeyType.PUBLIC; break; case 'private': keyType = _utils.KeyType.PRIVATE; break; case 'secret': keyType = _utils.KeyType.SECRET; break; default: // Should not happen throw new Error('invalid key type'); } this.handle.init(keyType, handleOrKey); } else { this.handle = handleOrKey; } this.type = type; } static from(key) { if (!(key instanceof CryptoKey)) { throw new TypeError(`The "key" argument must be an instance of CryptoKey. Received ${typeof key}`); } return key.keyObject; } toCryptoKey(algorithm, extractable, keyUsages) { return new CryptoKey(this, algorithm, keyUsages, extractable); } static createKeyObject(type, key, format, encoding, passphrase) { if (type !== 'secret' && type !== 'public' && type !== 'private') throw new Error(`invalid KeyObject type: ${type}`); const handle = _reactNativeNitroModules.NitroModules.createHybridObject('KeyObjectHandle'); let keyType; switch (type) { case 'public': keyType = _utils.KeyType.PUBLIC; break; case 'private': keyType = _utils.KeyType.PRIVATE; break; case 'secret': keyType = _utils.KeyType.SECRET; break; default: throw new Error('invalid key type'); } handle.init(keyType, key, format, encoding, passphrase); // For asymmetric keys, return the appropriate subclass if (type === 'public' || type === 'private') { try { handle.getAsymmetricKeyType(); // If we get here, it's an asymmetric key - return the appropriate subclass if (type === 'public') { return new PublicKeyObject(handle); } else { return new PrivateKeyObject(handle); } } catch { // Not an asymmetric key, fall through to regular KeyObject } } // For secret keys, return SecretKeyObject if (type === 'secret') { return new SecretKeyObject(handle); } // Return regular KeyObject for symmetric keys or if asymmetric detection failed return new KeyObject(type, handle); } getAsymmetricKeyType() { return undefined; } getAsymmetricKeyDetails() { return undefined; } } exports.KeyObject = KeyObject; class SecretKeyObject extends KeyObject { constructor(handle) { super('secret', handle); } get symmetricKeySize() { return this.handle.getSymmetricKeySize(); } export(options) { if (options?.format === 'pem' || options?.format === 'jwk') { throw new Error(`SecretKey export for ${options.format} is not supported`); } const key = this.handle.exportKey(); return _reactNativeBuffer.Buffer.from(key); } } // const kAsymmetricKeyType = Symbol('kAsymmetricKeyType'); // const kAsymmetricKeyDetails = Symbol('kAsymmetricKeyDetails'); // function normalizeKeyDetails(details = {}) { // if (details.publicExponent !== undefined) { // return { // ...details, // publicExponent: bigIntArrayToUnsignedBigInt( // new Uint8Array(details.publicExponent) // ), // }; // } // return details; // } exports.SecretKeyObject = SecretKeyObject; class AsymmetricKeyObject extends KeyObject { constructor(type, handle) { super(type, handle); } get asymmetricKeyType() { if (!this._asymmetricKeyType) { this._asymmetricKeyType = this.handle.getAsymmetricKeyType(); } return this._asymmetricKeyType; } get asymmetricKeyDetails() { if (!this._asymmetricKeyDetails) { this._asymmetricKeyDetails = this.handle.keyDetail(); } return this._asymmetricKeyDetails; } get namedCurve() { return this.asymmetricKeyDetails?.namedCurve; } } exports.AsymmetricKeyObject = AsymmetricKeyObject; class PublicKeyObject extends AsymmetricKeyObject { constructor(handle) { super('public', handle); } export(options) { if (options?.format === 'jwk') { return this.handle.exportJwk({}, false); } if (options?.format === 'raw-public') { if (this.asymmetricKeyType === 'ec') { const pointType = options.type ?? 'uncompressed'; if (pointType !== 'compressed' && pointType !== 'uncompressed') { throw new Error(`Invalid options.type for raw-public EC export: ${pointType}`); } return _reactNativeBuffer.Buffer.from(this.handle.exportECPublicRaw(pointType === 'compressed')); } return _reactNativeBuffer.Buffer.from(this.handle.exportRawPublic()); } const { format, type } = (0, _utils2.parsePublicKeyEncoding)(options, this.asymmetricKeyType); if (typeof format !== 'number') { throw new Error(`Unexpected format ${format} after raw-format dispatch`); } const key = this.handle.exportKey(format, typeof type === 'string' ? undefined : type); const buffer = _reactNativeBuffer.Buffer.from(key); if (options?.format === 'pem') { return buffer.toString('utf-8'); } return buffer; } } exports.PublicKeyObject = PublicKeyObject; class PrivateKeyObject extends AsymmetricKeyObject { constructor(handle) { super('private', handle); } export(options) { if (options?.format === 'jwk') { if (options.passphrase !== undefined) { throw new Error('jwk does not support encryption'); } return this.handle.exportJwk({}, false); } if (options?.format === 'raw-private') { if (this.asymmetricKeyType === 'ec') { return _reactNativeBuffer.Buffer.from(this.handle.exportECPrivateRaw()); } return _reactNativeBuffer.Buffer.from(this.handle.exportRawPrivate()); } if (options?.format === 'raw-seed') { return _reactNativeBuffer.Buffer.from(this.handle.exportRawSeed()); } const { format, type, cipher, passphrase } = (0, _utils2.parsePrivateKeyEncoding)(options, this.asymmetricKeyType); if (typeof format !== 'number') { throw new Error(`Unexpected format ${format} after raw-format dispatch`); } const key = this.handle.exportKey(format, typeof type === 'string' ? undefined : type, cipher, passphrase); const buffer = _reactNativeBuffer.Buffer.from(key); if (options?.format === 'pem') { return buffer.toString('utf-8'); } return buffer; } } exports.PrivateKeyObject = PrivateKeyObject; //# sourceMappingURL=classes.js.map