padd Message buffer for all outgoing messages (even opengroupv2)

pull/1604/head
Audric Ackermann 4 years ago
parent 63e66b2ac0
commit 7b96aba1bf
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -9,7 +9,13 @@ let tray = null;
function createTrayIcon(getMainWindow, messages) {
// A smaller icon is needed on macOS
const iconSize = process.platform === 'darwin' ? '16' : '256';
const iconNoNewMessages = path.join(__dirname, '..', 'images', 'session', `session_icon_${iconSize}.png`);
const iconNoNewMessages = path.join(
__dirname,
'..',
'images',
'session',
`session_icon_${iconSize}.png`
);
tray = new Tray(iconNoNewMessages);

@ -208,9 +208,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
return;
}
const isValidWithStoredInDB = Boolean(
await this.validatePasswordHash(oldPassword)
);
const isValidWithStoredInDB = Boolean(await this.validatePasswordHash(oldPassword));
if (!isValidWithStoredInDB) {
this.setState({
error: window.i18n('changePasswordInvalid'),

@ -17,6 +17,7 @@ import { KeyPairRequestManager } from './keyPairRequestManager';
import { requestEncryptionKeyPair } from '../session/group';
import { handleConfigurationMessage } from './configMessage';
import { ConversationTypeEnum } from '../models/conversation';
import { removeMessagePadding } from '../session/crypto/MessagePadding';
export async function handleContentMessage(envelope: EnvelopePlus) {
try {
@ -94,7 +95,7 @@ async function decryptForClosedGroup(envelope: EnvelopePlus, ciphertext: ArrayBu
}
window.log.info('ClosedGroup Message decrypted successfully with keyIndex:', keyIndex);
return unpad(decryptedContent);
return removeMessagePadding(decryptedContent);
} catch (e) {
/**
* If an error happened during the decoding,
@ -130,7 +131,7 @@ async function decryptForClosedGroup(envelope: EnvelopePlus, ciphertext: ArrayBu
* or a message sent to a closed group.
*
* We do not unpad the result here, as in the case of the keypair wrapper, there is not padding.
* Instead, it is the called who needs to unpad() the content.
* Instead, it is the called who needs to removeMessagePadding() the content.
*/
export async function decryptWithSessionProtocol(
envelope: EnvelopePlus,
@ -191,22 +192,6 @@ export async function decryptWithSessionProtocol(
return plaintext;
}
export function unpad(paddedData: ArrayBuffer): ArrayBuffer {
const paddedPlaintext = new Uint8Array(paddedData);
for (let i = paddedPlaintext.length - 1; i >= 0; i -= 1) {
if (paddedPlaintext[i] === 0x80) {
const plaintext = new Uint8Array(i);
plaintext.set(paddedPlaintext.subarray(0, i));
return plaintext.buffer;
} else if (paddedPlaintext[i] !== 0x00) {
throw new Error('Invalid padding');
}
}
throw new Error('Invalid padding');
}
export async function isBlocked(number: string) {
return BlockedNumberController.isBlockedAsync(number);
}
@ -227,7 +212,7 @@ async function decryptUnidentifiedSender(
);
// keep the await so the try catch works as expected
const retSessionProtocol = await decryptWithSessionProtocol(envelope, ciphertext, ecKeyPair);
return unpad(retSessionProtocol);
return removeMessagePadding(retSessionProtocol);
} catch (e) {
window.log.warn('decryptWithSessionProtocol for unidentified message throw:', e);
return null;

@ -9,7 +9,7 @@ import { processMessage } from '../session/snode_api/swarmPolling';
import { onError } from './errors';
// innerHandleContentMessage is only needed because of code duplication in handleDecryptedEnvelope...
import { handleContentMessage, innerHandleContentMessage, unpad } from './contentMessage';
import { handleContentMessage, innerHandleContentMessage } from './contentMessage';
import _, { noop } from 'lodash';
export { processMessage };
@ -36,6 +36,7 @@ import { OpenGroupMessageV2 } from '../opengroup/opengroupV2/OpenGroupMessageV2'
import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil';
import { handleMessageJob } from './queuedJob';
import { fromBase64ToArray } from '../session/utils/String';
import { removeMessagePadding } from '../session/crypto/MessagePadding';
// TODO: check if some of these exports no longer needed
@ -315,7 +316,8 @@ export async function handleOpenGroupV2Message(
return;
}
const dataUint = new Uint8Array(unpad(fromBase64ToArray(base64EncodedData)));
// Note: opengroup messages are not padded
const dataUint = new Uint8Array(removeMessagePadding(fromBase64ToArray(base64EncodedData)));
const decoded = SignalService.Content.decode(dataUint);

@ -6,29 +6,7 @@ import { fromHexToArray } from '../utils/String';
export { concatUInt8Array, getSodium };
import { getLatestClosedGroupEncryptionKeyPair } from '../../../ts/data/data';
import { UserUtils } from '../utils';
/**
* Add padding to a message buffer
* @param messageBuffer The buffer to add padding to.
*/
export function padPlainTextBuffer(messageBuffer: Uint8Array): Uint8Array {
const plaintext = new Uint8Array(getPaddedMessageLength(messageBuffer.byteLength + 1) - 1);
plaintext.set(new Uint8Array(messageBuffer));
plaintext[messageBuffer.byteLength] = 0x80;
return plaintext;
}
function getPaddedMessageLength(originalLength: number): number {
const messageLengthWithTerminator = originalLength + 1;
let messagePartCount = Math.floor(messageLengthWithTerminator / 160);
if (messageLengthWithTerminator % 160 !== 0) {
messagePartCount += 1;
}
return messagePartCount * 160;
}
import { addMessagePadding } from './MessagePadding';
type EncryptResult = {
envelopeType: SignalService.Envelope.Type;
@ -53,7 +31,7 @@ export async function encrypt(
throw new Error(`Invalid encryption type:${encryptionType}`);
}
const encryptForClosedGroup = encryptionType === EncryptionType.ClosedGroup;
const plainText = padPlainTextBuffer(plainTextBuffer);
const plainText = addMessagePadding(plainTextBuffer);
if (encryptForClosedGroup) {
window?.log?.info(

@ -0,0 +1,45 @@
/**
* Unpad the buffer from its padding.
* An error is thrown if there is no padding.
* A padded buffer is
* * whatever at start
* * ends with 0x80 and any number of 0x00 until the end
*/
export function removeMessagePadding(paddedData: ArrayBuffer): ArrayBuffer {
const paddedPlaintext = new Uint8Array(paddedData);
for (let i = paddedPlaintext.length - 1; i >= 0; i -= 1) {
if (paddedPlaintext[i] === 0x80) {
const plaintext = new Uint8Array(i);
plaintext.set(paddedPlaintext.subarray(0, i));
return plaintext.buffer;
} else if (paddedPlaintext[i] !== 0x00) {
throw new Error('Invalid padding');
}
}
throw new Error('Invalid padding');
}
/**
* Add padding to a message buffer
* @param messageBuffer The buffer to add padding to.
*/
export function addMessagePadding(messageBuffer: Uint8Array): Uint8Array {
const plaintext = new Uint8Array(getPaddedMessageLength(messageBuffer.byteLength + 1) - 1);
plaintext.set(new Uint8Array(messageBuffer));
plaintext[messageBuffer.byteLength] = 0x80;
return plaintext;
}
function getPaddedMessageLength(originalLength: number): number {
const messageLengthWithTerminator = originalLength + 1;
let messagePartCount = Math.floor(messageLengthWithTerminator / 160);
if (messageLengthWithTerminator % 160 !== 0) {
messagePartCount += 1;
}
return messagePartCount * 160;
}

@ -10,10 +10,10 @@ import { UserUtils } from '../utils';
import { OpenGroupRequestCommonType } from '../../opengroup/opengroupV2/ApiUtil';
import { postMessage } from '../../opengroup/opengroupV2/OpenGroupAPIV2';
import { OpenGroupMessageV2 } from '../../opengroup/opengroupV2/OpenGroupMessageV2';
import { padPlainTextBuffer } from '../crypto/MessageEncrypter';
import { fromUInt8ArrayToBase64 } from '../utils/String';
import { OpenGroupVisibleMessage } from '../messages/outgoing/visibleMessage/OpenGroupVisibleMessage';
import * as LokiMessageApi from './LokiMessageApi';
import { addMessagePadding } from '../crypto/MessagePadding';
// ================ Regular ================
@ -136,7 +136,8 @@ export async function sendToOpenGroupV2(
rawMessage: OpenGroupVisibleMessage,
roomInfos: OpenGroupRequestCommonType
): Promise<OpenGroupMessageV2> {
const paddedBody = padPlainTextBuffer(rawMessage.plainTextBuffer());
// we agreed to pad message for opengroupv2
const paddedBody = addMessagePadding(rawMessage.plainTextBuffer());
const v2Message = new OpenGroupMessageV2({
sentTimestamp: Date.now(),
sender: UserUtils.getOurPubKeyStrFromCache(),

@ -74,6 +74,7 @@ export class AttachmentUtils {
let attachmentData: ArrayBuffer;
// We don't pad attachments for opengroup as they are unencrypted
if (isRaw || openGroup) {
attachmentData = attachment.data;
} else {

@ -11,6 +11,7 @@ import { StringUtils, UserUtils } from '../../../../session/utils';
import chaiBytes from 'chai-bytes';
import { PubKey } from '../../../../session/types';
import { fromHex, toHex } from '../../../../session/utils/String';
import { addMessagePadding } from '../../../../session/crypto/MessagePadding';
chai.use(chaiBytes);
@ -187,7 +188,7 @@ describe('MessageEncrypter', () => {
const spy = sinon.spy(MessageEncrypter, 'encryptUsingSessionProtocol');
await MessageEncrypter.encrypt(TestUtils.generateFakePubKey(), data, EncryptionType.Fallback);
chai.expect(spy.callCount).to.be.equal(1);
const paddedData = MessageEncrypter.padPlainTextBuffer(data);
const paddedData = addMessagePadding(data);
const firstArgument = new Uint8Array(spy.args[0][1]);
chai.expect(firstArgument).to.deep.equal(paddedData);
spy.restore();

Loading…
Cancel
Save