From 0221e7b8c0fb2776ff6b31920a938b88deaa558e Mon Sep 17 00:00:00 2001 From: Maxim Shishmarev Date: Tue, 24 Mar 2020 18:22:51 +1100 Subject: [PATCH] fix linter warnings --- app/sql.js | 48 ++------ js/modules/loki_message_api.js | 3 - js/modules/loki_rpc.js | 193 +++++++++++++++++---------------- js/modules/loki_snode_api.js | 150 +++++++++++++------------ libloki/crypto.js | 38 +++++-- libloki/storage.js | 2 +- preload.js | 6 +- 7 files changed, 222 insertions(+), 218 deletions(-) diff --git a/app/sql.js b/app/sql.js index 6b9874510..d8ecea1c7 100644 --- a/app/sql.js +++ b/app/sql.js @@ -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,55 +1511,27 @@ 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 => - - db.run( - `INSERT INTO ${GUARD_NODE_TABLE} ( + await Promise.all( + nodes.map(edkey => + db.run( + `INSERT INTO ${GUARD_NODE_TABLE} ( ed25519PubKey ) values ($ed25519PubKey)`, - { - $ed25519PubKey: edkey, - } + { + $ed25519PubKey: edkey, + } + ) ) - - )); + ); await db.run('END TRANSACTION;'); - - } async function getPrimaryDeviceFor(secondaryDevicePubKey) { diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index 7af0125b1..a26757159 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -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( diff --git a/js/modules/loki_rpc.js b/js/modules/loki_rpc.js index e7d6a524a..78f2414d9 100644 --- a/js/modules/loki_rpc.js +++ b/js/modules/loki_rpc.js @@ -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); - - return await encryptForNode(node, req_str); + const reqJson = { + ciphertext: dcodeIO.ByteBuffer.wrap(payload).toString('base64'), + ephemeral_key: StringView.arrayBufferToHex(ctx.ephemeral_key), + destination: nextNode.pubkey_ed25519, + }; -} + const reqStr = JSON.stringify(reqJson); -const BAD_PATH = "bad_path"; + return encryptForNode(node, reqStr); +}; -// May return false BAD_PATH, indicating that we should try a new -const sendOnionRequest = async (req_idx, nodePath, targetNode, plaintext) => { +const BAD_PATH = 'bad_path'; - log.info("Sending an onion request"); +// May return false BAD_PATH, indicating that we should try a new +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++; - - 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}`); - - const result = await sendOnionRequest(this_idx, path, targetNode, fetchOptions.body); - - if (result == BAD_PATH) { - log.error("[path] Error on the path"); + const thisIdx = onionReqIdx; + onionReqIdx += 1; + + 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}` + ); + + // 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'); 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?? diff --git a/js/modules/loki_snode_api.js b/js/modules/loki_snode_api.js index 6e8719461..eadd46da1 100644 --- a/js/modules/loki_snode_api.js +++ b/js/modules/loki_snode_api.js @@ -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', @@ -55,9 +52,9 @@ class LokiSnodeAPI { const fetchOptions = { method: 'POST', - body: JSON.stringify(body), + 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() { + 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"); - - const all_nodes = await this.getRandomSnodePool(); + const _ = window.Lodash; - log.info("[maxim] all nodes: ", all_nodes.length); + log.info('building new onion paths'); - 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 diff --git a/libloki/crypto.js b/libloki/crypto.js index fc3ebd2c5..d5a23c619 100644 --- a/libloki/crypto.js +++ b/libloki/crypto.js @@ -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 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 diff --git a/libloki/storage.js b/libloki/storage.js index 6c5666a14..9f057d17e 100644 --- a/libloki/storage.js +++ b/libloki/storage.js @@ -274,7 +274,7 @@ getSecondaryDevicesFor, getPrimaryDeviceMapping, getGuardNodes, - updateGuardNodes + updateGuardNodes, }; // Libloki protocol store diff --git a/preload.js b/preload.js index ebe87e1e3..eac87872a 100644 --- a/preload.js +++ b/preload.js @@ -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 = {