diff --git a/src/services/nativeMessaging.service.ts b/src/services/nativeMessaging.service.ts index a594c953de..029aa61a77 100644 --- a/src/services/nativeMessaging.service.ts +++ b/src/services/nativeMessaging.service.ts @@ -16,7 +16,7 @@ const MessageValidTimeout = 10 * 1000; const EncryptionAlgorithm = 'sha1'; export class NativeMessagingService { - private sharedSecret: any; + private sharedSecrets = new Map(); constructor(private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService, private platformUtilService: PlatformUtilsService, private logService: LogService, private i18nService: I18nService, @@ -26,7 +26,9 @@ export class NativeMessagingService { }); } - private async messageHandler(rawMessage: any) { + private async messageHandler(msg: any) { + const appId = msg.appId; + const rawMessage = msg.message; // Request to setup secure encryption if (rawMessage.command === 'setupEncryption') { @@ -50,15 +52,15 @@ export class NativeMessagingService { return; } - this.secureCommunication(remotePublicKey); + this.secureCommunication(remotePublicKey, appId); return; } - const message = JSON.parse(await this.cryptoService.decryptToUtf8(rawMessage, this.sharedSecret)); + const message = JSON.parse(await this.cryptoService.decryptToUtf8(rawMessage, this.sharedSecrets.get(appId))); // Shared secret is invalidated, force re-authentication if (message == null) { - ipcRenderer.send('nativeMessagingReply', {command: 'invalidateEncryption'}); + ipcRenderer.send('nativeMessagingReply', {command: 'invalidateEncryption', appId: appId}); return; } @@ -70,14 +72,14 @@ export class NativeMessagingService { switch (message.command) { case 'biometricUnlock': if (! this.platformUtilService.supportsBiometric()) { - return this.send({command: 'biometricUnlock', response: 'not supported'}); + return this.send({command: 'biometricUnlock', response: 'not supported'}, appId); } const response = await this.platformUtilService.authenticateBiometric(); if (response) { - this.send({command: 'biometricUnlock', response: 'unlocked', keyB64: (await this.cryptoService.getKey()).keyB64}); + this.send({command: 'biometricUnlock', response: 'unlocked', keyB64: (await this.cryptoService.getKey()).keyB64}, appId); } else { - this.send({command: 'biometricUnlock', response: 'canceled'}); + this.send({command: 'biometricUnlock', response: 'canceled'}, appId); } break; @@ -86,19 +88,19 @@ export class NativeMessagingService { } } - private async send(message: any) { + private async send(message: any, appId: string) { message.timestamp = Date.now(); - const encrypted = await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecret); + const encrypted = await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecrets.get(appId)); - ipcRenderer.send('nativeMessagingReply', encrypted); + ipcRenderer.send('nativeMessagingReply', {appId: appId, message: encrypted}); } - private async secureCommunication(remotePublicKey: ArrayBuffer) { + private async secureCommunication(remotePublicKey: ArrayBuffer, appId: string) { const secret = await this.cryptoFunctionService.randomBytes(64); - this.sharedSecret = new SymmetricCryptoKey(secret); + this.sharedSecrets.set(appId, new SymmetricCryptoKey(secret)); const encryptedSecret = await this.cryptoFunctionService.rsaEncrypt(secret, remotePublicKey, EncryptionAlgorithm); - ipcRenderer.send('nativeMessagingReply', {command: 'setupEncryption', sharedSecret: Utils.fromBufferToB64(encryptedSecret)}); + ipcRenderer.send('nativeMessagingReply', {appId: appId, command: 'setupEncryption', sharedSecret: Utils.fromBufferToB64(encryptedSecret)}); } }