From 27165e8db2707b5623d4f19b448d591dc842c3e6 Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Fri, 2 Feb 2024 19:32:26 +0530 Subject: [PATCH] Pub key cache to speed up chat messages verification (#1081) * fix: minor fixes * fix: cache implementation for public keys --- .../restapi/src/lib/chat/helpers/crypto.ts | 47 +++++++++++++------ .../restapi/src/lib/chat/helpers/inbox.ts | 41 ++++++++++++---- .../src/lib/{pushapi => helpers}/cache.ts | 0 packages/restapi/src/lib/pushapi/PushAPI.ts | 3 +- 4 files changed, 67 insertions(+), 24 deletions(-) rename packages/restapi/src/lib/{pushapi => helpers}/cache.ts (100%) diff --git a/packages/restapi/src/lib/chat/helpers/crypto.ts b/packages/restapi/src/lib/chat/helpers/crypto.ts index 50e96fb34..796e3336d 100644 --- a/packages/restapi/src/lib/chat/helpers/crypto.ts +++ b/packages/restapi/src/lib/chat/helpers/crypto.ts @@ -26,6 +26,7 @@ import { IPGPHelper } from './pgp'; import { aesDecrypt } from './aes'; import { getEncryptedSecret } from './getEncryptedSecret'; import { getGroup } from '../getGroup'; +import { cache } from '../../helpers/cache'; const SIG_TYPE_V2 = 'eip712v2'; @@ -161,32 +162,50 @@ export const decryptFeeds = async ({ pgpHelper: PGP.IPGPHelper; env: ENV; }): Promise => { - let otherPeer: IUser; - let signatureValidationPubliKey: string; // To do signature verification it depends on who has sent the message - for (const feed of feeds) { - let gotOtherPeer = false; + const validateAndDecryptFeed = async (feed: IFeeds) => { + if (!pgpPrivateKey) { + throw new Error('Decrypted private key is necessary'); + } + if (feed.msg.encType !== 'PlainText') { - if (!pgpPrivateKey) { - throw Error('Decrypted private key is necessary'); - } - if (feed.msg.fromCAIP10 !== connectedUser.wallets.split(',')[0]) { - if (!gotOtherPeer) { - otherPeer = await getUser({ account: feed.msg.fromCAIP10, env }); - gotOtherPeer = true; + const senderCAIP10 = feed.msg.fromCAIP10; + const isSenderConnectedUser = + senderCAIP10 === connectedUser.wallets.split(',')[0]; + let publicKey: string; + + if (!isSenderConnectedUser) { + /** + * CACHE + */ + const cacheKey = `pgpPubKey-${senderCAIP10}`; + // Check if the pubkey is already in the cache + if (cache.has(cacheKey)) { + publicKey = cache.get(cacheKey); + } else { + // If not in cache, fetch from API + const otherPeer = await getUser({ account: senderCAIP10, env }); + // Cache the pubkey data + cache.set(cacheKey, otherPeer.publicKey); + publicKey = otherPeer.publicKey; } - signatureValidationPubliKey = otherPeer!.publicKey!; } else { - signatureValidationPubliKey = connectedUser.publicKey!; + publicKey = connectedUser.publicKey; } + feed.msg = await decryptAndVerifyMessage( feed.msg, - signatureValidationPubliKey, + publicKey, pgpPrivateKey, env, pgpHelper ); } + }; + + for (const feed of feeds) { + await validateAndDecryptFeed(feed); } + return feeds; }; diff --git a/packages/restapi/src/lib/chat/helpers/inbox.ts b/packages/restapi/src/lib/chat/helpers/inbox.ts index 66b36add8..c2e0314cd 100644 --- a/packages/restapi/src/lib/chat/helpers/inbox.ts +++ b/packages/restapi/src/lib/chat/helpers/inbox.ts @@ -5,6 +5,7 @@ import { IFeeds, IMessageIPFS, IUser, SpaceIFeeds } from '../../types'; import { get as getUser } from '../../user'; import { getCID } from '../ipfs'; import { decryptFeeds, decryptAndVerifyMessage } from './crypto'; +import { cache } from '../../helpers/cache'; type InboxListsType = { lists: IFeeds[]; @@ -78,7 +79,13 @@ export const getInboxLists = async ( } if (toDecrypt) - return decryptFeeds({ feeds, connectedUser, pgpPrivateKey, pgpHelper, env }); + return decryptFeeds({ + feeds, + connectedUser, + pgpPrivateKey, + pgpHelper, + env, + }); return feeds; }; @@ -123,7 +130,13 @@ export const getSpaceInboxLists = async ( } if (toDecrypt) - return decryptFeeds({ feeds, connectedUser, pgpPrivateKey, pgpHelper: PGP.PGPHelper, env }); + return decryptFeeds({ + feeds, + connectedUser, + pgpPrivateKey, + pgpHelper: PGP.PGPHelper, + env, + }); return feeds; }; @@ -170,11 +183,9 @@ export const decryptConversation = async (options: DecryptConverationType) => { pgpHelper = PGP.PGPHelper, env = Constants.ENV.PROD, } = options || {}; - let otherPeer: IUser; let signatureValidationPubliKey: string; // To do signature verification it depends on who has sent the message for (let i = 0; i < messages.length; i++) { const message = messages[i]; - let gotOtherPeer = false; if (message.encType !== 'PlainText') { // check if message is already decrypted if ( @@ -187,11 +198,23 @@ export const decryptConversation = async (options: DecryptConverationType) => { throw Error('Decrypted private key is necessary'); } if (message.fromCAIP10 !== connectedUser.wallets.split(',')[0]) { - if (!gotOtherPeer) { - otherPeer = await getUser({ account: message.fromCAIP10, env }); - gotOtherPeer = true; + /** + * CACHE + */ + const cacheKey = `pgpPubKey-${message.fromCAIP10}`; + // Check if the pubkey is already in the cache + if (cache.has(cacheKey)) { + signatureValidationPubliKey = cache.get(cacheKey); + } else { + // If not in cache, fetch from API + const otherPeer = await getUser({ + account: message.fromCAIP10, + env, + }); + // Cache the pubkey data + cache.set(cacheKey, otherPeer.publicKey); + signatureValidationPubliKey = otherPeer.publicKey; } - signatureValidationPubliKey = otherPeer!.publicKey; } else { signatureValidationPubliKey = connectedUser.publicKey; } @@ -200,7 +223,7 @@ export const decryptConversation = async (options: DecryptConverationType) => { signatureValidationPubliKey, pgpPrivateKey, env, - pgpHelper, + pgpHelper ); } } diff --git a/packages/restapi/src/lib/pushapi/cache.ts b/packages/restapi/src/lib/helpers/cache.ts similarity index 100% rename from packages/restapi/src/lib/pushapi/cache.ts rename to packages/restapi/src/lib/helpers/cache.ts diff --git a/packages/restapi/src/lib/pushapi/PushAPI.ts b/packages/restapi/src/lib/pushapi/PushAPI.ts index 0112368c3..5bea04700 100644 --- a/packages/restapi/src/lib/pushapi/PushAPI.ts +++ b/packages/restapi/src/lib/pushapi/PushAPI.ts @@ -19,7 +19,7 @@ import { ALPHA_FEATURE_CONFIG } from '../config'; import { Video } from './video'; import { isValidCAIP10NFTAddress } from '../helpers'; import { LRUCache } from 'lru-cache'; -import { cache } from './cache'; +import { cache } from '../helpers/cache'; export class PushAPI { private signer?: SignerType; @@ -307,6 +307,7 @@ export class PushAPI { this.profile = new Profile( this.account, this.env, + this.cache, this.decryptedPgpPvtKey, this.progressHook );