UNPKG

react-native-quick-crypto

Version:

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

180 lines (171 loc) 5.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Verify = exports.Sign = void 0; exports.createSign = createSign; exports.createVerify = createVerify; var _reactNativeBuffer = require("@craftzdog/react-native-buffer"); var _reactNativeNitroModules = require("react-native-nitro-modules"); var _classes = require("./classes"); var _utils = require("./utils"); var _utils2 = require("../utils"); function prepareKey(key, isPublic) { // Already a KeyObject if (key instanceof _classes.KeyObject) { if (isPublic) { if (key.type === 'secret') { throw new Error('Cannot use secret key for signature verification'); } } else { if (key.type !== 'private') { throw new Error('Key must be a private key for signing'); } } return { keyObject: key }; } // CryptoKey - extract KeyObject if ((0, _utils.isCryptoKey)(key)) { const cryptoKey = key; return prepareKey(cryptoKey.keyObject, isPublic); } // Raw string or buffer - create KeyObject if ((0, _utils2.isStringOrBuffer)(key)) { const isPem = typeof key === 'string' && key.includes('-----BEGIN'); const format = isPem ? _utils2.KFormatType.PEM : undefined; const type = isPublic ? 'public' : 'private'; const keyData = (0, _utils2.binaryLikeToArrayBuffer)(key); const keyObject = _classes.KeyObject.createKeyObject(type, keyData, format); return { keyObject }; } // KeyInputObject with options if (typeof key === 'object' && 'key' in key) { const keyObj = key; const { key: data, format, type, padding, saltLength, dsaEncoding } = keyObj; // Nested KeyObject if (data instanceof _classes.KeyObject) { return { keyObject: data, options: { padding, saltLength, dsaEncoding } }; } // Nested CryptoKey if ((0, _utils.isCryptoKey)(data)) { return { keyObject: data.keyObject, options: { padding, saltLength, dsaEncoding } }; } if (!(0, _utils2.isStringOrBuffer)(data)) { throw new Error('Invalid key data type'); } // Determine format const isPem = format === 'pem' || typeof data === 'string' && data.includes('-----BEGIN'); const kFormat = isPem ? _utils2.KFormatType.PEM : format === 'der' ? _utils2.KFormatType.DER : undefined; // Determine encoding type let kType; if (type === 'pkcs8') kType = _utils2.KeyEncoding.PKCS8;else if (type === 'pkcs1') kType = _utils2.KeyEncoding.PKCS1;else if (type === 'sec1') kType = _utils2.KeyEncoding.SEC1;else if (type === 'spki') kType = _utils2.KeyEncoding.SPKI; const keyType = isPublic ? 'public' : 'private'; // Always convert to ArrayBuffer to avoid Nitro bridge string truncation bug const originalLength = typeof data === 'string' ? data.length : data.byteLength; const keyData = (0, _utils2.binaryLikeToArrayBuffer)(data); console.log(`[prepareKey KeyInputObject] ${keyType} key, original length: ${originalLength}, ArrayBuffer size: ${keyData.byteLength}`); const keyObject = _classes.KeyObject.createKeyObject(keyType, keyData, kFormat, kType); return { keyObject, options: { padding, saltLength, dsaEncoding } }; } throw new Error('Invalid key input'); } function dsaEncodingToNumber(dsaEncoding) { if (dsaEncoding === 'der') return 0; if (dsaEncoding === 'ieee-p1363') return 1; return undefined; } class Sign { constructor(algorithm) { this.handle = _reactNativeNitroModules.NitroModules.createHybridObject('SignHandle'); this.handle.init(algorithm); } update(data) { const dataBuffer = (0, _utils2.binaryLikeToArrayBuffer)(data); this.handle.update(dataBuffer); return this; } sign(privateKey, outputEncoding) { if (privateKey === null || privateKey === undefined) { throw new Error('Private key is required'); } const { keyObject, options } = prepareKey(privateKey, false); const signature = this.handle.sign(keyObject.handle, options?.padding, options?.saltLength, dsaEncodingToNumber(options?.dsaEncoding)); const buf = _reactNativeBuffer.Buffer.from(signature); if (outputEncoding) { return buf.toString(outputEncoding); } return buf; } } exports.Sign = Sign; class Verify { constructor(algorithm) { this.handle = _reactNativeNitroModules.NitroModules.createHybridObject('VerifyHandle'); this.handle.init(algorithm); } update(data) { const dataBuffer = (0, _utils2.binaryLikeToArrayBuffer)(data); this.handle.update(dataBuffer); return this; } verify(publicKey, signature, signatureEncoding) { if (publicKey === null || publicKey === undefined) { throw new Error('Public key is required'); } const { keyObject, options } = prepareKey(publicKey, true); // Convert signature to ArrayBuffer let sigBuffer; if (signatureEncoding && typeof signature === 'string') { sigBuffer = (0, _utils2.binaryLikeToArrayBuffer)(_reactNativeBuffer.Buffer.from(signature, signatureEncoding)); } else { sigBuffer = (0, _utils2.binaryLikeToArrayBuffer)(signature); } return this.handle.verify(keyObject.handle, sigBuffer, options?.padding, options?.saltLength, dsaEncodingToNumber(options?.dsaEncoding)); } } exports.Verify = Verify; function createSign(algorithm) { return new Sign(algorithm); } function createVerify(algorithm) { return new Verify(algorithm); } //# sourceMappingURL=signVerify.js.map