Odborný článok

Šifrovanie XLSX výstupu pomocou AES v Delphi: čo zapisuje HotXLS SaveAsEncrypted

Excel sprístupňuje dve veci, ktoré sa zhodne nazývajú „heslo“, no len jedna z nich predstavuje skutočné šifrovanie. Heslo na otvorenie riadi skutočnú šifru: bez neho nie je možné súbor vôbec prečítať. Heslá na ochranu pracovného hárka a zošita nič také nerobia. Nastavujú iba príznak, ktorý sa spolupracujúci editor zaväzuje rešpektovať, a zošit obsahujúci iba tento príznak je obyčajný čitateľný ZIP súbor, v ktorom sú dáta uložené ako čistý text. Zvoľte si nesprávnu možnosť a odošlete mzdovú evidenciu, ktorá v Exceli vyzerá zamknutá, ale dá sa prečítať v akomkoľvek textovom editore

Dôkaz trvá desať sekúnd. Premenujte chránený súbor .xlsx na .zip, otvorte ho v ľubovoľnom archivačnom nástroji a pozrite sa na xl/worksheets/sheet1.xml. Ak sú dáta buniek uložené v čistom UTF-8, súbor nie je zašifrovaný, bez ohľadu na to, koľko výziev na zadanie hesla Excel zobrazí pri pokuse o úpravu bunky. Táto chyba prežíva roky v tímoch, ktoré predpokladajú, že ochrana hárka znamená dôvernosť dôležitých dát, a zvyčajne vyjde najavo v deň, keď bezpečnostný audit vykoná presne toto premenovanie

HotXLS je natívna knižnica pre tabuľkové procesory v Delphi a C++Builder a drží tieto dve funkcie na opačných stranách spomínanej hranice. Ochrana hárka a zošita sú obmedzenia úprav zálohované zámerne slabým starším hashom. Metóda SaveAsEncrypted vytvára balík zašifrovaný pomocou AES, ktorý neotvorí nič iné než správne heslo. Nasledujúce časti sa venujú tomu, čo toto volanie zapisuje, asymetrii, ktorú musíte zohľadniť pri návrhu (HotXLS zapisuje zašifrované súbory, ale nedokáže ich prečítať späť), a rozdielom v staršej ceste formátu XLS

Prečo ochrana hárka nie je šifrovaním

Metódy Protect na hárkoch a ProtectWorkbook na zošite ukladajú 4-ciferný hexadecimálny hash hesla. Ide o starší algoritmus, ktorý formáty OOXML aj BIFF zdedili z Excelu z 90. rokov, pričom dokumentácia k formátu nikdy netvrdí, že robí viac než len bráni náhodným úpravám. Balík zostáva obyčajným čitateľným ZIP súborom: dáta buniek, vzorce a zdieľané reťazce sú uložené v nešifrovanom XML. Predvolené nastavenie situáciu ešte zhoršuje. Každá bunka začína s hodnotou Locked=True, takže volanie Protect bez predchádzajúceho odomknutia vstupného rozsahu zmrazí celý hárok pred úpravami, no ponechá každú hodnotu na očiach

Nič z toho nerobí ochranu nepoužiteľnou. Navádzanie používateľov do upraviteľných rozsahov a stabilizácia rozloženia pre tlač sú reálne úlohy, o ktorých hovorí náš článok o ochrane pracovného hárka a nastavení stránky. To sú však úlohy týkajúce sa použiteľnosti. Vo chvíli, keď je požiadavkou dôvernosť, jediným API, ktoré na ňu odpovedá, je SaveAsEncrypted

Čo SaveAsEncrypted skutočne zapisuje

Implementácia sleduje štandardné šifrovanie ECMA-376 popísané v [MS-OFFCRYPTO] sekcii 2.3.4. Heslo prechádza cez 50 000 iterácií SHA-1 na odvodenie 128-bitového kľúča AES. Blok verifikátora zašifrovaný pomocou AES-128 v režime ECB umožňuje čítačke potvrdiť heslo predtým, ako čokoľvek dešifruje, a celý balík zošita je potom zašifrovaný pomocou AES-128 v režime CBC. To, čo sa uloží na disk, vôbec nie je ZIP. Ide o zložený súbor OLE (OLE compound file) obsahujúci toky EncryptionInfo, EncryptedPackage a DataSpaces, bez akéhokoľvek adresára xl/, ktorý by archivačný nástroj mohol zobraziť, preto test s premenovaním neodhalí nič čitateľné. Excel 2007 a novšie verzie ho otvoria iba s heslom a aktuálny LibreOffice tiež číta Standard Encryption

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  rc: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Sheet := Book.Sheets.Add('Payroll');
    Sheet.Cells[1, 1].Value := 'Employee';
    Sheet.Cells[1, 2].Value := 'Net pay';
    Sheet.Cells[2, 1].Value := 'A. Garcia';
    Sheet.Cells[2, 2].Value := 4815.16;

    rc := Book.SaveAsEncrypted('payroll-2026-06.xlsx', PasswordFromVault);
    if rc <> 1 then
      raise Exception.CreateFmt('Encrypted save failed (rc=%d)', [rc]);
  finally
    Book.Free;
  end;
