fix linter warnings

pull/1000/head
Maxim Shishmarev 5 years ago
parent f2ef69f00d
commit 0221e7b8c0

@ -993,7 +993,6 @@ async function updateToLokiSchemaVersion3(currentVersion, instance) {
console.log('updateToLokiSchemaVersion3: starting...');
await instance.run('BEGIN TRANSACTION;');
await instance.run(
`INSERT INTO loki_schema (
version
@ -1505,7 +1504,6 @@ async function getSecondaryDevicesFor(primaryDevicePubKey) {
}
async function getGuardNodes() {
const nodes = await db.all(`SELECT ed25519PubKey FROM ${GUARD_NODE_TABLE};`);
if (!nodes) {
@ -1513,41 +1511,15 @@ async function getGuardNodes() {
}
return nodes;
}
async function createOrUpdatePreKey(data) {
const { id, recipient } = data;
if (!id) {
throw new Error('createOrUpdate: Provided data did not have a truthy id');
}
await db.run(
`INSERT OR REPLACE INTO ${PRE_KEYS_TABLE} (
id,
recipient,
json
) values (
$id,
$recipient,
$json
)`,
{
$id: id,
$recipient: recipient || '',
$json: objectToJSON(data),
}
);
}
async function updateGuardNodes(nodes) {
await db.run('BEGIN TRANSACTION;');
await db.run(`DELETE FROM ${GUARD_NODE_TABLE}`);
await Promise.all(nodes.map(edkey =>
await Promise.all(
nodes.map(edkey =>
db.run(
`INSERT INTO ${GUARD_NODE_TABLE} (
ed25519PubKey
@ -1556,12 +1528,10 @@ async function updateGuardNodes(nodes) {
$ed25519PubKey: edkey,
}
)
));
)
);
await db.run('END TRANSACTION;');
}
async function getPrimaryDeviceFor(secondaryDevicePubKey) {

@ -7,7 +7,6 @@ const { lokiRpc } = require('./loki_rpc');
const DEFAULT_CONNECTIONS = 3;
const MAX_ACCEPTABLE_FAILURES = 1;
const LOKI_LONGPOLL_HEADER = 'X-Loki-Long-Poll';
function sleepFor(time) {
return new Promise(resolve => {
@ -283,7 +282,6 @@ class LokiMessageAPI {
!stopPollingResult &&
successiveFailures < MAX_ACCEPTABLE_FAILURES
) {
// TODO: Revert back to using snode address instead of IP
try {
// in general, I think we want exceptions to bubble up
@ -339,7 +337,6 @@ class LokiMessageAPI {
// Always wait a bit as we are no longer long-polling
await sleepFor(Math.max(successiveFailures, 2) * 1000);
}
if (successiveFailures >= MAX_ACCEPTABLE_FAILURES) {
const remainingSwarmSnodes = await lokiSnodeAPI.unreachableNode(

@ -1,5 +1,5 @@
/* global log, libloki, textsecure, getStoragePubKey, lokiSnodeAPI, StringView,
libsignal, window, TextDecoder, TextEncoder, dcodeIO, process */
libsignal, window, TextDecoder, TextEncoder, dcodeIO, process, crypto */
const nodeFetch = require('node-fetch');
const https = require('https');
@ -12,9 +12,8 @@ const snodeHttpsAgent = new https.Agent({
const LOKI_EPHEMKEY_HEADER = 'X-Loki-EphemKey';
const endpointBase = '/storage_rpc/v1';
// Request index for debugging
let onion_req_idx = 0;
let onionReqIdx = 0;
const decryptResponse = async (response, address) => {
let plaintext = false;
@ -36,7 +35,6 @@ const decryptResponse = async (response, address) => {
const timeoutDelay = ms => new Promise(resolve => setTimeout(resolve, ms));
const encryptForNode = async (node, payload) => {
const textEncoder = new TextEncoder();
const plaintext = textEncoder.encode(payload);
@ -49,64 +47,72 @@ const encryptForNode = async (node, payload) => {
ephemeral.privKey
);
const salt = window.Signal.Crypto.bytesFromString("LOKI");
const salt = window.Signal.Crypto.bytesFromString('LOKI');
let key = await crypto.subtle.importKey('raw', salt, {name: 'HMAC', hash: {name: 'SHA-256'}}, false, ['sign']);
let symmetricKey = await crypto.subtle.sign( {name: 'HMAC', hash: 'SHA-256'}, key, ephemeralSecret);
const key = await crypto.subtle.importKey(
'raw',
salt,
{ name: 'HMAC', hash: { name: 'SHA-256' } },
false,
['sign']
);
const symmetricKey = await crypto.subtle.sign(
{ name: 'HMAC', hash: 'SHA-256' },
key,
ephemeralSecret
);
const ciphertext = await window.libloki.crypto.EncryptGCM(
symmetricKey,
plaintext
);
return {ciphertext, symmetricKey, "ephemeral_key": ephemeral.pubKey};
}
return { ciphertext, symmetricKey, ephemeral_key: ephemeral.pubKey };
};
// Returns the actual ciphertext, symmetric key that will be used
// for decryption, and an ephemeral_key to send to the next hop
const encryptForDestination = async (node, payload) => {
// Do we still need "headers"?
const req_str = JSON.stringify({"body": payload, "headers": ""});
const reqStr = JSON.stringify({ body: payload, headers: '' });
return await encryptForNode(node, req_str);
}
return encryptForNode(node, reqStr);
};
// `ctx` holds info used by `node` to relay further
const encryptForRelay = async (node, next_node, ctx) => {
const encryptForRelay = async (node, nextNode, ctx) => {
const payload = ctx.ciphertext;
const req_json = {
"ciphertext": dcodeIO.ByteBuffer.wrap(payload).toString('base64'),
"ephemeral_key": StringView.arrayBufferToHex(ctx.ephemeral_key),
"destination": next_node.pubkey_ed25519,
}
const req_str = JSON.stringify(req_json);
const reqJson = {
ciphertext: dcodeIO.ByteBuffer.wrap(payload).toString('base64'),
ephemeral_key: StringView.arrayBufferToHex(ctx.ephemeral_key),
destination: nextNode.pubkey_ed25519,
};
return await encryptForNode(node, req_str);
const reqStr = JSON.stringify(reqJson);
}
return encryptForNode(node, reqStr);
};
const BAD_PATH = "bad_path";
const BAD_PATH = 'bad_path';
// May return false BAD_PATH, indicating that we should try a new
const sendOnionRequest = async (req_idx, nodePath, targetNode, plaintext) => {
log.info("Sending an onion request");
const sendOnionRequest = async (reqIdx, nodePath, targetNode, plaintext) => {
log.info('Sending an onion request');
let ctx_1 = await encryptForDestination(targetNode, plaintext);
let ctx_2 = await encryptForRelay(nodePath[2], targetNode, ctx_1);
let ctx_3 = await encryptForRelay(nodePath[1], nodePath[2], ctx_2);
let ctx_4 = await encryptForRelay(nodePath[0], nodePath[1], ctx_3);
const ctx1 = await encryptForDestination(targetNode, plaintext);
const ctx2 = await encryptForRelay(nodePath[2], targetNode, ctx1);
const ctx3 = await encryptForRelay(nodePath[1], nodePath[2], ctx2);
const ctx4 = await encryptForRelay(nodePath[0], nodePath[1], ctx3);
const ciphertext_base64 = dcodeIO.ByteBuffer.wrap(ctx_4.ciphertext).toString('base64');
const ciphertextBase64 = dcodeIO.ByteBuffer.wrap(ctx4.ciphertext).toString(
'base64'
);
const payload = {
"ciphertext": ciphertext_base64,
"ephemeral_key": StringView.arrayBufferToHex(ctx_4.ephemeral_key),
}
ciphertext: ciphertextBase64,
ephemeral_key: StringView.arrayBufferToHex(ctx4.ephemeral_key),
};
const fetchOptions = {
method: 'POST',
@ -120,42 +126,44 @@ const sendOnionRequest = async (req_idx, nodePath, targetNode, plaintext) => {
const response = await nodeFetch(url, fetchOptions);
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
return await processOnionResponse(req_idx, response, ctx_1.symmetricKey, true);
}
return processOnionResponse(reqIdx, response, ctx1.symmetricKey, true);
};
// Process a response as it arrives from `nodeFetch`, handling
// http errors and attempting to decrypt the body with `shared_key`
const processOnionResponse = async (req_idx, response, shared_key, use_aes_gcm) => {
console.log(`(${req_idx}) [path] processing onion response`);
// http errors and attempting to decrypt the body with `sharedKey`
const processOnionResponse = async (reqIdx, response, sharedKey, useAesGcm) => {
log.info(`(${reqIdx}) [path] processing onion response`);
// detect SNode is not ready (not in swarm; not done syncing)
if (response.status === 503) {
console.warn("Got 503: snode not ready");
log.warn('Got 503: snode not ready');
return BAD_PATH;
}
if (response.status == 504) {
if (response.status === 504) {
log.warn('Got 504: Gateway timeout');
return BAD_PATH;
}
if (response.status == 404) {
if (response.status === 404) {
// Why would we get this error on testnet?
log.warn('Got 404: Gateway timeout');
return BAD_PATH;
}
if (response.status !== 200) {
log.warn('lokiRpc sendToProxy fetch unhandled error code:', response.status);
return;
log.warn(
'lokiRpc sendToProxy fetch unhandled error code:',
response.status
);
return false;
}
const ciphertext = await response.text();
if (!ciphertext) {
log.warn("[path]: Target node return empty ciphertext");
return;
log.warn('[path]: Target node return empty ciphertext');
return false;
}
let plaintext;
@ -166,27 +174,20 @@ const processOnionResponse = async (req_idx, response, shared_key, use_aes_gcm)
'base64'
).toArrayBuffer();
const decrypt_fn = use_aes_gcm ? window.libloki.crypto.DecryptGCM : window.libloki.crypto.DHDecrypt;
const decryptFn = useAesGcm
? window.libloki.crypto.DecryptGCM
: window.libloki.crypto.DHDecrypt;
const plaintextBuffer = await decrypt_fn(
shared_key,
ciphertextBuffer
);
const plaintextBuffer = await decryptFn(sharedKey, ciphertextBuffer);
const textDecoder = new TextDecoder();
plaintext = textDecoder.decode(plaintextBuffer);
} catch(e) {
log.error(
'lokiRpc sendToProxy decode error',
e.code,
e.message,
`from ${randSnode.ip}:${randSnode.port} ciphertext:`,
ciphertext
);
} catch (e) {
log.error(`(${reqIdx}) lokiRpc sendToProxy decode error`);
if (ciphertextBuffer) {
log.error('ciphertextBuffer', ciphertextBuffer);
}
return;
return false;
}
try {
@ -194,14 +195,11 @@ const processOnionResponse = async (req_idx, response, shared_key, use_aes_gcm)
// emulate nodeFetch response...
jsonRes.json = () => {
try {
let res = JSON.parse(jsonRes.body);
const res = JSON.parse(jsonRes.body);
return res;
} catch (e) {
log.error(
'lokiRpc sendToProxy parse error',
e.code,
e.message,
`from ${randSnode.ip}:${randSnode.port} json:`,
`(${reqIdx}) lokiRpc sendToProxy parse error json: `,
jsonRes.body
);
}
@ -213,22 +211,24 @@ const processOnionResponse = async (req_idx, response, shared_key, use_aes_gcm)
'lokiRpc sendToProxy parse error',
e.code,
e.message,
`from ${randSnode.ip}:${randSnode.port} json:`,
`json:`,
plaintext
);
return;
return false;
}
}
};
const sendToProxy = async (options = {}, targetNode, retryNumber = 0) => {
const _ = window.Lodash;
let snodePool = await lokiSnodeAPI.getRandomSnodePool();
const snodePool = await lokiSnodeAPI.getRandomSnodePool();
if (snodePool.length < 2) {
console.error("Not enough service nodes for a proxy request, only have: ", snodePool.length);
return;
log.error(
'Not enough service nodes for a proxy request, only have: ',
snodePool.length
);
return false;
}
// Making sure the proxy node is not the same as the target node:
@ -467,34 +467,43 @@ const lokiFetch = async (url, options = {}, targetNode = null) => {
};
try {
// Absence of targetNode indicates that we want a direct connection
// (e.g. to connect to a seed node for the first time)
if (window.lokiFeatureFlags.useOnionRequests && targetNode) {
// Loop until the result is not BAD_PATH
// eslint-disable-next-line no-constant-condition
while (true) {
// Get a path excluding `targetNode`:
// eslint-disable-next-line no-await-in-loop
const path = await lokiSnodeAPI.getOnionPath(targetNode);
const this_idx = onion_req_idx++;
const thisIdx = onionReqIdx;
onionReqIdx += 1;
log.info(`(${this_idx}) using path ${path[0].ip}:${path[0].port} -> ${path[1].ip}:${path[1].port} -> ${path[2].ip}:${path[2].port} => ${targetNode.ip}:${targetNode.port}`);
log.info(
`(${thisIdx}) using path ${path[0].ip}:${path[0].port} -> ${
path[1].ip
}:${path[1].port} -> ${path[2].ip}:${path[2].port} => ${
targetNode.ip
}:${targetNode.port}`
);
const result = await sendOnionRequest(this_idx, path, targetNode, fetchOptions.body);
// eslint-disable-next-line no-await-in-loop
const result = await sendOnionRequest(
thisIdx,
path,
targetNode,
fetchOptions.body
);
if (result == BAD_PATH) {
log.error("[path] Error on the path");
if (result === BAD_PATH) {
log.error('[path] Error on the path');
lokiSnodeAPI.markPathAsBad(path);
} else {
return result ? result.json() : false;
}
}
}
if (window.lokiFeatureFlags.useSnodeProxy && targetNode) {
const result = await sendToProxy(fetchOptions, targetNode);
// if not result, maybe we should throw??

@ -1,12 +1,11 @@
/* eslint-disable class-methods-use-this */
/* global window, textsecure, ConversationController, _, log, clearTimeout */
/* global window, textsecure, ConversationController, _, log, clearTimeout, process */
const is = require('@sindresorhus/is');
const { lokiRpc } = require('./loki_rpc');
const nodeFetch = require('node-fetch');
const RANDOM_SNODES_TO_USE_FOR_PUBKEY_SWARM = 3;
const RANDOM_SNODES_POOL_SIZE = 1024;
const SEED_NODE_RETRIES = 3;
class LokiSnodeAPI {
@ -25,27 +24,25 @@ class LokiSnodeAPI {
}
async getRandomSnodePool() {
if (this.randomSnodePool.length === 0) {
await this.refreshRandomPool();
}
return this.randomSnodePool;
}
async test_guard_node(snode) {
log.info("[maxim] Testing a candidate guard node ", snode);
async testGuardNode(snode) {
log.info('Testing a candidate guard node ', snode);
// Send a post request and make sure it is OK
const endpoint = "/storage_rpc/v1";
const endpoint = '/storage_rpc/v1';
const url = `https://${snode.ip}:${snode.port}${endpoint}`;
const our_pk = textsecure.storage.user.getNumber();
const pubKey = window.getStoragePubKey(our_pk); // truncate if testnet
const ourPK = textsecure.storage.user.getNumber();
const pubKey = window.getStoragePubKey(ourPK); // truncate if testnet
const method = 'get_snodes_for_pubkey';
const params = { pubKey }
const params = { pubKey };
const body = {
jsonrpc: '2.0',
id: '0',
@ -57,7 +54,7 @@ class LokiSnodeAPI {
method: 'POST',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
timeout: 10000 // 10s, we want a smaller timeout for testing
timeout: 10000, // 10s, we want a smaller timeout for testing
};
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
@ -68,7 +65,7 @@ class LokiSnodeAPI {
response = await nodeFetch(url, fetchOptions);
} catch (e) {
if (e.type === 'request-timeout') {
log.warn(`[maxim] test timeout for node,`, snode);
log.warn(`test timeout for node,`, snode);
}
return false;
} finally {
@ -83,152 +80,164 @@ class LokiSnodeAPI {
}
async selectGuardNodes() {
const _ = window.Lodash;
let node_pool = await this.getRandomSnodePool();
const nodePool = await this.getRandomSnodePool();
if (node_pool.length === 0) {
log.error(`Could not select guarn nodes: node pool is empty`)
if (nodePool.length === 0) {
log.error(`Could not select guarn nodes: node pool is empty`);
return [];
}
let shuffled = _.shuffle(node_pool);
const shuffled = _.shuffle(nodePool);
let guard_nodes = [];
let guardNodes = [];
const DESIRED_GUARD_COUNT = 3;
while (guard_nodes.length < 3) {
// The use of await inside while is intentional:
// we only want to repeat if the await fails
// eslint-disable-next-line-no-await-in-loop
while (guardNodes.length < 3) {
if (shuffled.length < DESIRED_GUARD_COUNT) {
log.error(`Not enought nodes in the pool`);
break;
}
const candidate_nodes = shuffled.splice(0, DESIRED_GUARD_COUNT);
const candidateNodes = shuffled.splice(0, DESIRED_GUARD_COUNT);
// Test all three nodes at once
const idx_ok = await Promise.all(candidate_nodes.map(n => this.test_guard_node(n)));
// eslint-disable-next-line no-await-in-loop
const idxOk = await Promise.all(
candidateNodes.map(n => this.testGuardNode(n))
);
const good_nodes = _.zip(idx_ok, candidate_nodes).filter(x => x[0]).map(x => x[1]);
const goodNodes = _.zip(idxOk, candidateNodes)
.filter(x => x[0])
.map(x => x[1]);
guard_nodes = _.concat(guard_nodes, good_nodes);
guardNodes = _.concat(guardNodes, goodNodes);
}
if (guard_nodes.length < DESIRED_GUARD_COUNT) {
log.error(`COULD NOT get enough guard nodes, only have: ${guard_nodes.length}`);
debugger;
if (guardNodes.length < DESIRED_GUARD_COUNT) {
log.error(
`COULD NOT get enough guard nodes, only have: ${guardNodes.length}`
);
}
console.log("new guard nodes: ", guard_nodes);
log.info('new guard nodes: ', guardNodes);
const edKeys = guard_nodes.map(n => n.pubkey_ed25519);
const edKeys = guardNodes.map(n => n.pubkey_ed25519);
await window.libloki.storage.updateGuardNodes(edKeys);
return guard_nodes;
return guardNodes;
}
async getOnionPath(toExclude = null) {
const _ = window.Lodash;
const good_paths = this.onionPaths.filter(x => !x.bad);
const goodPaths = this.onionPaths.filter(x => !x.bad);
if (good_paths.length < 2) {
log.error(`Must have at least 2 good onion paths, actual: ${good_paths.length}`);
if (goodPaths.length < 2) {
log.error(
`Must have at least 2 good onion paths, actual: ${goodPaths.length}`
);
await this.buildNewOnionPaths();
}
const paths = _.shuffle(good_paths);
const paths = _.shuffle(goodPaths);
if (!toExclude) {
return paths[0];
}
// Select a path that doesn't contain `toExclude`
const other_paths = paths.filter(path => !_.some(path, node => node.pubkey_ed25519 == toExclude.pubkey_ed25519));
const otherPaths = paths.filter(
path =>
!_.some(path, node => node.pubkey_ed25519 === toExclude.pubkey_ed25519)
);
if (other_paths.length === 0) {
if (otherPaths.length === 0) {
// This should never happen!
log.error("No onion paths available after filtering");
log.error('No onion paths available after filtering');
}
return other_paths[0].path;
return otherPaths[0].path;
}
async markPathAsBad(path) {
this.onionPaths.forEach(p => {
if (p.path == path) {
if (p.path === path) {
// eslint-disable-next-line no-param-reassign
p.bad = true;
}
})
});
}
async buildNewOnionPaths() {
// Note: this function may be called concurrently, so
// might consider blocking the other calls
const _ = window.Lodash;
log.info("building new onion paths");
log.info('building new onion paths');
const all_nodes = await this.getRandomSnodePool();
log.info("[maxim] all nodes: ", all_nodes.length);
if (this.guardNodes.length == 0) {
const allNodes = await this.getRandomSnodePool();
if (this.guardNodes.length === 0) {
// Not cached, load from DB
let nodes = await window.libloki.storage.getGuardNodes();
const nodes = await window.libloki.storage.getGuardNodes();
if (nodes.length == 0) {
log.warn("no guard nodes in DB. Will be selecting new guards nodes...");
if (nodes.length === 0) {
log.warn('no guard nodes in DB. Will be selecting new guards nodes...');
} else {
// We only store the nodes' keys, need to find full entries:
let ed_keys = nodes.map(x => x.ed25519PubKey);
this.guardNodes = all_nodes.filter(x => ed_keys.indexOf(x.pubkey_ed25519) !== -1);
const edKeys = nodes.map(x => x.ed25519PubKey);
this.guardNodes = allNodes.filter(
x => edKeys.indexOf(x.pubkey_ed25519) !== -1
);
if (this.guardNodes.length < ed_keys.length) {
log.warn(`could not find some guard nodes: ${this.guardNodes.length}/${ed_keys.length}`);
if (this.guardNodes.length < edKeys.length) {
log.warn(
`could not find some guard nodes: ${this.guardNodes.length}/${
edKeys.length
}`
);
}
}
// If guard nodes is still empty (the old nodes are now invalid), select new ones:
if (this.guardNodes.length == 0 || true) {
if (this.guardNodes.length === 0) {
this.guardNodes = await this.selectGuardNodes();
}
}
// TODO: select one guard node and 2 other nodes randomly
let other_nodes = _.difference(all_nodes, this.guardNodes);
let otherNodes = _.difference(allNodes, this.guardNodes);
if (other_nodes.length < 2) {
log.error("Too few nodes to build an onion path!");
if (otherNodes.length < 2) {
log.error('Too few nodes to build an onion path!');
return;
}
other_nodes = _.shuffle(other_nodes);
otherNodes = _.shuffle(otherNodes);
const guards = _.shuffle(this.guardNodes);
// Create path for every guard node:
// Each path needs 2 nodes in addition to the guard node:
const max_path = Math.floor(Math.min(guards.length, other_nodes.length / 2));
const maxPath = Math.floor(Math.min(guards.length, otherNodes.length / 2));
// TODO: might want to keep some of the existing paths
this.onionPaths = [];
for (let i = 0; i < max_path; i++) {
const path = [guards[i], other_nodes[i * 2], other_nodes[i * 2 + 1]];
this.onionPaths.push({path, bad: false});
for (let i = 0; i < maxPath; i += 1) {
const path = [guards[i], otherNodes[i * 2], otherNodes[i * 2 + 1]];
this.onionPaths.push({ path, bad: false });
}
log.info("Built onion paths: ", this.onionPaths);
log.info('Built onion paths: ', this.onionPaths);
}
async getRandomSnodeAddress() {
@ -253,7 +262,6 @@ class LokiSnodeAPI {
let timeoutTimer = null;
// private retry container
const trySeedNode = async (consecutiveErrors = 0) => {
// Removed limit until there is a way to get snode info
// for individual nodes (needed for guard nodes); this way
// we get all active nodes

@ -35,12 +35,21 @@
}
async function EncryptGCM(symmetricKey, plaintext) {
const nonce = crypto.getRandomValues(new Uint8Array(NONCE_LENGTH));
const key = await crypto.subtle.importKey('raw', symmetricKey, {name: 'AES-GCM'}, false, ['encrypt']);
const key = await crypto.subtle.importKey(
'raw',
symmetricKey,
{ name: 'AES-GCM' },
false,
['encrypt']
);
const ciphertext = await crypto.subtle.encrypt({name: 'AES-GCM', iv: nonce, tagLength: 128}, key, plaintext);
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: nonce, tagLength: 128 },
key,
plaintext
);
const ivAndCiphertext = new Uint8Array(
NONCE_LENGTH + ciphertext.byteLength
@ -53,14 +62,22 @@
}
async function DecryptGCM(symmetricKey, ivAndCiphertext) {
const nonce = ivAndCiphertext.slice(0, NONCE_LENGTH);
const ciphertext = ivAndCiphertext.slice(NONCE_LENGTH);
const key = await crypto.subtle.importKey('raw', symmetricKey, {name: 'AES-GCM'}, false, ['decrypt']);
return await crypto.subtle.decrypt({name: 'AES-GCM', iv: nonce}, key, ciphertext);
const key = await crypto.subtle.importKey(
'raw',
symmetricKey,
{ name: 'AES-GCM' },
false,
['decrypt']
);
return crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: nonce },
key,
ciphertext
);
}
async function DHDecrypt(symmetricKey, ivAndCiphertext) {
@ -137,7 +154,7 @@
}
function generateEphemeralKeyPair() {
let keys = libsignal.Curve.generateKeyPair();
const keys = libsignal.Curve.generateKeyPair();
// Signal protocol prepends with "0x05"
keys.pubKey = keys.pubKey.slice(1);
return keys;
@ -145,7 +162,6 @@
class LokiSnodeChannel {
constructor() {
this._ephemeralKeyPair = generateEphemeralKeyPair();
this._ephemeralPubKeyHex = StringView.arrayBufferToHex(
this._ephemeralKeyPair.pubKey

@ -274,7 +274,7 @@
getSecondaryDevicesFor,
getPrimaryDeviceMapping,
getGuardNodes,
updateGuardNodes
updateGuardNodes,
};
// Libloki protocol store

@ -420,7 +420,11 @@ Promise.prototype.ignore = function() {
this.then(() => {});
};
if (config.environment.includes('test') && !config.environment == "swarm-testing1" && !config.environment == "swarm-testing2") {
if (
config.environment.includes('test') &&
!config.environment === 'swarm-testing1' &&
!config.environment === 'swarm-testing2'
) {
const isWindows = process.platform === 'win32';
/* eslint-disable global-require, import/no-extraneous-dependencies */
window.test = {

Loading…
Cancel
Save