Decrypt and persist all file metadata layers

Extends RawEnteFile and EnteFile with optional magicMetadata and
pubMagicMetadata fields. Both are secretstream blobs under the file
key, decrypted to arbitrary JSON (Record<string, unknown>).

pubMagicMetadata carries ML-derived data from the Ente clients:
camera make/model, image dimensions, datetime with timezone offset,
and (when present) captions, editedName, face labels, keywords.

magicMetadata carries private mutable fields like visibility.

Backup now writes per-file JSON at originals/<fileID>.json containing
all three metadata layers (basic + magic + pubMagic).

Live-tested: all 11 files in the dev account have pubMagicMetadata
with SONY DSC-RX1RM3 camera info and 3000x2000 dimensions.
This commit is contained in:
2026-05-13 19:07:16 -07:00
parent 7baa9b585a
commit d4098c711a
4 changed files with 49 additions and 0 deletions

View File

@@ -40,6 +40,8 @@ export interface EnteFile {
ownerID: number;
key: Uint8Array;
metadata: FileMetadata;
magicMetadata?: Record<string, unknown>;
pubMagicMetadata?: Record<string, unknown>;
file: FileBlob;
thumbnail: FileBlob;
updationTime: Microseconds;
@@ -59,6 +61,13 @@ export interface RawCollection {
isDeleted?: boolean;
}
export interface RawMagicMetadata {
version: number;
count: number;
data: string;
header: string;
}
export interface RawEnteFile {
id: number;
collectionID: number;
@@ -66,6 +75,8 @@ export interface RawEnteFile {
encryptedKey: string;
keyDecryptionNonce: string;
metadata: { encryptedData: string; decryptionHeader: string };
magicMetadata?: RawMagicMetadata;
pubMagicMetadata?: RawMagicMetadata;
info?: { fileSize?: number; thumbSize?: number };
file: { decryptionHeader: string };
thumbnail: { decryptionHeader: string };