From 399041c5b32a2a89b025daa8fa4ad0e056a8a6a1 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 13 Jul 2021 14:18:33 +1000 Subject: [PATCH] cache identity pair and add some per measure --- ts/receiver/closedGroups.ts | 4 ++++ ts/receiver/contentMessage.ts | 26 +++++++++++++++++++++++++- ts/receiver/receiver.ts | 3 +++ ts/session/snode_api/swarmPolling.ts | 5 +++++ ts/session/utils/User.ts | 8 +++++++- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/ts/receiver/closedGroups.ts b/ts/receiver/closedGroups.ts index 306ebd520..b9c5d6073 100644 --- a/ts/receiver/closedGroups.ts +++ b/ts/receiver/closedGroups.ts @@ -36,6 +36,7 @@ import { getSwarmPollingInstance } from '../session/snode_api'; import { MessageModel } from '../models/message'; import { updateConfirmModal } from '../state/ducks/modalDialog'; +import { perfEnd, perfStart } from '../session/utils/Performance'; export const distributingClosedGroupEncryptionKeyPairs = new Map(); @@ -409,11 +410,14 @@ async function handleClosedGroupEncryptionKeyPair( } let plaintext: Uint8Array; try { + perfStart(`encryptionKeyPair-${envelope.id}`); + const buffer = await decryptWithSessionProtocol( envelope, ourWrapper.encryptedKeyPair, ECKeyPair.fromKeyPair(ourKeyPair) ); + perfEnd(`encryptionKeyPair-${envelope.id}`, 'encryptionKeyPair'); if (!buffer || buffer.byteLength === 0) { throw new Error(); diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index 3f8ffb4ce..8ca06b0b4 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -28,7 +28,10 @@ export async function handleContentMessage(envelope: EnvelopePlus) { } else if (plaintext instanceof ArrayBuffer && plaintext.byteLength === 0) { return; } + perfStart(`innerHandleContentMessage-${envelope.id}`); + await innerHandleContentMessage(envelope, plaintext); + perfEnd(`innerHandleContentMessage-${envelope.id}`, 'innerHandleContentMessage'); } catch (e) { window?.log?.warn(e); } @@ -131,6 +134,7 @@ export async function decryptWithSessionProtocol( x25519KeyPair: ECKeyPair, isClosedGroup?: boolean ): Promise { + perfStart(`decryptWithSessionProtocol-${envelope.id}`); const recipientX25519PrivateKey = x25519KeyPair.privateKeyData; const hex = toHex(new Uint8Array(x25519KeyPair.publicKeyData)); @@ -147,6 +151,8 @@ export async function decryptWithSessionProtocol( new Uint8Array(recipientX25519PrivateKey) ); if (plaintextWithMetadata.byteLength <= signatureSize + ed25519PublicKeySize) { + perfEnd(`decryptWithSessionProtocol-${envelope.id}`, 'decryptWithSessionProtocol'); + throw new Error('Decryption failed.'); // throw Error.decryptionFailed; } @@ -167,11 +173,15 @@ export async function decryptWithSessionProtocol( ); if (!isValid) { + perfEnd(`decryptWithSessionProtocol-${envelope.id}`, 'decryptWithSessionProtocol'); + throw new Error('Invalid message signature.'); //throw Error.invalidSignature } // 4. ) Get the sender's X25519 public key const senderX25519PublicKey = sodium.crypto_sign_ed25519_pk_to_curve25519(senderED25519PublicKey); if (!senderX25519PublicKey) { + perfEnd(`decryptWithSessionProtocol-${envelope.id}`, 'decryptWithSessionProtocol'); + throw new Error('Decryption failed.'); // Error.decryptionFailed } @@ -181,6 +191,8 @@ export async function decryptWithSessionProtocol( } else { envelope.source = `05${toHex(senderX25519PublicKey)}`; } + perfEnd(`decryptWithSessionProtocol-${envelope.id}`, 'decryptWithSessionProtocol'); + return plaintext; } @@ -195,16 +207,25 @@ async function decryptUnidentifiedSender( window?.log?.info('received unidentified sender message'); try { const userX25519KeyPair = await UserUtils.getIdentityKeyPair(); + if (!userX25519KeyPair) { throw new Error('Failed to find User x25519 keypair from stage'); // noUserX25519KeyPair } + const ecKeyPair = ECKeyPair.fromArrayBuffer( userX25519KeyPair.pubKey, userX25519KeyPair.privKey ); + // keep the await so the try catch works as expected + perfStart(`decryptUnidentifiedSender-${envelope.id}`); + const retSessionProtocol = await decryptWithSessionProtocol(envelope, ciphertext, ecKeyPair); - return removeMessagePadding(retSessionProtocol); + + const ret = removeMessagePadding(retSessionProtocol); + perfEnd(`decryptUnidentifiedSender-${envelope.id}`, 'decryptUnidentifiedSender'); + + return ret; } catch (e) { window?.log?.warn('decryptWithSessionProtocol for unidentified message throw:', e); return null; @@ -241,12 +262,15 @@ async function decrypt(envelope: EnvelopePlus, ciphertext: ArrayBuffer): Promise return null; } + perfStart(`updateCache-${envelope.id}`); + await updateCache(envelope, plaintext).catch((error: any) => { window?.log?.error( 'decrypt failed to save decrypted message contents to cache:', error && error.stack ? error.stack : error ); }); + perfEnd(`updateCache-${envelope.id}`, 'updateCache'); return plaintext; } catch (error) { diff --git a/ts/receiver/receiver.ts b/ts/receiver/receiver.ts index 398a93fdd..f41e3d05e 100644 --- a/ts/receiver/receiver.ts +++ b/ts/receiver/receiver.ts @@ -37,6 +37,7 @@ import { fromBase64ToArray } from '../session/utils/String'; import { removeMessagePadding } from '../session/crypto/BufferPadding'; import { isDuplicateBasedOnHash } from './hashDuplicateFilter'; import { createTaskWithTimeout } from '../session/utils/TaskWithTimeout'; +import { perfEnd, perfStart } from '../session/utils/Performance'; // TODO: check if some of these exports no longer needed @@ -141,8 +142,10 @@ async function handleRequestDetail( // NOTE: Annoyngly we add plaintext to the cache // after we've already processed some of it (thus the // need to handle senderIdentity separately)... + perfStart(`addToCache-${envelope.id}`); await addToCache(envelope, plaintext); + perfEnd(`addToCache-${envelope.id}`, 'addToCache'); // TODO: This is the glue between the first and the last part of the // receiving pipeline refactor. It is to be implemented in the next PR. diff --git a/ts/session/snode_api/swarmPolling.ts b/ts/session/snode_api/swarmPolling.ts index 40a45c194..512b0c7e2 100644 --- a/ts/session/snode_api/swarmPolling.ts +++ b/ts/session/snode_api/swarmPolling.ts @@ -16,6 +16,7 @@ import { StringUtils, UserUtils } from '../../session/utils'; import { ConversationModel } from '../../models/conversation'; import { DURATION, SWARM_POLLING_TIMEOUT } from '../constants'; import { getConversationController } from '../conversations'; +import { perfEnd, perfStart } from '../utils/Performance'; type PubkeyToHash = { [key: string]: string }; @@ -213,8 +214,12 @@ export class SwarmPolling { }); } + perfStart(`handleSeenMessages-${pkStr}`); + const newMessages = await this.handleSeenMessages(messages); + perfEnd(`handleSeenMessages-${pkStr}`, 'handleSeenMessages'); + newMessages.forEach((m: Message) => { const options = isGroup ? { conversationId: pkStr } : {}; processMessage(m.data, options); diff --git a/ts/session/utils/User.ts b/ts/session/utils/User.ts index 71eeeb5c5..38644b5fc 100644 --- a/ts/session/utils/User.ts +++ b/ts/session/utils/User.ts @@ -46,13 +46,19 @@ export function getOurPubKeyFromCache(): PubKey { return PubKey.cast(ourNumber); } +let cachedIdentityKeyPair: KeyPair | undefined; + /** * This return the stored x25519 identity keypair for the current logged in user */ export async function getIdentityKeyPair(): Promise { + if (cachedIdentityKeyPair) { + return cachedIdentityKeyPair; + } const item = await getItemById('identityKey'); - return item?.value; + cachedIdentityKeyPair = item?.value; + return cachedIdentityKeyPair; } export async function getUserED25519KeyPair(): Promise {