Encrypted LND Sockets

This commit is contained in:
emad-salah 2020-05-27 00:26:02 +00:00
parent 643443434d
commit 9dc028d8fb

View file

@ -1,67 +1,169 @@
/** @prettier */
// app/sockets.js
const logger = require("winston");
const LightningServices = require("../utils/lightningServices");
const logger = require('winston')
const Encryption = require('../utils/encryptionStore')
const LightningServices = require('../utils/lightningServices')
module.exports = (
/** @type {import('socket.io').Server} */
io
) => {
const Mediator = require("../services/gunDB/Mediator/index.js");
const Mediator = require('../services/gunDB/Mediator/index.js')
// This should be used for encrypting and emitting your data
const emitEncryptedEvent = ({ eventName, data, socket }) => {
try {
if (Encryption.isNonEncrypted(eventName)) {
return socket.emit(eventName, data)
}
const deviceId = socket.handshake.query['x-shockwallet-device-id']
const authorized = Encryption.isAuthorizedDevice({ deviceId })
if (!deviceId) {
throw {
field: 'deviceId',
message: 'Please specify a device ID'
}
}
if (!authorized) {
throw {
field: 'deviceId',
message: 'Please exchange keys with the API before using the socket'
}
}
const encryptedMessage = Encryption.encryptMessage({
message: data,
deviceId
})
return socket.emit(eventName, encryptedMessage)
} catch (err) {
logger.error(
`[SOCKET] An error has occurred while encrypting an event (${eventName}):`,
err
)
return socket.emit('encryption:error', err)
}
}
const parseJSON = data => {
try {
if (typeof data === 'string') {
return JSON.parse(data)
}
return data
} catch (err) {
return data
}
}
const decryptEvent = ({ eventName, data, socket }) => {
try {
const deviceId = socket.handshake.query['x-shockwallet-device-id']
if (Encryption.isNonEncrypted(eventName)) {
return data
}
if (!data) {
return data
}
const parsedData = parseJSON(data)
if (!deviceId) {
throw {
field: 'deviceId',
message: 'Please specify a device ID'
}
}
if (!Encryption.isAuthorizedDevice({ deviceId })) {
throw {
field: 'deviceId',
message: 'Please exchange keys with the API before using the socket'
}
}
const decryptedKey = Encryption.decryptKey({
deviceId,
message: parsedData.encryptedKey
})
const decryptedMessage = Encryption.decryptMessage({
message: parsedData.encryptedData,
key: decryptedKey,
iv: parsedData.iv
})
const decryptedData = JSON.parse(decryptedMessage)
return decryptedData
} catch (err) {
logger.error(
`[SOCKET] An error has occurred while decrypting an event (${eventName}):`,
err
)
return socket.emit('encryption:error', err)
}
}
const onNewInvoice = socket => {
const { lightning } = LightningServices.services;
logger.warn("Subscribing to invoices socket...")
const stream = lightning.subscribeInvoices({});
stream.on("data", data => {
logger.info("[SOCKET] New invoice data:", data);
socket.emit("invoice:new", data)
const { lightning } = LightningServices.services
logger.warn('Subscribing to invoices socket...')
const stream = lightning.subscribeInvoices({})
stream.on('data', data => {
logger.info('[SOCKET] New invoice data:', data)
emitEncryptedEvent({ eventName: 'invoice:new', data, socket })
})
stream.on("end", () => {
logger.info("New invoice stream ended, starting a new one...")
onNewInvoice(socket);
stream.on('end', () => {
logger.info('New invoice stream ended, starting a new one...')
onNewInvoice(socket)
})
stream.on("error", err => {
logger.error("New invoice stream error:", err);
stream.on('error', err => {
logger.error('New invoice stream error:', err)
})
stream.on("status", status => {
logger.error("New invoice stream status:", status);
stream.on('status', status => {
logger.warn('New invoice stream status:', status)
if (status.code === 14) {
onNewInvoice(socket);
onNewInvoice(socket)
}
})
}
const onNewTransaction = socket => {
const { lightning } = LightningServices.services;
const stream = lightning.subscribeTransactions({});
logger.warn("Subscribing to transactions socket...")
stream.on("data", data => {
logger.info("[SOCKET] New transaction data:", data);
socket.emit("transaction:new", data)
const { lightning } = LightningServices.services
const stream = lightning.subscribeTransactions({})
logger.warn('Subscribing to transactions socket...')
stream.on('data', data => {
logger.info('[SOCKET] New transaction data:', data)
emitEncryptedEvent({ eventName: 'transaction:new', data, socket })
})
stream.on("end", () => {
logger.info("New invoice stream ended, starting a new one...")
onNewTransaction(socket);
stream.on('end', () => {
logger.info('New invoice stream ended, starting a new one...')
onNewTransaction(socket)
})
stream.on("error", err => {
logger.error("New invoice stream error:", err);
stream.on('error', err => {
logger.error('New invoice stream error:', err)
})
stream.on("status", status => {
logger.error("New invoice stream status:", status);
stream.on('status', status => {
logger.error('New invoice stream status:', status)
if (status.code === 14) {
onNewTransaction(socket);
onNewTransaction(socket)
}
})
}
io.on("connection", socket => {
io.on('connection', socket => {
logger.info(`io.onconnection`)
logger.info("socket.handshake", socket.handshake);
logger.info('socket.handshake', socket.handshake)
/** printing out the client who joined */
logger.info("New socket client connected (id=" + socket.id + ").");
logger.info('New socket client connected (id=' + socket.id + ').')
const isOneTimeUseSocket = !!socket.handshake.query.IS_GUN_AUTH
const isLNDSocket = !!socket.handshake.query.IS_LND_SOCKET
@ -92,18 +194,18 @@ module.exports = (
logger.info('New socket is NOT one time use')
// this is where we create the websocket connection
// with the GunDB service.
Mediator.createMediator(socket);
Mediator.createMediator(socket)
if (isLNDSocket) {
onNewInvoice(socket);
onNewTransaction(socket);
onNewInvoice(socket)
onNewTransaction(socket)
}
/** listening if client has disconnected */
socket.on("disconnect", () => {
logger.info("client disconnected (id=" + socket.id + ").");
});
socket.on('disconnect', () => {
logger.info('client disconnected (id=' + socket.id + ').')
})
}
})
return io;
};
return io
}