diff --git a/src/routes.js b/src/routes.js index e67a7c69..14d4c4f5 100644 --- a/src/routes.js +++ b/src/routes.js @@ -20,7 +20,6 @@ const path = require('path') const getListPage = require('../utils/paginate') const auth = require('../services/auth/auth') const FS = require('../utils/fs') -const Encryption = require('../utils/encryptionStore') const ECC = require('../utils/ECC') const LightningServices = require('../utils/lightningServices') const lndErrorManager = require('../utils/lightningServices/errors') @@ -214,98 +213,13 @@ module.exports = async ( next() }) - app.use((req, res, next) => { - const legacyDeviceId = req.headers['x-shockwallet-device-id'] - const deviceId = req.headers['encryption-device-id'] - try { - if ( - nonEncryptedRoutes.includes(req.path) || - process.env.DISABLE_SHOCK_ENCRYPTION === 'true' || - (deviceId && !legacyDeviceId) - ) { - return next() - } - - if (!legacyDeviceId) { - const error = { - field: 'deviceId', - message: 'Please specify a device ID' - } - logger.error('Please specify a device ID') - return res.status(401).json(error) - } - - if (!Encryption.isAuthorizedDevice({ deviceId: legacyDeviceId })) { - const error = { - field: 'deviceId', - message: 'Please specify a device ID' - } - logger.error('Unknown Device') - return res.status(401).json(error) - } - if ( - !req.body.encryptionKey && - !req.body.iv && - !req.headers['x-shock-encryption-token'] - ) { - return next() - } - let reqData = null - let IV = null - let encryptedKey = null - let encryptedToken = null - if (req.method === 'GET' || req.method === 'DELETE') { - if (req.headers['x-shock-encryption-token']) { - encryptedToken = req.headers['x-shock-encryption-token'] - encryptedKey = req.headers['x-shock-encryption-key'] - IV = req.headers['x-shock-encryption-iv'] - } - } else { - encryptedToken = req.body.token - encryptedKey = req.body.encryptionKey || req.body.encryptedKey - IV = req.body.iv - reqData = req.body.data || req.body.encryptedData - } - const decryptedKey = Encryption.decryptKey({ - deviceId: legacyDeviceId, - message: encryptedKey - }) - if (reqData) { - const decryptedMessage = Encryption.decryptMessage({ - message: reqData, - key: decryptedKey, - iv: IV - }) - req.body = JSON.parse(decryptedMessage) - } - - const decryptedToken = encryptedToken - ? Encryption.decryptMessage({ - message: encryptedToken, - key: decryptedKey, - iv: IV - }) - : null - - if (decryptedToken) { - req.headers.authorization = decryptedToken - } - - return next() - } catch (err) { - logger.error(err) - return res.status(401).json(err) - } - }) - app.use(async (req, res, next) => { - const legacyDeviceId = req.headers['x-shockwallet-device-id'] const deviceId = req.headers['encryption-device-id'] try { if ( nonEncryptedRoutes.includes(req.path) || process.env.DISABLE_SHOCK_ENCRYPTION === 'true' || - (legacyDeviceId && !deviceId) + !deviceId ) { return next() } @@ -499,44 +413,6 @@ module.exports = async ( res.json({ msg: 'OK' }) }) - app.post('/api/security/exchangeKeys', async (req, res) => { - try { - const { publicKey, deviceId } = req.body - - if (!publicKey) { - return res.status(400).json({ - field: 'publicKey', - message: 'Please provide a valid public key' - }) - } - - if ( - !deviceId || - !/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/iu.test( - deviceId - ) - ) { - return res.status(400).json({ - field: 'deviceId', - message: 'Please provide a valid device ID' - }) - } - - const authorizedDevice = await Encryption.authorizeDevice({ - deviceId, - publicKey - }) - logger.info(authorizedDevice) - return res.json(authorizedDevice) - } catch (err) { - logger.error(err) - return res.status(401).json({ - field: 'unknown', - message: err - }) - } - }) - app.post('/api/encryption/exchange', async (req, res) => { try { const { publicKey, deviceId } = req.body diff --git a/src/server.js b/src/server.js index b62c0d34..5cd84b0a 100644 --- a/src/server.js +++ b/src/server.js @@ -1,5 +1,3 @@ -const { generateRandomString } = require('../utils/encryptionStore') - /** * @prettier */ @@ -22,7 +20,6 @@ const server = program => { const ECC = require('../utils/ECC') const LightningServices = require('../utils/lightningServices') - const Encryption = require('../utils/encryptionStore') const app = Express() const compression = require('compression') @@ -124,7 +121,6 @@ const server = program => { * @param {(() => void)} next */ const modifyResponseBody = (req, res, next) => { - const legacyDeviceId = req.headers['x-shockwallet-device-id'] const deviceId = req.headers['encryption-device-id'] const oldSend = res.send @@ -136,38 +132,6 @@ const server = program => { return } - if (legacyDeviceId) { - res.send = (...args) => { - if (args[0] && args[0].encryptedData && args[0].encryptionKey) { - logger.warn('Response loop detected!') - oldSend.apply(res, args) - return - } - - const { cached, hash } = cacheCheck({ req, res, args, send: oldSend }) - - if (cached) { - return - } - - // arguments[0] (or `data`) contains the response body - const authorized = Encryption.isAuthorizedDevice({ - deviceId: legacyDeviceId - }) - const encryptedMessage = authorized - ? Encryption.encryptMessage({ - message: args[0] ? args[0] : {}, - deviceId: legacyDeviceId, - metadata: { - hash - } - }) - : args[0] - args[0] = JSON.stringify(encryptedMessage) - oldSend.apply(res, args) - } - } - if (deviceId) { res.send = (...args) => { if (args[0] && args[0].ciphertext && args[0].iv) { @@ -288,7 +252,7 @@ const server = program => { return randomField } - const newValue = await Encryption.generateRandomString(length) + const newValue = await ECC.generateRandomString(length) await Storage.setItem(fieldName, newValue) return newValue } @@ -440,14 +404,16 @@ const server = program => { }) } - if(process.env.ALLOW_UNLOCKED_LND === 'true'){ - const codes = await Storage.valuesWithKeyMatch(/^UnlockedAccessSecrets\//u) - if(codes.length === 0){ - const code = generateRandomString(12) + if (process.env.ALLOW_UNLOCKED_LND === 'true') { + const codes = await Storage.valuesWithKeyMatch( + /^UnlockedAccessSecrets\//u + ) + if (codes.length === 0) { + const code = ECC.generateRandomString(12) await Storage.setItem(`UnlockedAccessSecrets/${code}`, false) - logger.info("the access code is:"+code) - } else if(codes.length === 1 || codes[0] === false){ - logger.info("the access code is:"+codes[0]) + logger.info('the access code is:' + code) + } else if (codes.length === 1 || codes[0] === false) { + logger.info('the access code is:' + codes[0]) } } serverInstance.listen(serverPort, serverHost) diff --git a/utils/encryptionStore.js b/utils/encryptionStore.js deleted file mode 100644 index eb32f369..00000000 --- a/utils/encryptionStore.js +++ /dev/null @@ -1,181 +0,0 @@ -/** - * @prettier - */ -const Crypto = require('crypto') -const { Buffer } = require('buffer') -const logger = require('../config/log') - -const APIKeyPair = new Map() -const authorizedDevices = new Map() - -const nonEncryptedEvents = [ - 'ping', - 'disconnect', - 'IS_GUN_AUTH', - 'SET_LAST_SEEN_APP' -] - -const Encryption = { - /** - * @param {string} event - * @returns {boolean} - */ - isNonEncrypted: event => nonEncryptedEvents.includes(event), - /** - * @param {{ deviceId: string , message: string }} arg0 - */ - encryptKey: ({ deviceId, message }) => { - if (!authorizedDevices.has(deviceId)) { - throw { field: 'deviceId', message: 'Unknown Device ID' } - } - - const devicePublicKey = authorizedDevices.get(deviceId) - const data = Buffer.from(message) - const encryptedData = Crypto.publicEncrypt( - { - key: devicePublicKey, - padding: Crypto.constants.RSA_PKCS1_PADDING - }, - data - ) - - return encryptedData.toString('base64') - }, - /** - * @param {{ deviceId: string , message: string }} arg0 - */ - decryptKey: ({ deviceId, message }) => { - if (!authorizedDevices.has(deviceId)) { - throw { field: 'deviceId', message: 'Unknown Device ID' } - } - - const data = Buffer.from(message, 'base64') - const encryptedData = Crypto.privateDecrypt( - { - key: APIKeyPair.get(deviceId).privateKey, - padding: Crypto.constants.RSA_PKCS1_PADDING - }, - data - ) - - return encryptedData.toString() - }, - /** - * @param {{ deviceId: string , message: any , metadata?: any}} arg0 - */ - encryptMessage: ({ deviceId, message, metadata = {} }) => { - const parsedMessage = - typeof message === 'object' ? JSON.stringify(message) : message - const data = Buffer.from(parsedMessage) - const key = Crypto.randomBytes(32) - const iv = Crypto.randomBytes(16) - const encryptedKey = Encryption.encryptKey({ - deviceId, - message: key.toString('hex') - }) - const cipher = Crypto.createCipheriv('aes-256-cbc', key, iv) - const encryptedCipher = cipher.update(data) - const encryptedBuffer = Buffer.concat([ - Buffer.from(encryptedCipher), - Buffer.from(cipher.final()) - ]) - const encryptedData = encryptedBuffer.toString('base64') - const encryptedMessage = { - encryptedData, - encryptedKey, - iv: iv.toString('hex'), - metadata - } - - return encryptedMessage - }, - /** - * @param {{ message: string , key: string , iv: string }} arg0 - */ - decryptMessage: ({ message, key, iv }) => { - const data = Buffer.from(message, 'base64') - const cipher = Crypto.createDecipheriv( - 'aes-256-cbc', - Buffer.from(key, 'hex'), - Buffer.from(iv, 'hex') - ) - const decryptedCipher = cipher.update(data) - const decryptedBuffer = Buffer.concat([ - Buffer.from(decryptedCipher), - Buffer.from(cipher.final()) - ]) - const decryptedData = decryptedBuffer.toString() - - return decryptedData.toString() - }, - /** - * @param {{ deviceId: string }} arg0 - */ - isAuthorizedDevice: ({ deviceId }) => { - if (authorizedDevices.has(deviceId)) { - return true - } - - return false - }, - /** - * @param {{ deviceId: string , publicKey: string }} arg0 - */ - authorizeDevice: ({ deviceId, publicKey }) => - new Promise((resolve, reject) => { - authorizedDevices.set(deviceId, publicKey) - Crypto.generateKeyPair( - 'rsa', - { - modulusLength: 2048, - privateKeyEncoding: { - type: 'pkcs1', - format: 'pem' - }, - publicKeyEncoding: { - type: 'pkcs1', - format: 'pem' - } - }, - (err, publicKey, privateKey) => { - if (err) { - // @ts-ignore - logger.error(err) - reject(err) - return - } - - const exportedKey = { - publicKey, - privateKey - } - - APIKeyPair.set(deviceId, exportedKey) - resolve({ - success: true, - APIPublicKey: exportedKey.publicKey - }) - } - ) - }), - /** - * @param {{ deviceId: string }} arg0 - */ - unAuthorizeDevice: ({ deviceId }) => { - authorizedDevices.delete(deviceId) - }, - generateRandomString: (length = 16) => - new Promise((resolve, reject) => { - Crypto.randomBytes(length, (err, buffer) => { - if (err) { - reject(err) - return - } - - const token = buffer.toString('hex') - resolve(token) - }) - }) -} - -module.exports = Encryption