HotXLS scrive un blocco dataIntegrity conforme nei pacchetti XLSX cifrati con Agile e lo verifica all'apertura. L'HMAC-SHA-512 copre l'intero stream EncryptedPackage, incluso il suo prefisso StreamSize di otto byte, ed è controllato sul ciphertext prima che qualunque segmento venga decifrato, così una password sbagliata o un pacchetto modificato viene rilevato invece di essere decifrato in dati spazzatura
La cifratura senza integrità è una risposta a metà, e i formati di file Office rendono facile trascurare quel divario perché la cifratura sembra così accurata dall'esterno. Capire cosa promette ogni livello è ciò che mantiene breve una security review
Cosa promette davvero una cartella di lavoro cifrata?
La cifratura Agile, definita in [MS-OFFCRYPTO], ti dà riservatezza tramite AES in modalità CBC con una chiave derivata da un hash della password SHA-512 iterato. La riservatezza è l'intera promessa di quella costruzione. CBC non è una modalità autenticata: non dice nulla su se il ciphertext che stai decifrando sia il ciphertext che è stato scritto
La conseguenza pratica è specifica. Inverti dei bit in un pacchetto cifrato e CBC li decifrerà volentieri in un plaintext diverso. Di solito otterrai un errore di parsing ZIP da qualche parte a valle, perché uno stream deflate corrotto raramente sopravvive, ma «di solito» fa un gran lavoro in quella frase, e un errore del parser a valle è un pessimo posto per scoprire che un file è stato modificato. L'elemento dataIntegrity esiste per rispondere direttamente alla domanda, prima della decifratura, con un MAC calcolato sui byte esatti
Come viene eseguito il controllo, e in che ordine
L'ordine è la parte interessante. HotXLS deriva la chiave intermedia dalla password, decifra la chiave HMAC e il valore HMAC cifrati dagli attributi dataIntegrity usando IV derivati dalla block key, calcola l'HMAC-SHA-512 sul pacchetto cifrato così come è memorizzato, e confronta. Solo a quel punto inizia la decifratura dei segmenti
Controllare il MAC sul ciphertext anziché sul plaintext è la disciplina standard encrypt-then-MAC, ed è ciò che rende il controllo significativo: un pacchetto manomesso viene rifiutato senza che alcun byte controllato dall'attaccante sia mai passato attraverso il percorso di decifratura e inflate. Entrambi i confronti nel percorso di apertura, l'hash del verifier della password e il valore HMAC, accumulano le differenze con XOR e OR sull'intero digest invece di uscire subito al primo byte non corrispondente, così nessuno dei due rivela una posizione di byte tramite il tempo di esecuzione
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
// Funziona per file semplici, cifrati Standard e cifrati Agile
if Book.OpenEncrypted('incoming.xlsx', PasswordFromVault) = 1 then
ProcessWorkbook(Book)
else
// Password sbagliata, oppure un pacchetto il cui HMAC dataIntegrity non corrisponde
Quarantine('incoming.xlsx');
except
on E: Exception do
Quarantine('incoming.xlsx: ' + E.Message);
end;
Book.Free;
end;
Sul lato scrittura non cambia nulla nel tuo codice. SaveAsEncrypted emette il blocco automaticamente, e i salt, l'input del verifier e la chiave HMAC provengono da CryptGenRandom. Se quella chiamata fallisce, HotXLS solleva un'eccezione invece di ripiegare su una sorgente più debole. Un CSPRNG fail-closed non è paranoia; un declassamento silenzioso a una sorgente casuale prevedibile produce file che sembrano cifrati, superano ogni test funzionale, e sono inutili
Perché i file privi del blocco si aprono comunque?
Perché moltissime cartelle di lavoro cifrate Agile in circolazione sono state scritte da producer che omettono del tutto dataIntegrity, e rifiutarle romperebbe molto più lavoro legittimo di quanto ne proteggerebbe. HotXLS considera l'integrità presente solo quando entrambi gli attributi, la chiave HMAC cifrata e il valore HMAC cifrato, sono presenti e ben formati. Altrimenti la verifica viene saltata e il file si apre come prima
Questa è una decisione di compatibilità con una conseguenza di sicurezza che dovresti nominare esplicitamente nel tuo threat model: l'assenza del blocco non può essere distinta da un attaccante che lo rimuove, perché gli attributi sono fuori dal MAC che dovrebbero portare. Se controlli entrambe le estremità di una pipeline, tratta un blocco mancante come un fallimento di policy a livello applicativo. Se accetti file dal mondo esterno, tratta il controllo per quello che è, un segnale prezioso quando presente e nessun segnale quando assente
Password to modify è una convenzione, non un confine
Le cartelle di lavoro XLS classiche supportano un meccanismo separato che viene regolarmente confuso con la cifratura: la write reservation, il prompt «password to modify» di Excel. HotXLS la espone tramite SetModifyPassword, che accetta la password, un flag recommend-read-only e il nome dell'utente che riserva, e riporta lo stato tramite IsWriteReserved. Passare una password vuota cancella la riserva
Ciò che viene scritto è una coppia di record WRITEPROT e FILESHARING che porta il flag recommend-read-only, un hash della password legacy a 16 bit e il nome utente come stringa Unicode BIFF8. Quell'hash a 16 bit è un checksum, non un digest crittografico, e il contenuto del documento non è affatto cifrato. Chiunque apra il file con un altro strumento qualsiasi legge tutto. Il compito reale della funzionalità è la coordinazione: dice alla persona successiva che qualcuno considera questo file suo da modificare, nella stessa categoria dei controlli a livello di foglio trattati in protezione del foglio XLSX e opzioni allow
var
Book: IXLSWorkbook; // interface-counted: do not Free
begin
Book := TXLSWorkbook.Create;
if Book.Open('shared-model.xls') = 1 then
begin
// Consiglia sola lettura, riservato dal servizio di reporting
Book.SetModifyPassword('edit-me', True, 'Reporting Service');
if Book.IsWriteReserved then
Book.SaveAs('shared-model.xls', xlExcel97);
end;
end;
Usa entrambi i livelli per ciò in cui ciascuno eccelle. La riservatezza reale viene da SaveAsEncrypted con una password che nessuno al di fuori del pubblico previsto possiede, che produce l'output AES-256 descritto in output XLSX protetto AES. La write reservation si aggiunge sopra quando la cartella di lavoro è un artefatto di editing condiviso e vuoi che Excel chieda conferma prima che qualcuno salvi sopra
Cosa controllare in un percorso di ingestion non attendibile
La verifica dell'integrità protegge il payload cifrato, non il contenitore che lo circonda. Un file XLSX è un archivio ZIP, e la struttura dell'archivio viene analizzata prima che qualunque logica di cifratura entri in funzione, quindi la validazione a livello di contenitore va posta per prima nella catena; le modalità di fallimento specifiche sono trattate in validazione ZIP end-of-central-directory per XLSX non attendibili. Dopodiché, tratta un fallimento di integrità e una password sbagliata come lo stesso evento operativo, perché dal tuo punto di vista sono indistinguibili per progettazione, ed entrambi significano che non ci si può fidare che il file sia quello che il mittente pensa che sia
Registra quali file portavano un blocco dataIntegrity e quali no. Su qualche migliaio di documenti quella statistica ti dice qualcosa di utile sugli strumenti dei tuoi mittenti, e trasforma un controllo per singolo file in un'osservazione a livello di flotta su cui puoi agire
HotXLS legge e scrive XLS, XLSX e ODS da Delphi e C++Builder senza installazione di Excel, implementando in Pascal i percorsi di cifratura Standard e Agile di [MS-OFFCRYPTO]. Le API di cifratura, protezione e cartella di lavoro sono documentate sulla pagina del componente foglio di calcolo Delphi HotXLS