diff --git a/js/models/conversations.js b/js/models/conversations.js index 189345aa4..933c33176 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -1410,14 +1410,7 @@ } ); - const rawMessage = libsession.Utils.MessageUtils.toRawMessage( - destinationPubkey, - mediumGroupChatMessage - ); - await libsession.Sending.MessageSender.sendToMediumGroup( - rawMessage, - this.get('id') - ); + await libsession.getMessageQueue().send(destinationPubkey, mediumGroupChatMessage); } else { const closedGroupChatMessage = new libsession.Messages.Outgoing.ClosedGroupChatMessage( { diff --git a/ts/session/crypto/MessageEncrypter.ts b/ts/session/crypto/MessageEncrypter.ts index d3afce99c..bb550e7e8 100644 --- a/ts/session/crypto/MessageEncrypter.ts +++ b/ts/session/crypto/MessageEncrypter.ts @@ -2,6 +2,7 @@ import { EncryptionType } from '../types/EncryptionType'; import { SignalService } from '../../protobuf'; import { UserUtil } from '../../util'; import { CipherTextObject } from '../../../libtextsecure/libsignal-protocol'; +import { encryptWithSenderKey } from '../../session/medium_group/ratchet'; import { PubKey } from '../types'; /** @@ -29,6 +30,11 @@ function getPaddedMessageLength(originalLength: number): number { return messagePartCount * 160; } +type EncryptResult = { + envelopeType: SignalService.Envelope.Type; + cipherText: Uint8Array; +}; + /** * Encrypt `plainTextBuffer` with given `encryptionType` for `device`. * @@ -41,14 +47,11 @@ export async function encrypt( device: PubKey, plainTextBuffer: Uint8Array, encryptionType: EncryptionType -): Promise<{ - envelopeType: SignalService.Envelope.Type; - cipherText: Uint8Array; -}> { +): Promise { const plainText = padPlainTextBuffer(plainTextBuffer); if (encryptionType === EncryptionType.MediumGroup) { - throw new Error('MediumGroup should not be encypted here'); + return encryptForMediumGroup(device, plainTextBuffer); } const address = new window.libsignal.SignalProtocolAddress(device.key, 1); @@ -68,6 +71,47 @@ export async function encrypt( return encryptUsingSealedSender(device, innerCipherText); } +export async function encryptForMediumGroup( + device: PubKey, + plainTextBuffer: Uint8Array +): Promise { + + const ourKey = await UserUtil.getCurrentDevicePubKey() as string; + + // "Device" does not really make sense for medium groups, but + // that's where the group pubkey is currently stored + const groupId = device.key; + + const { ciphertext, keyIdx } = await encryptWithSenderKey( + plainTextBuffer, + groupId, + ourKey + ); + + // We should include ciphertext idx in the message + const content = SignalService.MediumGroupCiphertext.encode({ + ciphertext, + source: ourKey, + keyIdx, + }).finish(); + + // Encrypt for the group's identity key to hide source and key idx: + const { + ciphertext: ciphertextOuter, + ephemeralKey, + } = await window.libloki.crypto.encryptForPubkey(groupId, content); + + const contentOuter = SignalService.MediumGroupContent.encode({ + ciphertext: ciphertextOuter, + ephemeralKey: new Uint8Array(ephemeralKey), + }).finish(); + + const envelopeType = SignalService.Envelope.Type.MEDIUM_GROUP_CIPHERTEXT; + + return { envelopeType, cipherText: contentOuter }; + +} + async function encryptUsingSealedSender( device: PubKey, innerCipherText: CipherTextObject diff --git a/ts/session/sending/MessageSender.ts b/ts/session/sending/MessageSender.ts index db75d1609..6a03b9ffc 100644 --- a/ts/session/sending/MessageSender.ts +++ b/ts/session/sending/MessageSender.ts @@ -5,7 +5,6 @@ import { OpenGroupMessage } from '../messages/outgoing'; import { SignalService } from '../../protobuf'; import { UserUtil } from '../../util'; import { MessageEncrypter } from '../crypto'; -import { encryptWithSenderKey } from '../../session/medium_group/ratchet'; import pRetry from 'p-retry'; import { PubKey } from '../types'; @@ -53,56 +52,6 @@ export async function send( ); } -export async function sendToMediumGroup( - message: RawMessage, - groupId: string, - attempts: number = 3 -): Promise { - if (!canSendToSnode()) { - throw new Error('lokiMessageAPI is not initialized.'); - } - - const { plainTextBuffer, timestamp, ttl } = message; - - const ourKey = window.textsecure.storage.user.getNumber(); - - const { ciphertext, keyIdx } = await encryptWithSenderKey( - plainTextBuffer, - groupId, - ourKey - ); - const envelopeType = SignalService.Envelope.Type.MEDIUM_GROUP_CIPHERTEXT; - - // We should include ciphertext idx in the message - const content = SignalService.MediumGroupCiphertext.encode({ - ciphertext, - source: ourKey, - keyIdx, - }).finish(); - - // Encrypt for the group's identity key to hide source and key idx: - const { - ciphertext: ciphertextOuter, - ephemeralKey, - } = await window.libloki.crypto.encryptForPubkey(groupId, content); - - const contentOuter = SignalService.MediumGroupContent.encode({ - ciphertext: ciphertextOuter, - ephemeralKey: new Uint8Array(ephemeralKey), - }).finish(); - - const envelope = await buildEnvelope(envelopeType, timestamp, contentOuter); - const data = wrapEnvelope(envelope); - - return pRetry( - async () => - window.lokiMessageAPI.sendMessage(groupId, data, timestamp, ttl), - { - retries: Math.max(attempts - 1, 0), - factor: 1, - } - ); -} async function buildEnvelope( type: SignalService.Envelope.Type, diff --git a/ts/session/utils/Messages.ts b/ts/session/utils/Messages.ts index 269275373..5169afdd7 100644 --- a/ts/session/utils/Messages.ts +++ b/ts/session/utils/Messages.ts @@ -1,7 +1,7 @@ import { RawMessage } from '../types/RawMessage'; import { ContentMessage, - MediumGroupMessage, + MediumGroupChatMessage, SessionRequestMessage, } from '../messages/outgoing'; import { EncryptionType, PubKey } from '../types'; @@ -16,7 +16,7 @@ export async function toRawMessage( const plainTextBuffer = message.plainTextBuffer(); let encryption: EncryptionType; - if (message instanceof MediumGroupMessage) { + if (message instanceof MediumGroupChatMessage) { encryption = EncryptionType.MediumGroup; } else if (message instanceof SessionRequestMessage) { encryption = EncryptionType.Fallback;