add attachment padding

pull/1534/head
Audric Ackermann 4 years ago
parent 6dd166d7d4
commit 0228cd5115
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -3,6 +3,7 @@ import _ from 'lodash';
import { MessageModel } from '../models/message';
import { saveMessage } from '../../ts/data/data';
import { fromBase64ToArrayBuffer } from '../session/utils/String';
import { AttachmentUtils } from '../session/utils';
export async function downloadAttachment(attachment: any) {
const serverUrl = new URL(attachment.url).origin;
@ -70,9 +71,16 @@ export async function downloadAttachment(attachment: any) {
);
if (!size || size !== data.byteLength) {
throw new Error(
`downloadAttachment: Size ${size} did not match downloaded attachment size ${data.byteLength}`
);
// we might have padding, check that all the remaining bytes are padding bytes
// otherwise we have an error.
if (AttachmentUtils.isLeftOfBufferPaddingOnly(data, size)) {
// we can safely remove the padding
data = data.slice(0, size);
} else {
throw new Error(
`downloadAttachment: Size ${size} did not match downloaded attachment size ${data.byteLength}`
);
}
}
}

@ -14,6 +14,7 @@ interface UploadParams {
openGroup?: OpenGroup;
isAvatar?: boolean;
isRaw?: boolean;
shouldPad?: boolean;
}
interface RawPreview {
@ -37,6 +38,8 @@ interface RawQuote {
// tslint:disable-next-line: no-unnecessary-class
export class AttachmentUtils {
public static readonly PADDING_BYTE = 0;
private constructor() {}
public static getDefaultServer(): LokiAppDotNetServerInterface {
@ -44,7 +47,13 @@ export class AttachmentUtils {
}
public static async upload(params: UploadParams): Promise<AttachmentPointer> {
const { attachment, openGroup, isAvatar = false, isRaw = false } = params;
const {
attachment,
openGroup,
isAvatar = false,
isRaw = false,
shouldPad = false,
} = params;
if (typeof attachment !== 'object' || attachment == null) {
throw new Error('Invalid attachment passed.');
}
@ -83,8 +92,12 @@ export class AttachmentUtils {
server = this.getDefaultServer();
pointer.key = new Uint8Array(crypto.randomBytes(64));
const iv = new Uint8Array(crypto.randomBytes(16));
const dataToEncrypt = !shouldPad
? attachment.data
: AttachmentUtils.addAttachmentPadding(attachment.data);
const data = await window.textsecure.crypto.encryptAttachment(
attachment.data,
dataToEncrypt,
pointer.key.buffer,
iv.buffer
);
@ -126,6 +139,7 @@ export class AttachmentUtils {
this.upload({
attachment,
openGroup,
shouldPad: true,
})
);
@ -181,4 +195,43 @@ export class AttachmentUtils {
attachments,
};
}
public static isLeftOfBufferPaddingOnly(
data: ArrayBuffer,
unpaddedExpectedSize: number
): boolean {
// to have a padding we must have a strictly longer length expected
if (data.byteLength <= unpaddedExpectedSize) {
return false;
}
const dataUint = new Uint8Array(data);
for (let i = unpaddedExpectedSize; i < data.byteLength; i++) {
if (dataUint[i] !== this.PADDING_BYTE) {
return false;
}
}
return true;
}
private static addAttachmentPadding(data: ArrayBuffer): ArrayBuffer {
const originalUInt = new Uint8Array(data);
const paddedSize = Math.max(
541,
Math.floor(
Math.pow(
1.05,
Math.ceil(Math.log(originalUInt.length) / Math.log(1.05))
)
)
);
const paddedData = new ArrayBuffer(paddedSize);
const paddedUInt = new Uint8Array(paddedData);
paddedUInt.fill(AttachmentUtils.PADDING_BYTE, originalUInt.length);
paddedUInt.set(originalUInt);
return paddedUInt.buffer;
}
}

Loading…
Cancel
Save