[WIP] End-to-End encryption store completed

This commit is contained in:
emad-salah 2020-01-13 15:24:35 +01:00
parent bd53750ac3
commit 2a604edb9e
3 changed files with 91 additions and 9 deletions

View file

@ -5,9 +5,10 @@
*/ */
"use strict"; "use strict";
const Http = require("axios"); const Axios = require("axios");
const Crypto = require("crypto"); const Crypto = require("crypto");
const logger = require("winston"); const logger = require("winston");
const httpsAgent = require("https");
const responseTime = require("response-time"); const responseTime = require("response-time");
const getListPage = require("../utils/paginate"); const getListPage = require("../utils/paginate");
const auth = require("../services/auth/auth"); const auth = require("../services/auth/auth");
@ -19,12 +20,18 @@ const { unprotectedRoutes } = require("../utils/protectedRoutes");
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10; const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
// module.exports = (app) => { // module.exports = (app) => {
module.exports = ( module.exports = async (
app, app,
config, config,
mySocketsEvents, mySocketsEvents,
{ serverPort } { serverPort, CA, CA_KEY, usetls }
) => { ) => {
const Http = Axios.create({
httpsAgent: new httpsAgent.Agent({
ca: await FS.readFile(CA)
})
})
const sanitizeLNDError = (message = "") => const sanitizeLNDError = (message = "") =>
message.toLowerCase().includes("unknown") message.toLowerCase().includes("unknown")
? message ? message
@ -81,7 +88,7 @@ module.exports = (
const serviceStatus = await getAvailableService(); const serviceStatus = await getAvailableService();
const LNDStatus = serviceStatus; const LNDStatus = serviceStatus;
try { try {
const APIHealth = await Http.get(`http://localhost:${serverPort}/ping`); const APIHealth = await Http.get(`${usetls ? 'https' : 'http'}://localhost:${serverPort}/ping`);
const APIStatus = { const APIStatus = {
message: APIHealth.data, message: APIHealth.data,
responseTime: APIHealth.headers["x-response-time"], responseTime: APIHealth.headers["x-response-time"],
@ -92,6 +99,7 @@ module.exports = (
APIStatus APIStatus
}; };
} catch (err) { } catch (err) {
console.error(err);
const APIStatus = { const APIStatus = {
message: err.response.data, message: err.response.data,
responseTime: err.response.headers["x-response-time"], responseTime: err.response.headers["x-response-time"],
@ -259,6 +267,10 @@ module.exports = (
res.json({ msg: "OK" }); res.json({ msg: "OK" });
}); });
app.post("/api/security/exchangeKeys", (req, res) => {
})
app.get("/api/lnd/wallet/status", async (req, res) => { app.get("/api/lnd/wallet/status", async (req, res) => {
try { try {
const walletStatus = await walletExists(); const walletStatus = await walletExists();

View file

@ -125,12 +125,15 @@ const server = program => {
.send({ status: 500, errorMessage: "internal error" }); .send({ status: 500, errorMessage: "internal error" });
}); });
const CA = LightningServices.servicesConfig.lndCertPath
const CA_KEY = CA.replace("cert", "key")
const createServer = async () => { const createServer = async () => {
try { try {
if (program.usetls) { if (LightningServices.servicesConfig.lndCertPath && program.usetls) {
const [key, cert] = await Promise.all([ const [key, cert] = await Promise.all([
FS.readFile(program.usetls + "/key.pem"), FS.readFile(CA_KEY),
FS.readFile(program.usetls + "/cert.pem") FS.readFile(CA)
]); ]);
const httpsServer = Https.createServer({ key, cert }, app); const httpsServer = Https.createServer({ key, cert }, app);
@ -141,7 +144,10 @@ const server = program => {
return httpServer; return httpServer;
} catch (err) { } catch (err) {
logger.error(err.message); logger.error(err.message);
throw err; logger.error("An error has occurred while finding an LND cert to use to open an HTTPS server")
logger.warn("Falling back to opening an HTTP server...")
const httpServer = Http.Server(app);
return httpServer
} }
}; };
@ -164,7 +170,10 @@ const server = program => {
Sockets, Sockets,
{ {
serverHost: module.serverHost, serverHost: module.serverHost,
serverPort: module.serverPort serverPort: module.serverPort,
usetls: program.usetls,
CA,
CA_KEY
} }
); );

61
utils/encryptionStore.js Normal file
View file

@ -0,0 +1,61 @@
/**
* @prettier
*/
const Crypto = require('crypto')
const { Buffer } = require('buffer')
const APIKeyPair = new Map()
const authorizedDevices = new Map()
module.exports = {
encrypt: ({ 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(devicePublicKey, data)
return encryptedData.toString('base64')
},
decrypt: ({ deviceId, message }) => {
if (!authorizedDevices.has(deviceId)) {
throw { field: 'deviceId', message: 'Unknown Device ID' }
}
const data = Buffer.from(message, 'base64')
const encryptedData = Crypto.privateDecrypt(APIKeyPair.private, data)
return encryptedData.toString('base64')
},
authorizeDevice: ({ deviceId, publicKey }) =>
new Promise((resolve, reject) => {
if (authorizedDevices.has(deviceId)) {
const error = { success: false, message: 'Device already exists' }
reject(error)
return error
}
authorizedDevices.set(deviceId, publicKey)
Crypto.generateKeyPair(
'rsa',
{
modulusLength: 4096
},
(err, publicKey, privateKey) => {
if (err) {
reject({ field: 'APIKeyPair', errorMessage: err })
return err
}
APIKeyPair.set(deviceId, {
publicKey,
privateKey
})
resolve({ success: true })
}
)
}),
unAuthorizeDevice: ({ deviceId }) => {
authorizedDevices.delete(deviceId)
}
}