end;

S premennou hesla zaobchádzajte rovnako opatrne ako s pripájacím reťazcom databázy. Získajte ho z trezoru alebo služby na generovanie tajných kľúčov v poslednej chvíli, nikdy ho nezaznamenávajte do logov a nezapisujte ho do samotného zošita. Kontrola návratového kódu nie je len nepovinná formalita. Uloženie so šifrovaním, ktoré zlyhá v priebehu procesu, musí prerušiť odosielanie, pretože jediná náhradná možnosť, ktorú volajúci kód môže ponúknuť, je nezašifrovaná kópia, a táto kópia je presne tým incidentom, ktorému má táto funkcia zabrániť

Existuje tiež strojovo overiteľný akceptačný test, ktorý nestojí takmer nič: zavolajte CanReadEncrypted na súbor, ktorý ste práve zapísali. Vracia hodnotu true iba vtedy, keď je výstupom skutočne šifrovaný kontajner, takže jeho testovanie po každom šifrovanom uložení zachytí tú najdôležitejšiu regresiu — cestu kódu, ktorá ticho prešla na obyčajné SaveAs — a to hneď, keď k nej dôjde, a nie až o niekoľko týždňov neskôr v doručenej pošte zákazníka. Konečné slovo má však stále manuálne otvorenie v Exceli s reálnym heslom počas testovania vydania

Navrhnuté len na zápis: spracovanie EXlsxEncryptionNotImplemented

Tu je asymetria, ktorá by mala formovať architektúru vášho spracovania dát: HotXLS šifruje pri uložení, ale nedešifruje pri otvorení. Metóda OpenEncrypted vyvolá výnimku EXlsxEncryptionNotImplemented, ak smeruje na skutočne zašifrovaný balík; pri obyčajnom zošite jednoducho prejde na bežné volanie Open. Sprievodná sonda CanReadEncrypted rýchlo deteguje šifrovaný kontajner OLE, takže vstupný kód môže tieto súbory smerovať bez vyvolania výnimky:

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    if Book.CanReadEncrypted(FileName) then
    begin
      // Encrypted container: HotXLS cannot decrypt it.
      Writeln(FileName + ': needs manual decryption in Excel first');
      Exit;
    end;
    try
      Book.OpenEncrypted(FileName, '');   // plain files fall through to Open
      Writeln(FileName + ': opened, ' + IntToStr(Book.Sheets.Count) + ' sheet(s)');
    except
      on EXlsxEncryptionNotImplemented do
        Writeln(FileName + ': encrypted - routed to manual queue');
    end;
  finally
    Book.Free;
  end;
end;

Táto asymetria má jedno jasné architektonické vysvetlenie: šifrujte na okraji dodávky, ako posledný krok. Uchovávajte predlohu v čistom texte vo vnútri vašej dôveryhodnej zóny — v databáze, úložisku dokumentov alebo na zdieľanom disku s riadeným prístupom — a zašifrovanú kópiu vytvorte ako posledný krok predtým, ako súbor opustí systém. Linka, ktorá archivuje iba zašifrovaný výstup, sa uzamkne pred vlastnými dátami, pretože žiadna neskoršia fáza rovnakého systému tieto súbory nedokáže znova otvoriť. Keď nadväzujúci proces HotXLS potrebuje zošit znova, odovzdajte mu predlohu v čistom texte, nikdy nie dodaný zašifrovaný súbor

Štandardné šifrovanie AES-128 a požiadavka na AES-256

Šifrovanie súborov Office prichádza v dvoch generáciách. Štandardné šifrovanie (Standard Encryption), ktoré HotXLS zapisuje, používa AES-128 s odvodením kľúča pomocou SHA-1. Šifrovanie Agile prišlo neskôr a prechádza na AES-256 so SHA-512 a odlišným, XML-popísaným kontajnerom kľúčov. Obe verzie sa v Exceli otvárajú transparentne a AES-128 je stále výpočtovo dostatočne bezpečný na ochranu súboru pri prenosu k zákazníkovi

