mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-01 15:57:42 +01:00
Allow incremental playback for attachments with plaintextHash
This commit is contained in:
@@ -25,6 +25,7 @@ import { access } from 'node:fs/promises';
|
||||
import {
|
||||
type DecryptAttachmentToSinkOptionsType,
|
||||
decryptAttachmentV2ToSink,
|
||||
type IntegrityCheckType,
|
||||
} from '../ts/AttachmentCrypto.node.js';
|
||||
import * as Bytes from '../ts/Bytes.std.js';
|
||||
import type { MessageAttachmentsCursorType } from '../ts/sql/Interface.std.js';
|
||||
@@ -68,6 +69,7 @@ import {
|
||||
getStickersPath,
|
||||
getTempPath,
|
||||
} from './attachments.node.js';
|
||||
import { isValidDigest, isValidPlaintextHash } from '../ts/types/Crypto.std.js';
|
||||
|
||||
const { isNumber } = lodash;
|
||||
|
||||
@@ -98,7 +100,7 @@ type RangeFinderContextType = Readonly<
|
||||
}
|
||||
| {
|
||||
type: 'incremental';
|
||||
digest: Uint8Array<ArrayBuffer>;
|
||||
integrityCheck: IntegrityCheckType;
|
||||
incrementalMac: Uint8Array<ArrayBuffer>;
|
||||
chunkSize: number;
|
||||
keysBase64: string;
|
||||
@@ -154,10 +156,7 @@ async function safeDecryptToSink(
|
||||
theirChunkSize: ctx.chunkSize,
|
||||
theirIncrementalMac: ctx.incrementalMac,
|
||||
type: 'standard',
|
||||
integrityCheck: {
|
||||
type: 'encrypted',
|
||||
digest: ctx.digest,
|
||||
},
|
||||
integrityCheck: ctx.integrityCheck,
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
@@ -703,9 +702,26 @@ export async function handleAttachmentRequest(req: Request): Promise<Response> {
|
||||
// When trying to view in-progress downloads, we need more information
|
||||
// to validate the file before returning data.
|
||||
|
||||
const digestBase64 = url.searchParams.get('digest');
|
||||
if (digestBase64 == null) {
|
||||
return new Response('Missing digest', { status: 400 });
|
||||
const digestBase64 = url.searchParams.get('digest') ?? undefined;
|
||||
const plaintextHashHex =
|
||||
url.searchParams.get('plaintextHash') ?? undefined;
|
||||
|
||||
let integrityCheck: IntegrityCheckType;
|
||||
|
||||
if (isValidPlaintextHash(plaintextHashHex)) {
|
||||
integrityCheck = {
|
||||
type: 'plaintext',
|
||||
plaintextHash: Bytes.fromHex(plaintextHashHex),
|
||||
};
|
||||
} else if (isValidDigest(digestBase64)) {
|
||||
integrityCheck = {
|
||||
type: 'encrypted',
|
||||
digest: Bytes.fromBase64(digestBase64),
|
||||
};
|
||||
} else {
|
||||
return new Response('Missing/invalid plaintextHash or digest', {
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
|
||||
const incrementalMacBase64 = url.searchParams.get('incrementalMac');
|
||||
@@ -724,7 +740,7 @@ export async function handleAttachmentRequest(req: Request): Promise<Response> {
|
||||
context = {
|
||||
type: 'incremental',
|
||||
chunkSize,
|
||||
digest: Bytes.fromBase64(digestBase64),
|
||||
integrityCheck,
|
||||
incrementalMac: Bytes.fromBase64(incrementalMacBase64),
|
||||
keysBase64,
|
||||
path,
|
||||
|
||||
@@ -27,6 +27,7 @@ export function getLocalAttachmentUrl(
|
||||
AttachmentType,
|
||||
| 'contentType'
|
||||
| 'digest'
|
||||
| 'plaintextHash'
|
||||
| 'downloadPath'
|
||||
| 'incrementalMac'
|
||||
| 'chunkSize'
|
||||
@@ -87,10 +88,17 @@ export function getLocalAttachmentUrl(
|
||||
}
|
||||
url.searchParams.set('key', attachment.key);
|
||||
|
||||
if (!attachment.digest) {
|
||||
throw new Error('getLocalAttachmentUrl: Missing attachment digest!');
|
||||
// Attachments restored from backup / link & sync may have plaintextHash but not
|
||||
// digest
|
||||
if (attachment.plaintextHash) {
|
||||
url.searchParams.set('plaintextHash', attachment.plaintextHash);
|
||||
} else if (attachment.digest) {
|
||||
url.searchParams.set('digest', attachment.digest);
|
||||
} else {
|
||||
throw new Error(
|
||||
'getLocalAttachmentUrl: Missing attachment plaintextHash and digest!'
|
||||
);
|
||||
}
|
||||
url.searchParams.set('digest', attachment.digest);
|
||||
|
||||
if (!attachment.incrementalMac) {
|
||||
throw new Error(
|
||||
|
||||
Reference in New Issue
Block a user