mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-05-08 08:58:38 +01:00
Store IV when encrypting or decrypting attachments
This commit is contained in:
@@ -37,6 +37,7 @@ import {
|
||||
CipherType,
|
||||
} from '../Crypto';
|
||||
import {
|
||||
type HardcodedIVForEncryptionType,
|
||||
KEY_SET_LENGTH,
|
||||
_generateAttachmentIv,
|
||||
decryptAttachmentV2,
|
||||
@@ -608,19 +609,24 @@ describe('Crypto', () => {
|
||||
path,
|
||||
data,
|
||||
plaintextHash,
|
||||
encryptionKeys,
|
||||
dangerousIv,
|
||||
}: {
|
||||
path?: string;
|
||||
data: Uint8Array;
|
||||
plaintextHash: Uint8Array;
|
||||
encryptionKeys?: Uint8Array;
|
||||
dangerousIv?: HardcodedIVForEncryptionType;
|
||||
}): Promise<void> {
|
||||
let plaintextPath;
|
||||
let ciphertextPath;
|
||||
const keys = generateAttachmentKeys();
|
||||
const keys = encryptionKeys ?? generateAttachmentKeys();
|
||||
|
||||
try {
|
||||
const encryptedAttachment = await encryptAttachmentV2ToDisk({
|
||||
keys,
|
||||
plaintext: path ? { absolutePath: path } : { data },
|
||||
dangerousIv,
|
||||
});
|
||||
|
||||
ciphertextPath = window.Signal.Migrations.getAbsoluteAttachmentPath(
|
||||
@@ -639,6 +645,21 @@ describe('Crypto', () => {
|
||||
);
|
||||
|
||||
const plaintext = readFileSync(plaintextPath);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
encryptedAttachment.iv,
|
||||
decryptedAttachment.iv
|
||||
);
|
||||
if (dangerousIv) {
|
||||
assert.deepStrictEqual(encryptedAttachment.iv, dangerousIv.iv);
|
||||
if (dangerousIv.reason === 'reencrypting-for-backup') {
|
||||
assert.deepStrictEqual(
|
||||
encryptedAttachment.digest,
|
||||
dangerousIv.digestToMatch
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert.isTrue(constantTimeEqual(data, plaintext));
|
||||
assert.strictEqual(
|
||||
encryptedAttachment.ciphertextSize,
|
||||
@@ -711,6 +732,52 @@ describe('Crypto', () => {
|
||||
plaintextHash,
|
||||
});
|
||||
});
|
||||
describe('dangerousIv', () => {
|
||||
it('uses hardcodedIv in tests', async () => {
|
||||
await testV2RoundTripData({
|
||||
data: FILE_CONTENTS,
|
||||
plaintextHash: FILE_HASH,
|
||||
dangerousIv: {
|
||||
reason: 'test',
|
||||
iv: _generateAttachmentIv(),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('uses hardcodedIv when re-encrypting for backup', async () => {
|
||||
const keys = generateAttachmentKeys();
|
||||
const previouslyEncrypted = await encryptAttachmentV2ToDisk({
|
||||
keys,
|
||||
plaintext: { data: FILE_CONTENTS },
|
||||
});
|
||||
|
||||
await testV2RoundTripData({
|
||||
data: FILE_CONTENTS,
|
||||
plaintextHash: FILE_HASH,
|
||||
encryptionKeys: keys,
|
||||
dangerousIv: {
|
||||
reason: 'reencrypting-for-backup',
|
||||
iv: previouslyEncrypted.iv,
|
||||
digestToMatch: previouslyEncrypted.digest,
|
||||
},
|
||||
});
|
||||
|
||||
// If the digest is wrong, it should throw
|
||||
await assert.isRejected(
|
||||
testV2RoundTripData({
|
||||
data: FILE_CONTENTS,
|
||||
plaintextHash: FILE_HASH,
|
||||
encryptionKeys: keys,
|
||||
dangerousIv: {
|
||||
reason: 'reencrypting-for-backup',
|
||||
iv: previouslyEncrypted.iv,
|
||||
digestToMatch: getRandomBytes(32),
|
||||
},
|
||||
}),
|
||||
'iv was hardcoded for backup re-encryption, but digest does not match'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('v2 -> v1 (disk -> memory)', async () => {
|
||||
@@ -774,7 +841,7 @@ describe('Crypto', () => {
|
||||
const encryptedAttachmentV2 = await encryptAttachmentV2ToDisk({
|
||||
keys,
|
||||
plaintext: { absolutePath: FILE_PATH },
|
||||
dangerousTestOnlyIv,
|
||||
dangerousIv: { iv: dangerousTestOnlyIv, reason: 'test' },
|
||||
});
|
||||
ciphertextPath = window.Signal.Migrations.getAbsoluteAttachmentPath(
|
||||
encryptedAttachmentV2.path
|
||||
|
||||
Reference in New Issue
Block a user