Rozdiel prestáva byť akademický v deň, keď bezpečnostný dotazník vyžaduje „šifrovanie AES-256 pre uložené súbory“. Štandardné šifrovanie túto požiadavku nespĺňa, bez ohľadu na to, aké silné je heslo, a žiadny parameter SaveAsEncrypted nemení emitovaný algoritmus. Preto vo svojej bezpečnostnej dokumentácii presne uveďte tento profil: AES-128, Štandardné šifrovanie ECMA-376, odvodenie kľúča SHA-1 pri 50 000 iteráciách. Tvrdenie, ktoré obstojí pri kontrole, má väčšiu hodnotu ako optimistické, ktoré zlyhá pri audite

Staršia cesta XLS: RC4 von, RC4 a XOR späť dnu

Rozhranie BIFF má opačný charakter. Jeho šifrovanie je staršie a slabšie, no prenos je obojsmerný: to, čo zapíše, dokáže prečítať aj späť. Nastavenie EncryptionPassword pred volaním SaveAs vytvorí RC4 zašifrovaný súbor .xls cez mechanizmus BIFF FilePass a metóda Open s parametrom hesla číta všetky tri staršie schémy — RC4, RC4 CryptoAPI aj prastarú obfuskáciu XOR:

var
  Writer, Reader: IXLSWorkbook;   // interface refs: no manual Free
begin
  Writer := TXLSWorkbook.Create;
  Writer.Sheets.Add.Cells.Item[1, 1].Value := 'Confidential';
  Writer.EncryptionPassword := 'S3cret!';
  Writer.SaveAs('confidential.xls');

  Reader := TXLSWorkbook.Create;
  if Reader.Open('confidential.xls', 'S3cret!') > 0 then
    Writeln(Reader.Sheets[1].Cells.Item[1, 1].Value);  // Entries are 1-based
end;

RC4 je zastaraná kryptografia a nikdy by nemala chrániť dáta, na ktorých dnes záleží; jej jedinou zostávajúcou hodnotou je interoperabilita so systémami, ktoré si stále vymieňajú súbory .xls. Strana čítania však nájde svoje uplatnenie pri migračných prácach. Starší súbor chráneným heslom sa otvorí pomocou Open(FileName, Password), prevedie sa do modelu OOXML a znova sa zabezpečí cez cestu AES, čo je jednosmerný upgrade prebiehajúci bez potreby Excelu v systéme. Pri veľkoobjemových šifrovaných dodávkach platia poznámky o priepustnosti zápisu v našom článku o streamovanom zápise pre serverové dávkové úlohy na fázu tvorby obsahu pred šifrovaním

Šifrovanie a ochrana nie sú rivali

Ešte jeden bod, ktorý stojí za to vyjasniť, pretože sa objavuje vo chvíli, keď niekto pochopí varovanie na začiatku tejto stránky tak, že „ochrana je zbytočná“. Nie je to tak. Šifrovanie a ochrana odpovedajú na rôzne otázky a dajú sa kombinovať. Šifrovanie rozhoduje o tom, kto môže súbor otvoriť; ochrana rozhoduje o tom, čo čitateľ, ktorý je už vo vnútri, môže zmeniť. Mzdová zásielka môže rozumne využívať oboje: zašifrovať balík tak, aby ho videl iba majiteľ hesla, a potom uzamknúť bunky so vzorcami, aby príjemca mohol filtrovať a triediť, ale nie potichu prepisovať výpočty. Ochrana sama o sebe nie je chybou. Chybou je nechať ju nahradiť šifrovanie v prípade, že požiadavkou bola dôvernosť dát

Na strane správy hesiel neexistuje žiadna záchranná sieť, a to zámerne. Odvodenie kľúča pomocou 50 000 iterácií existuje preto, aby bolo hádanie náročné, a nič vo vnútri súboru neobsahuje zálohu tajného kľúča. Stratené heslo znamená stratené dáta. Generujte, doručujte a ukladajte tieto heslá s rovnakou disciplínou, akú uplatňujete pri databázových prihlasovacích údajoch, a šifrovanie splní svoju úlohu

Skutočné šifrovanie súborov je v HotXLS otázkou jedného volania. Disciplína však spočíva vo všetkom okolo tohto volania: správa hesiel, limit len na zápis, ktorý bráni HotXLS znova otvoriť svoj vlastný výstup, a deklarácia algoritmu, ktorú dokážete obhájiť pri audite. Metóda SaveAsEncrypted a starší obojsmerný prenos sa dodávajú s komponentom HotXLS, ktorý beží natívne v procesoch Delphi a C++Builder bez akejkoľvek automatizácie Excelu