1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-02-17 01:31:25 +01:00

Add support for communicating with multiple extensions at the same time

This commit is contained in:
Hinton 2020-12-16 15:42:46 +01:00
parent ac870ef31a
commit c13d6f810e

View File

@ -16,7 +16,7 @@ const MessageValidTimeout = 10 * 1000;
const EncryptionAlgorithm = 'sha1'; const EncryptionAlgorithm = 'sha1';
export class NativeMessagingService { export class NativeMessagingService {
private sharedSecret: any; private sharedSecrets = new Map<string, SymmetricCryptoKey>();
constructor(private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService, constructor(private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService,
private platformUtilService: PlatformUtilsService, private logService: LogService, private i18nService: I18nService, 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 // Request to setup secure encryption
if (rawMessage.command === 'setupEncryption') { if (rawMessage.command === 'setupEncryption') {
@ -50,15 +52,15 @@ export class NativeMessagingService {
return; return;
} }
this.secureCommunication(remotePublicKey); this.secureCommunication(remotePublicKey, appId);
return; 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 // Shared secret is invalidated, force re-authentication
if (message == null) { if (message == null) {
ipcRenderer.send('nativeMessagingReply', {command: 'invalidateEncryption'}); ipcRenderer.send('nativeMessagingReply', {command: 'invalidateEncryption', appId: appId});
return; return;
} }
@ -70,14 +72,14 @@ export class NativeMessagingService {
switch (message.command) { switch (message.command) {
case 'biometricUnlock': case 'biometricUnlock':
if (! this.platformUtilService.supportsBiometric()) { 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(); const response = await this.platformUtilService.authenticateBiometric();
if (response) { 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 { } else {
this.send({command: 'biometricUnlock', response: 'canceled'}); this.send({command: 'biometricUnlock', response: 'canceled'}, appId);
} }
break; break;
@ -86,19 +88,19 @@ export class NativeMessagingService {
} }
} }
private async send(message: any) { private async send(message: any, appId: string) {
message.timestamp = Date.now(); 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); 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); 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)});
} }
} }