UNPKG

react-native-quick-crypto

Version:

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

157 lines (156 loc) 5.32 kB
"use strict"; import { NitroModules } from 'react-native-nitro-modules'; import { binaryLikeToArrayBuffer as toAB, isStringOrBuffer, KFormatType, KeyEncoding } from '../utils'; import { isCryptoKey } from './utils'; import { KeyObject } from './classes'; import { constants } from '../constants'; function preparePublicCipherKey(key, isEncrypt) { let keyObj; let padding; let oaepHash; let oaepLabel; if (key instanceof KeyObject) { if (isEncrypt && key.type !== 'public') { throw new Error('publicEncrypt requires a public key'); } // publicDecrypt accepts both public and private keys (Node.js behavior) // A private key contains the public components needed for verify_recover keyObj = key; } else if (isCryptoKey(key)) { const cryptoKey = key; keyObj = cryptoKey.keyObject; } else if (isStringOrBuffer(key)) { const data = toAB(key); const isPem = typeof key === 'string' && key.includes('-----BEGIN'); const isPrivatePem = typeof key === 'string' && key.includes('-----BEGIN PRIVATE'); // publicDecrypt accepts both public and private keys (Node.js behavior) if (!isEncrypt && isPrivatePem) { keyObj = KeyObject.createKeyObject('private', data, KFormatType.PEM, KeyEncoding.PKCS8); } else { keyObj = KeyObject.createKeyObject('public', data, isPem ? KFormatType.PEM : KFormatType.DER, KeyEncoding.SPKI); } } else if (typeof key === 'object' && 'key' in key) { const options = key; const result = preparePublicCipherKey(options.key, isEncrypt); keyObj = result.keyHandle; padding = options.padding; oaepHash = options.oaepHash; if (options.oaepLabel) { oaepLabel = toAB(options.oaepLabel); } } else { throw new Error('Invalid key input'); } return { keyHandle: keyObj, padding, oaepHash, oaepLabel }; } export function publicEncrypt(key, buffer) { const { keyHandle, padding, oaepHash, oaepLabel } = preparePublicCipherKey(key, true); const rsaCipher = NitroModules.createHybridObject('RsaCipher'); const data = toAB(buffer); const paddingMode = padding ?? constants.RSA_PKCS1_OAEP_PADDING; const hashAlgorithm = oaepHash || 'SHA-256'; try { const encrypted = rsaCipher.encrypt(keyHandle.handle, data, paddingMode, hashAlgorithm, oaepLabel); return Buffer.from(encrypted); } catch (error) { throw new Error(`publicEncrypt failed: ${error.message}`); } } export function publicDecrypt(key, buffer) { const { keyHandle, padding } = preparePublicCipherKey(key, false); const rsaCipher = NitroModules.createHybridObject('RsaCipher'); const data = toAB(buffer); const paddingMode = padding ?? constants.RSA_PKCS1_PADDING; try { const decrypted = rsaCipher.publicDecrypt(keyHandle.handle, data, paddingMode); return Buffer.from(decrypted); } catch (error) { throw new Error(`publicDecrypt failed: ${error.message}`); } } function preparePrivateCipherKey(key, isEncrypt) { let keyObj; let padding; let oaepHash; let oaepLabel; if (key instanceof KeyObject) { if (isEncrypt && key.type !== 'private') { throw new Error('privateEncrypt requires a private key'); } if (!isEncrypt && key.type !== 'private') { throw new Error('privateDecrypt requires a private key'); } keyObj = key; } else if (isCryptoKey(key)) { const cryptoKey = key; keyObj = cryptoKey.keyObject; } else if (isStringOrBuffer(key)) { const data = toAB(key); const isPem = typeof key === 'string' && key.includes('-----BEGIN'); keyObj = KeyObject.createKeyObject('private', data, isPem ? KFormatType.PEM : KFormatType.DER, KeyEncoding.PKCS8); } else if (typeof key === 'object' && 'key' in key) { const options = key; const result = preparePrivateCipherKey(options.key, isEncrypt); keyObj = result.keyHandle; padding = options.padding; oaepHash = options.oaepHash; if (options.oaepLabel) { oaepLabel = toAB(options.oaepLabel); } } else { throw new Error('Invalid key input'); } return { keyHandle: keyObj, padding, oaepHash, oaepLabel }; } export function privateEncrypt(key, buffer) { const { keyHandle, padding } = preparePrivateCipherKey(key, true); const rsaCipher = NitroModules.createHybridObject('RsaCipher'); const data = toAB(buffer); const paddingMode = padding ?? constants.RSA_PKCS1_PADDING; try { const encrypted = rsaCipher.privateEncrypt(keyHandle.handle, data, paddingMode); return Buffer.from(encrypted); } catch (error) { throw new Error(`privateEncrypt failed: ${error.message}`); } } export function privateDecrypt(key, buffer) { const { keyHandle, padding, oaepHash, oaepLabel } = preparePrivateCipherKey(key, false); const rsaCipher = NitroModules.createHybridObject('RsaCipher'); const data = toAB(buffer); const paddingMode = padding ?? constants.RSA_PKCS1_OAEP_PADDING; const hashAlgorithm = oaepHash || 'SHA-256'; try { const decrypted = rsaCipher.privateDecrypt(keyHandle.handle, data, paddingMode, hashAlgorithm, oaepLabel); return Buffer.from(decrypted); } catch (error) { throw new Error(`privateDecrypt failed: ${error.message}`); } } //# sourceMappingURL=publicCipher.js.map