trigger new ratchet send on message sent success

send our new ratchet to all new members when we just sent a message
containing no senderKey in it.

an set but empty senderKey array should only be sent when a user left or
was removed.
pull/1364/head
Audric Ackermann 5 years ago
parent a05b6556b0
commit cfb9e65f30
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -1238,7 +1238,7 @@
const isOurDevice = await window.libsession.Protocols.MultiDeviceProtocol.isOurDevice( const isOurDevice = await window.libsession.Protocols.MultiDeviceProtocol.isOurDevice(
sentMessage.device sentMessage.device
); );
// FIXME this is not correct and will cause issues with syncing
// At this point the only way to check for medium // At this point the only way to check for medium
// group is by comparing the encryption type // group is by comparing the encryption type
const isMediumGroupMessage = const isMediumGroupMessage =
@ -1272,6 +1272,46 @@
sentMessage.device 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: * We should hit the notify endpoint for push notification only if:
* It's a one-to-one chat or a closed group * It's a one-to-one chat or a closed group

@ -10,12 +10,12 @@ import * as SenderKeyAPI from '../session/medium_group';
import { getChainKey } from '../session/medium_group/ratchet'; import { getChainKey } from '../session/medium_group/ratchet';
import { StringUtils } from '../session/utils'; import { StringUtils } from '../session/utils';
import { BufferType } from '../session/utils/String'; import { BufferType } from '../session/utils/String';
import { MultiDeviceProtocol } from '../session/protocols';
import { ConversationModel } from '../../js/models/conversations'; import { ConversationModel } from '../../js/models/conversations';
import { UserUtil } from '../util'; import { UserUtil } from '../util';
import { import {
createSenderKeyForGroup, createSenderKeyForGroup,
RatchetState, RatchetState,
shareSenderKeys,
} from '../session/medium_group/senderKeys'; } from '../session/medium_group/senderKeys';
const toHex = (d: BufferType) => StringUtils.decode(d, 'hex'); const toHex = (d: BufferType) => StringUtils.decode(d, 'hex');
@ -70,23 +70,6 @@ async function handleSenderKeyRequest(
await removeFromCache(envelope); await removeFromCache(envelope);
} }
export async function shareSenderKeys(
groupId: string,
recipientsPrimary: Array<string>,
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( async function handleSenderKey(
envelope: EnvelopePlus, envelope: EnvelopePlus,
groupUpdate: SignalService.MediumGroupUpdate groupUpdate: SignalService.MediumGroupUpdate

@ -4,7 +4,8 @@ import * as Types from './types';
import * as Utils from './utils'; import * as Utils from './utils';
import * as Sending from './sending'; import * as Sending from './sending';
import * as Constants from './constants'; import * as Constants from './constants';
import * as MediumGroup from './medium_group';
export * from './instance'; export * from './instance';
export { Messages, Utils, Protocols, Types, Sending, Constants }; export { Messages, Utils, Protocols, Types, Sending, Constants, MediumGroup };

@ -8,6 +8,7 @@ import {
RatchetState, RatchetState,
saveSenderKeys, saveSenderKeys,
saveSenderKeysInner, saveSenderKeysInner,
shareSenderKeys,
} from './senderKeys'; } from './senderKeys';
import { getChainKey } from './ratchet'; import { getChainKey } from './ratchet';
import { MultiDeviceProtocol } from '../protocols'; import { MultiDeviceProtocol } from '../protocols';
@ -20,7 +21,6 @@ import {
ExpirationTimerUpdateMessage, ExpirationTimerUpdateMessage,
MediumGroupCreateMessage, MediumGroupCreateMessage,
MediumGroupMessage, MediumGroupMessage,
Message,
} from '../messages/outgoing'; } from '../messages/outgoing';
import { MessageModel, MessageModelType } from '../../../js/models/messages'; import { MessageModel, MessageModelType } from '../../../js/models/messages';
import { getMessageQueue } from '../../session'; import { getMessageQueue } from '../../session';
@ -28,13 +28,13 @@ import { ConversationModel } from '../../../js/models/conversations';
import { MediumGroupUpdateMessage } from '../messages/outgoing/content/data/mediumgroup/MediumGroupUpdateMessage'; import { MediumGroupUpdateMessage } from '../messages/outgoing/content/data/mediumgroup/MediumGroupUpdateMessage';
import uuid from 'uuid'; import uuid from 'uuid';
import { BlockedNumberController } from '../../util/blockedNumberController'; import { BlockedNumberController } from '../../util/blockedNumberController';
import { shareSenderKeys } from '../../receiver/mediumGroups';
export { export {
createSenderKeyForGroup, createSenderKeyForGroup,
saveSenderKeys, saveSenderKeys,
saveSenderKeysInner, saveSenderKeysInner,
getChainKey, getChainKey,
shareSenderKeys,
}; };
const toHex = (d: BufferType) => StringUtils.decode(d, 'hex'); const toHex = (d: BufferType) => StringUtils.decode(d, 'hex');
@ -610,8 +610,6 @@ async function sendGroupUpdateForMedium(
(pkHex: string) => new Uint8Array(fromHex(pkHex)) (pkHex: string) => new Uint8Array(fromHex(pkHex))
); );
const remainingMembers = _.difference(groupUpdate.members, joiningMembers);
const params = { const params = {
timestamp: Date.now(), timestamp: Date.now(),
identifier: messageId || uuid(), identifier: messageId || uuid(),
@ -637,30 +635,6 @@ async function sendGroupUpdateForMedium(
); );
window.log.warn('Sending to groupUpdateMessage without senderKeys'); window.log.warn('Sending to groupUpdateMessage without senderKeys');
await getMessageQueue().sendToGroup(messageStripped); 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 { } else {
let senderKeys: Array<RatchetState>; let senderKeys: Array<RatchetState>;
if (joiningMembers.length > 0) { if (joiningMembers.length > 0) {

@ -1,6 +1,8 @@
import { PubKey } from '../types'; import { PubKey } from '../types';
import { StringUtils } from '../utils'; import { StringUtils } from '../utils';
import * as Data from '../../../js/modules/data'; import * as Data from '../../../js/modules/data';
import { MediumGroupResponseKeysMessage } from '../messages/outgoing';
import { getMessageQueue } from '..';
const toHex = (buffer: ArrayBuffer) => StringUtils.decode(buffer, 'hex'); const toHex = (buffer: ArrayBuffer) => StringUtils.decode(buffer, 'hex');
const fromHex = (hex: string) => StringUtils.encode(hex, 'hex'); const fromHex = (hex: string) => StringUtils.encode(hex, 'hex');
@ -86,3 +88,20 @@ export async function saveSenderKeys(
messageKeys messageKeys
); );
} }
export async function shareSenderKeys(
groupId: string,
recipientsPrimary: Array<string>,
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))
);
}

Loading…
Cancel
Save