UNPKG

@m92/express-utils

Version:

Utility Module for Express Framework

154 lines (119 loc) 5.39 kB
'use strict' import autoBind from 'auto-bind' import { Aes, AesUtils, Pgp } from '@m92/crypto' import ResponseBody from '../helpers/ResponseBody' import CRYPTO_ERRORS from '../constants/CRYPTO_ERRORS' export default class Crypto { constructor (CONFIG, CONSTANTS, options = {}, thisExpressUtils) { const { CustomError, logger } = thisExpressUtils this.CONFIG = CONFIG this.CONSTANTS = CONSTANTS this.options = options this.CustomError = CustomError this.logger = logger autoBind(this) } validatePgpOptions () { const { options, CustomError } = this const { getPassphrase, getPublicKeyArmored, getPrivateKeyArmored } = options if (!getPassphrase || typeof getPassphrase !== 'function') { throw new CustomError(undefined, CRYPTO_ERRORS.INVALID_PASSPHRASE_FUNC) } if (!getPublicKeyArmored || typeof getPublicKeyArmored !== 'function') { throw new CustomError(undefined, CRYPTO_ERRORS.INVALID_PUBLIC_KEY_FUNC) } if (!getPrivateKeyArmored || typeof getPrivateKeyArmored !== 'function') { throw new CustomError(undefined, CRYPTO_ERRORS.INVALID_PRIVATE_KEY_FUNC) } } encryptPayload (request, response, next) { const { CONFIG, CONSTANTS, CustomError } = this const { DISABLE_PAYLOAD_CRYPTOGRAPHY } = CONFIG if (DISABLE_PAYLOAD_CRYPTOGRAPHY) { return process.nextTick(next) } try { const { DEFAULT_AUTH, AUTH_HEADER, ACCESS_TOKEN_PROP, ACCESS_TOKEN_HEADER_KEY } = CONSTANTS if (!DEFAULT_AUTH && !ACCESS_TOKEN_PROP) { return process.nextTick(next) } if (DEFAULT_AUTH && !AUTH_HEADER.REQUEST_PROP) { return process.nextTick(next) } const tokenProp = (DEFAULT_AUTH && AUTH_HEADER.REQUEST_PROP) || ACCESS_TOKEN_PROP const tokenHeader = (DEFAULT_AUTH && AUTH_HEADER.HEADER_KEY) || ACCESS_TOKEN_HEADER_KEY.toLowerCase() const token = response[tokenProp] || response.get(tokenHeader) || '' const { body } = response if (!body || !token) { return process.nextTick(next) } const encryptionKey = AesUtils.extractKeyFromToken(token) const bodyString = JSON.stringify(body) const encryptParams = { key: encryptionKey, data: bodyString } const encryptedDataObj = Aes.encrypt('aes-256-gcm', encryptParams) const { payload } = encryptedDataObj const encryptedBody = { payload } const encryptedResponseBody = new ResponseBody(200, undefined, encryptedBody) response.encryptedBody = encryptedResponseBody return process.nextTick(next) } catch (e) { const error = new CustomError(e, CRYPTO_ERRORS.PAYLOAD_ENCRYPTION) response.body = error return process.nextTick(next) } } decryptPayload (request, response, next) { if (response.body) { return process.nextTick(next) } const { CONFIG, CONSTANTS, CustomError } = this const { DISABLE_PAYLOAD_CRYPTOGRAPHY } = CONFIG const { DEFAULT_AUTH, AUTH_HEADER, ACCESS_TOKEN_PROP, ACCESS_TOKEN_HEADER_KEY } = CONSTANTS if (DISABLE_PAYLOAD_CRYPTOGRAPHY) { return process.nextTick(next) } if (!DEFAULT_AUTH && !ACCESS_TOKEN_PROP) { return process.nextTick(next) } if (DEFAULT_AUTH && !AUTH_HEADER.REQUEST_PROP) { return process.nextTick(next) } try { const { body } = request const tokenProp = (DEFAULT_AUTH && AUTH_HEADER.REQUEST_PROP) || ACCESS_TOKEN_PROP const tokenHeader = (DEFAULT_AUTH && AUTH_HEADER.HEADER_KEY) || ACCESS_TOKEN_HEADER_KEY.toLowerCase() const token = request[tokenProp] || request.get(tokenHeader) || '' if (!body || !token) { return process.nextTick(next) } const decryptionKey = AesUtils.extractKeyFromToken(token) const { payload = '' } = body if (!payload) { return process.nextTick(next) } const decryptParams = { key: decryptionKey, payload } const decryptedDataObj = Aes.decrypt('aes-256-gcm', decryptParams) const { data: decryptedDataString } = decryptedDataObj const decryptedData = JSON.parse(decryptedDataString) request.body = decryptedData return process.nextTick(next) } catch (e) { const error = new CustomError(e, CRYPTO_ERRORS.PAYLOAD_DECRYPTION) response.body = error return process.nextTick(next) } } async decryptCredentials (request, response, next) { const { CONFIG, options, CustomError } = this const { getPassphrase, getPrivateKeyArmored } = options const { DISABLE_CREDENTIAL_CRYPTOGRAPHY } = CONFIG if (DISABLE_CREDENTIAL_CRYPTOGRAPHY) { return process.nextTick(next) } try { const { body } = request if (!body) { return process.nextTick(next) } this.validatePgpOptions() const passphrase = getPassphrase.constructor.name === 'AsyncFunction' ? await getPassphrase() : getPassphrase() const privateKeyArmored = getPrivateKeyArmored.constructor.name === 'AsyncFunction' ? await getPrivateKeyArmored() : getPrivateKeyArmored() const decryptParams = { data: body, privateKeyArmored, passphrase } const decryptedData = await Pgp.decrypt(decryptParams) request.body = decryptedData return next() } catch (e) { const error = new CustomError(e, CRYPTO_ERRORS.CREDENTIAL_DECRYPTION) response.body = error return process.nextTick(next) } } }