[WIP] End-to-End encryption store completed
This commit is contained in:
parent
bd53750ac3
commit
2a604edb9e
3 changed files with 91 additions and 9 deletions
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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
61
utils/encryptionStore.js
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue