Fix file metadata decryption: use secretstream blob, not secretbox

File metadata is encrypted as a single-chunk secretstream blob (the
'decryptionHeader' is the secretstream init header, not a secretbox
nonce). Collection keys and names correctly use secretbox.

Adds decryptBlob(ciphertext, header, key) to the crypto module as a
convenience wrapper for single-chunk secretstream decryption (init +
pull + verify TAG_FINAL).

Live-tested: collection names and file metadata (titles, types, dates)
decrypt correctly from the real Ente API.
This commit is contained in:
2026-05-13 17:38:18 -07:00
parent f81216333e
commit 44718a92a9
5 changed files with 170 additions and 41 deletions

View File

@@ -99,10 +99,16 @@ const buildRawFile = (
longitude: 2.3522,
hash: "abcdef1234567890",
};
// File metadata is encrypted as a single-chunk secretstream blob
// (not secretbox). The decryptionHeader is the secretstream init header.
const metadataBytes = new TextEncoder().encode(JSON.stringify(metadata));
const { ciphertext: encMeta, nonce: metaNonce } = secretboxEncrypt(
const push =
sodium.crypto_secretstream_xchacha20poly1305_init_push(fileKey);
const encMeta = sodium.crypto_secretstream_xchacha20poly1305_push(
push.state,
metadataBytes,
fileKey,
null,
sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL,
);
return {
@@ -113,7 +119,7 @@ const buildRawFile = (
keyDecryptionNonce: toBase64(fileKeyNonce),
metadata: {
encryptedData: toBase64(encMeta),
decryptionHeader: toBase64(metaNonce),
decryptionHeader: toBase64(push.header),
},
file: { decryptionHeader: toBase64(sodium.randombytes_buf(24)) },
thumbnail: { decryptionHeader: toBase64(sodium.randombytes_buf(24)) },