mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +00:00
Ensure incrementalMac consistency when exporting
This commit is contained in:
@@ -249,10 +249,7 @@ export class BackupExportStream extends Readable {
|
||||
readonly #serviceIdToRecipientId = new Map<string, number>();
|
||||
readonly #e164ToRecipientId = new Map<string, number>();
|
||||
readonly #roomIdToRecipientId = new Map<string, number>();
|
||||
readonly #mediaNamesToLocatorInfos = new Map<
|
||||
string,
|
||||
Backups.FilePointer.ILocatorInfo
|
||||
>();
|
||||
readonly #mediaNamesToFilePointers = new Map<string, Backups.FilePointer>();
|
||||
readonly #stats: StatsType = {
|
||||
adHocCalls: 0,
|
||||
callLinks: 0,
|
||||
@@ -355,7 +352,7 @@ export class BackupExportStream extends Readable {
|
||||
}
|
||||
|
||||
public getMediaNamesIterator(): MapIterator<string> {
|
||||
return this.#mediaNamesToLocatorInfos.keys();
|
||||
return this.#mediaNamesToFilePointers.keys();
|
||||
}
|
||||
|
||||
public getStats(): Readonly<StatsType> {
|
||||
@@ -2608,16 +2605,17 @@ export class BackupExportStream extends Readable {
|
||||
const mediaName = getMediaNameForAttachment(attachment);
|
||||
|
||||
// Re-use existing locatorInfo and backup job if we've already seen this file
|
||||
const existingLocatorInfo = this.#mediaNamesToLocatorInfos.get(mediaName);
|
||||
const existingFilePointer = this.#mediaNamesToFilePointers.get(mediaName);
|
||||
|
||||
if (existingLocatorInfo) {
|
||||
filePointer.locatorInfo = existingLocatorInfo;
|
||||
if (existingFilePointer?.locatorInfo) {
|
||||
filePointer.locatorInfo = existingFilePointer.locatorInfo;
|
||||
// Also copy over incrementalMac, since that depends on the encryption key
|
||||
filePointer.incrementalMac = existingFilePointer.incrementalMac;
|
||||
filePointer.incrementalMacChunkSize =
|
||||
existingFilePointer.incrementalMacChunkSize;
|
||||
} else {
|
||||
if (filePointer.locatorInfo) {
|
||||
this.#mediaNamesToLocatorInfos.set(
|
||||
mediaName,
|
||||
filePointer.locatorInfo
|
||||
);
|
||||
this.#mediaNamesToFilePointers.set(mediaName, filePointer);
|
||||
}
|
||||
|
||||
if (backupJob) {
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
isValidAttachmentKey,
|
||||
isValidPlaintextHash,
|
||||
} from '../../../types/Crypto';
|
||||
import { isTestOrMockEnvironment } from '../../../environment';
|
||||
|
||||
const log = createLogger('filePointers');
|
||||
|
||||
@@ -227,19 +228,18 @@ export async function getFilePointerForAttachment({
|
||||
height: attachment.height,
|
||||
caption: attachment.caption,
|
||||
blurHash: attachment.blurHash,
|
||||
|
||||
// Resilience to invalid data in the database from internal testing
|
||||
...(typeof attachment.incrementalMac === 'string' && attachment.chunkSize
|
||||
? {
|
||||
incrementalMac: Bytes.fromBase64(attachment.incrementalMac),
|
||||
incrementalMacChunkSize: attachment.chunkSize,
|
||||
}
|
||||
: {
|
||||
incrementalMac: undefined,
|
||||
incrementalMacChunkSize: undefined,
|
||||
}),
|
||||
});
|
||||
|
||||
// TODO: DESKTOP-9112
|
||||
if (isTestOrMockEnvironment()) {
|
||||
// Check for string type for resilience to invalid data in the database from internal
|
||||
// testing
|
||||
if (typeof attachment.incrementalMac === 'string' && attachment.chunkSize) {
|
||||
filePointer.incrementalMac = Bytes.fromBase64(attachment.incrementalMac);
|
||||
filePointer.incrementalMacChunkSize = attachment.chunkSize;
|
||||
}
|
||||
}
|
||||
|
||||
const locatorInfo = getLocatorInfoForAttachment({
|
||||
attachment,
|
||||
isLocalBackup,
|
||||
|
||||
@@ -100,12 +100,14 @@ describe('backup/attachments', () => {
|
||||
plaintextHash: Bytes.toHex(getRandomBytes(32)),
|
||||
key: Bytes.toBase64(generateKeys()),
|
||||
digest: Bytes.toBase64(getRandomBytes(32)),
|
||||
size: 100,
|
||||
size: 100 + index,
|
||||
contentType: IMAGE_JPEG,
|
||||
path: `/path/to/file${index}.png`,
|
||||
caption: `caption${index}`,
|
||||
localKey: Bytes.toBase64(generateAttachmentKeys()),
|
||||
uploadTimestamp: index,
|
||||
incrementalMac: Bytes.toBase64(getRandomBytes(32)),
|
||||
chunkSize: index * 128,
|
||||
thumbnail: {
|
||||
size: 1024,
|
||||
width: 150,
|
||||
@@ -405,11 +407,10 @@ describe('backup/attachments', () => {
|
||||
it('deduplicates attachments on export based on mediaName', async () => {
|
||||
const attachment1 = composeAttachment(1);
|
||||
const attachment2 = {
|
||||
...attachment1,
|
||||
contentType: IMAGE_WEBP,
|
||||
caption: 'attachment2caption',
|
||||
cdnKey: 'attachment2cdnkey',
|
||||
cdnNumber: 25,
|
||||
...composeAttachment(2),
|
||||
plaintextHash: attachment1.plaintextHash,
|
||||
key: attachment1.key,
|
||||
size: attachment1.size,
|
||||
};
|
||||
|
||||
await asymmetricRoundtripHarness(
|
||||
@@ -431,6 +432,9 @@ describe('backup/attachments', () => {
|
||||
...attachment2,
|
||||
cdnKey: attachment1.cdnKey,
|
||||
cdnNumber: attachment1.cdnNumber,
|
||||
uploadTimestamp: attachment1.uploadTimestamp,
|
||||
incrementalMac: attachment1.incrementalMac,
|
||||
chunkSize: attachment1.chunkSize,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user