Attachments: support for incrementalMac and chunkSize
This commit is contained in:
parent
dbf057856f
commit
b51a0e0298
19 changed files with 322 additions and 69 deletions
|
@ -44,10 +44,11 @@ describe('ContactsParser', () => {
|
|||
const keys = generateKeys();
|
||||
|
||||
({ path } = await encryptAttachmentV2ToDisk({
|
||||
plaintext: { data },
|
||||
keys,
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: false,
|
||||
plaintext: { data },
|
||||
}));
|
||||
|
||||
const contacts = await parseContactsV2({
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// Copyright 2015 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { readFileSync, unlinkSync, writeFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import { createCipheriv } from 'crypto';
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { isNumber } from 'lodash';
|
||||
|
||||
import * as log from '../logging/log';
|
||||
import * as Bytes from '../Bytes';
|
||||
import * as Curve from '../Curve';
|
||||
|
@ -584,6 +586,8 @@ describe('Crypto', () => {
|
|||
...splitKeys(keys),
|
||||
size: FILE_CONTENTS.byteLength,
|
||||
theirDigest: encryptedAttachment.digest,
|
||||
theirIncrementalMac: undefined,
|
||||
theirChunkSize: undefined,
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
});
|
||||
|
@ -611,6 +615,7 @@ describe('Crypto', () => {
|
|||
plaintextHash,
|
||||
encryptionKeys,
|
||||
dangerousIv,
|
||||
modifyIncrementalMac,
|
||||
overrideSize,
|
||||
}: {
|
||||
path?: string;
|
||||
|
@ -618,6 +623,7 @@ describe('Crypto', () => {
|
|||
plaintextHash?: Uint8Array;
|
||||
encryptionKeys?: Uint8Array;
|
||||
dangerousIv?: HardcodedIVForEncryptionType;
|
||||
modifyIncrementalMac?: boolean;
|
||||
overrideSize?: number;
|
||||
}): Promise<DecryptedAttachmentV2> {
|
||||
let plaintextPath;
|
||||
|
@ -631,12 +637,22 @@ describe('Crypto', () => {
|
|||
dangerousIv,
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: true,
|
||||
});
|
||||
|
||||
ciphertextPath = window.Signal.Migrations.getAbsoluteAttachmentPath(
|
||||
encryptedAttachment.path
|
||||
);
|
||||
|
||||
const macLength = encryptedAttachment.incrementalMac?.length;
|
||||
if (
|
||||
modifyIncrementalMac &&
|
||||
isNumber(macLength) &&
|
||||
encryptedAttachment.incrementalMac
|
||||
) {
|
||||
encryptedAttachment.incrementalMac[macLength / 2] += 1;
|
||||
}
|
||||
|
||||
const decryptedAttachment = await decryptAttachmentV2({
|
||||
type: 'standard',
|
||||
ciphertextPath,
|
||||
|
@ -644,6 +660,8 @@ describe('Crypto', () => {
|
|||
...splitKeys(keys),
|
||||
size: overrideSize ?? data.byteLength,
|
||||
theirDigest: encryptedAttachment.digest,
|
||||
theirIncrementalMac: encryptedAttachment.incrementalMac,
|
||||
theirChunkSize: encryptedAttachment.chunkSize,
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
});
|
||||
|
@ -736,6 +754,25 @@ describe('Crypto', () => {
|
|||
unlinkSync(sourcePath);
|
||||
}
|
||||
});
|
||||
it('v2 fails decrypt for large disk file if incrementalMac is wrong', async () => {
|
||||
const sourcePath = join(tempDir, 'random');
|
||||
const data = getRandomBytes(5 * 1024 * 1024);
|
||||
const plaintextHash = sha256(data);
|
||||
writeFileSync(sourcePath, data);
|
||||
try {
|
||||
await assert.isRejected(
|
||||
testV2RoundTripData({
|
||||
path: sourcePath,
|
||||
data,
|
||||
plaintextHash,
|
||||
modifyIncrementalMac: true,
|
||||
}),
|
||||
/Corrupted/
|
||||
);
|
||||
} finally {
|
||||
unlinkSync(sourcePath);
|
||||
}
|
||||
});
|
||||
|
||||
it('v2 roundtrips large file from memory', async () => {
|
||||
// Get sufficient large data to have more than 64kb of padding and
|
||||
|
@ -785,6 +822,7 @@ describe('Crypto', () => {
|
|||
plaintext: { data: FILE_CONTENTS },
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: true,
|
||||
});
|
||||
|
||||
await testV2RoundTripData({
|
||||
|
@ -826,6 +864,7 @@ describe('Crypto', () => {
|
|||
plaintext: { absolutePath: FILE_PATH },
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: false,
|
||||
});
|
||||
ciphertextPath = window.Signal.Migrations.getAbsoluteAttachmentPath(
|
||||
encryptedAttachment.path
|
||||
|
@ -882,6 +921,7 @@ describe('Crypto', () => {
|
|||
dangerousIv: { iv: dangerousTestOnlyIv, reason: 'test' },
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: false,
|
||||
});
|
||||
ciphertextPath = window.Signal.Migrations.getAbsoluteAttachmentPath(
|
||||
encryptedAttachmentV2.path
|
||||
|
@ -918,6 +958,7 @@ describe('Crypto', () => {
|
|||
plaintext: { absolutePath: plaintextAbsolutePath },
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: true,
|
||||
});
|
||||
innerCiphertextPath =
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath(
|
||||
|
@ -931,6 +972,7 @@ describe('Crypto', () => {
|
|||
dangerousTestOnlySkipPadding: true,
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: false,
|
||||
});
|
||||
|
||||
outerCiphertextPath =
|
||||
|
@ -969,6 +1011,9 @@ describe('Crypto', () => {
|
|||
...splitKeys(innerKeys),
|
||||
size: FILE_CONTENTS.byteLength,
|
||||
theirDigest: encryptResult.innerEncryptedAttachment.digest,
|
||||
theirIncrementalMac:
|
||||
encryptResult.innerEncryptedAttachment.incrementalMac,
|
||||
theirChunkSize: encryptResult.innerEncryptedAttachment.chunkSize,
|
||||
outerEncryption: splitKeys(outerKeys),
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
|
@ -1025,6 +1070,9 @@ describe('Crypto', () => {
|
|||
...splitKeys(innerKeys),
|
||||
size: data.byteLength,
|
||||
theirDigest: encryptResult.innerEncryptedAttachment.digest,
|
||||
theirIncrementalMac:
|
||||
encryptResult.innerEncryptedAttachment.incrementalMac,
|
||||
theirChunkSize: encryptResult.innerEncryptedAttachment.chunkSize,
|
||||
outerEncryption: splitKeys(outerKeys),
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
|
@ -1075,6 +1123,9 @@ describe('Crypto', () => {
|
|||
...splitKeys(innerKeys),
|
||||
size: data.byteLength,
|
||||
theirDigest: encryptResult.innerEncryptedAttachment.digest,
|
||||
theirIncrementalMac:
|
||||
encryptResult.innerEncryptedAttachment.incrementalMac,
|
||||
theirChunkSize: encryptResult.innerEncryptedAttachment.chunkSize,
|
||||
outerEncryption: {
|
||||
aesKey: splitKeys(outerKeys).aesKey,
|
||||
macKey: splitKeys(innerKeys).macKey, // wrong mac!
|
||||
|
|
|
@ -107,6 +107,7 @@ describe('AttachmentBackupManager/JobManager', function attachmentBackupManager(
|
|||
absolutePath: join(__dirname, '../../../fixtures/cat-gif.mp4'),
|
||||
},
|
||||
keys: Bytes.fromBase64(LOCAL_ENCRYPTION_KEYS),
|
||||
needIncrementalMac: false,
|
||||
sink: createWriteStream(absolutePath),
|
||||
getAbsoluteAttachmentPath,
|
||||
});
|
||||
|
|
|
@ -40,6 +40,7 @@ describe('utils/ensureAttachmentIsReencryptable', async () => {
|
|||
},
|
||||
getAbsoluteAttachmentPath:
|
||||
window.Signal.Migrations.getAbsoluteAttachmentPath,
|
||||
needIncrementalMac: false,
|
||||
});
|
||||
digest = encrypted.digest;
|
||||
iv = encrypted.iv;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue