diff --git a/js/models/messages.js b/js/models/messages.js index d762d95c3..e9997fdcf 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -1238,7 +1238,7 @@ const isOurDevice = await window.libsession.Protocols.MultiDeviceProtocol.isOurDevice( sentMessage.device ); - + // FIXME this is not correct and will cause issues with syncing // At this point the only way to check for medium // group is by comparing the encryption type const isMediumGroupMessage = @@ -1272,6 +1272,46 @@ sentMessage.device ); + if (isMediumGroupMessage) { + // Delete all ratchets (it's important that this happens * after * sending out the update) + const shouldTriggerRatchetReset = + dataMessage && + dataMessage.mediumGroupUpdate && + dataMessage.mediumGroupUpdate.senderKeys && + dataMessage.mediumGroupUpdate.senderKeys.length === 0; + if (shouldTriggerRatchetReset) { + const { groupPublicKey } = dataMessage.mediumGroupUpdate; + const groupPubKeyUint = new Uint8Array( + groupPublicKey.toArrayBuffer() + ); + const groupId = libsession.Utils.StringUtils.decode( + groupPubKeyUint, + 'hex' + ); + await window.Signal.Data.removeAllClosedGroupRatchets(groupId); + // Send out the user's new ratchet to all members (minus the removed ones) using established channels + const ourPrimary = await window.Signal.Util.UserUtil.getPrimary(); + + const userSenderKey = await window.libsession.MediumGroup.createSenderKeyForGroup( + groupId, + ourPrimary + ); + + const currentMembers = this.getConversation().get('members'); + + window.log.warn( + 'Sharing our new senderKey with remainingMembers via established channels with', + currentMembers + ); + + await window.libsession.MediumGroup.shareSenderKeys( + groupId, + currentMembers, + userSenderKey + ); + } + } + /** * We should hit the notify endpoint for push notification only if: * • It's a one-to-one chat or a closed group diff --git a/ts/receiver/mediumGroups.ts b/ts/receiver/mediumGroups.ts index 28b14dacf..ddb3849b8 100644 --- a/ts/receiver/mediumGroups.ts +++ b/ts/receiver/mediumGroups.ts @@ -10,12 +10,12 @@ import * as SenderKeyAPI from '../session/medium_group'; import { getChainKey } from '../session/medium_group/ratchet'; import { StringUtils } from '../session/utils'; import { BufferType } from '../session/utils/String'; -import { MultiDeviceProtocol } from '../session/protocols'; import { ConversationModel } from '../../js/models/conversations'; import { UserUtil } from '../util'; import { createSenderKeyForGroup, RatchetState, + shareSenderKeys, } from '../session/medium_group/senderKeys'; const toHex = (d: BufferType) => StringUtils.decode(d, 'hex'); @@ -70,23 +70,6 @@ async function handleSenderKeyRequest( await removeFromCache(envelope); } -export async function shareSenderKeys( - groupId: string, - recipientsPrimary: Array, - senderKey: RatchetState -) { - const message = new MediumGroupResponseKeysMessage({ - timestamp: Date.now(), - groupId, - senderKey, - }); - - const recipients = recipientsPrimary.map(pk => PubKey.cast(pk)); - await Promise.all( - recipients.map(pk => getMessageQueue().sendUsingMultiDevice(pk, message)) - ); -} - async function handleSenderKey( envelope: EnvelopePlus, groupUpdate: SignalService.MediumGroupUpdate diff --git a/ts/session/index.ts b/ts/session/index.ts index c2a115733..1db6e3736 100644 --- a/ts/session/index.ts +++ b/ts/session/index.ts @@ -4,7 +4,8 @@ import * as Types from './types'; import * as Utils from './utils'; import * as Sending from './sending'; import * as Constants from './constants'; +import * as MediumGroup from './medium_group'; export * from './instance'; -export { Messages, Utils, Protocols, Types, Sending, Constants }; +export { Messages, Utils, Protocols, Types, Sending, Constants, MediumGroup }; diff --git a/ts/session/medium_group/index.ts b/ts/session/medium_group/index.ts index 5a79c84b2..ac00cfc7b 100644 --- a/ts/session/medium_group/index.ts +++ b/ts/session/medium_group/index.ts @@ -8,6 +8,7 @@ import { RatchetState, saveSenderKeys, saveSenderKeysInner, + shareSenderKeys, } from './senderKeys'; import { getChainKey } from './ratchet'; import { MultiDeviceProtocol } from '../protocols'; @@ -20,7 +21,6 @@ import { ExpirationTimerUpdateMessage, MediumGroupCreateMessage, MediumGroupMessage, - Message, } from '../messages/outgoing'; import { MessageModel, MessageModelType } from '../../../js/models/messages'; import { getMessageQueue } from '../../session'; @@ -28,13 +28,13 @@ import { ConversationModel } from '../../../js/models/conversations'; import { MediumGroupUpdateMessage } from '../messages/outgoing/content/data/mediumgroup/MediumGroupUpdateMessage'; import uuid from 'uuid'; import { BlockedNumberController } from '../../util/blockedNumberController'; -import { shareSenderKeys } from '../../receiver/mediumGroups'; export { createSenderKeyForGroup, saveSenderKeys, saveSenderKeysInner, getChainKey, + shareSenderKeys, }; const toHex = (d: BufferType) => StringUtils.decode(d, 'hex'); @@ -610,8 +610,6 @@ async function sendGroupUpdateForMedium( (pkHex: string) => new Uint8Array(fromHex(pkHex)) ); - const remainingMembers = _.difference(groupUpdate.members, joiningMembers); - const params = { timestamp: Date.now(), identifier: messageId || uuid(), @@ -637,30 +635,6 @@ async function sendGroupUpdateForMedium( ); window.log.warn('Sending to groupUpdateMessage without senderKeys'); await getMessageQueue().sendToGroup(messageStripped); - - getMessageQueue().events.addListener('success', async message => { - if (message.identifier === params.identifier) { - // console.log('Our first message encrypted with old sk is sent.'); - // Delete all ratchets (it's important that this happens * after * sending out the update) - await Data.removeAllClosedGroupRatchets(groupId); - if (isUserLeaving) { - // nothing to do on desktop - } else { - // Send out the user's new ratchet to all members (minus the removed ones) using established channels - const userSenderKey = await createSenderKeyForGroup( - groupId, - ourPrimary - ); - window.log.warn( - 'Sharing our new senderKey with remainingMembers via message', - remainingMembers, - userSenderKey - ); - - await shareSenderKeys(groupId, remainingMembers, userSenderKey); - } - } - }); } else { let senderKeys: Array; if (joiningMembers.length > 0) { diff --git a/ts/session/medium_group/senderKeys.ts b/ts/session/medium_group/senderKeys.ts index 5c645e557..b48a2f17b 100644 --- a/ts/session/medium_group/senderKeys.ts +++ b/ts/session/medium_group/senderKeys.ts @@ -1,6 +1,8 @@ import { PubKey } from '../types'; import { StringUtils } from '../utils'; import * as Data from '../../../js/modules/data'; +import { MediumGroupResponseKeysMessage } from '../messages/outgoing'; +import { getMessageQueue } from '..'; const toHex = (buffer: ArrayBuffer) => StringUtils.decode(buffer, 'hex'); const fromHex = (hex: string) => StringUtils.encode(hex, 'hex'); @@ -86,3 +88,20 @@ export async function saveSenderKeys( messageKeys ); } + +export async function shareSenderKeys( + groupId: string, + recipientsPrimary: Array, + senderKey: RatchetState +) { + const message = new MediumGroupResponseKeysMessage({ + timestamp: Date.now(), + groupId, + senderKey, + }); + + const recipients = recipientsPrimary.map(pk => PubKey.cast(pk)); + await Promise.all( + recipients.map(pk => getMessageQueue().sendUsingMultiDevice(pk, message)) + ); +}