Tehnični članak

Šifrirajte datoteke XLSX z AES v Delphiju s HotXLS

Excel izpostavlja dve stvari, ki se obe imenujeta »geslo«, in le ena od njiju je šifriranje. Geslo za odpiranje ključa resnično šifro: brez njega datoteke sploh ni mogoče prebrati. Gesli za zaščito delovnega lista in delovnega zvezka ne počneta nič takega. Nastavita zastavico, ki jo sodelujoč urejevalnik privoli spoštovati, delovni zvezek, ki nosi samo to zastavico, pa je navaden berljiv zip s podatki v čistopisu. Izberite napačno in odpremite plačilno listo, ki je v Excelu videti zaklenjena, bere pa se v katerem koli urejevalniku besedila

Dokaz vzame deset sekund. Preimenujte zaščiten .xlsx v .zip, odprite ga v katerem koli arhivskem orodju in poglejte xl/worksheets/sheet1.xml. Če so vrednosti celic tam v navadnem UTF-8, datoteka ni šifrirana, ne glede na to, koliko poziv za geslo Excel sproži, ko kdo skuša urediti celico. Ta vrzel v ekipah, ki domnevajo, da je zaščita lista zaupnost, preživi leta, in običajno pride na dan tistega dne, ko varnostni pregled požene natanko to preimenovanje

HotXLS je izvorna knjižnica za preglednice v Delphiju in C++Builderju, ki obe zmožnosti ohranja na nasprotnih straneh te črte. Zaščita delovnega lista in delovnega zvezka sta omejitvi urejanja, podprti z namerno šibko podedovano zgoščevalno funkcijo. SaveAsEncrypted ustvari paket, šifriran z AES, ki ga ne odpre nič manj kot geslo. Spodnji razdelki pokrivajo, kaj ta klic zapiše, asimetrijo, ki ji morate prilagoditi zasnovo (HotXLS šifrirane datoteke piše, a jih ne zna prebrati nazaj), in kako se starejša pot XLS razlikuje

Diagram, ki primerja zaščito lista XLSX v Delphiju, ki hrani šibko zgoščeno vrednost in pusti podatke celic berljive v navadnem zipu, s HotXLS SaveAsEncrypted, ki izpelje ključ AES-128 in zapiše šifrirni vsebnik OLE
Zaščita lista hrani šibko zgoščeno vrednost in pusti paket kot berljiv zip. SaveAsEncrypted izpelje ključ AES-128 in zapiše vsebnik OLE, ki ga nobeno arhivsko orodje ne zna izpisati

Zakaj zaščita lista ni šifriranje

Metode Protect na listih in ProtectWorkbook na delovnem zvezku shranijo štirimestno šestnajstiško zgoščeno vrednost gesla. To je podedovani algoritem, ki sta ga OOXML in BIFF prevzela iz Excela devetdesetih let, dokumentacija zapisa pa nikoli ne trdi, da počne kaj več kot ustavlja nenamerna urejanja. Paket ostane običajen berljiv zip: podatki celic, formule in deljeni nizi so vsi v čistopisu XML. Privzeta nastavitev stvari poslabša, ne izboljša. Vsaka celica se začne z Locked=True, zato klic metode Protect brez predhodnega odklepanja vnosnega območja zamrzne cel list pred urejanjem, medtem ko vsako vrednost pusti na očeh

Nič od tega zaščite ne naredi neuporabne. Usmerjanje uporabnikov v urejljiva območja in stabiliziranje postavitve za tiskanje sta resnični nalogi, ki ju pokriva naš članek o zaščiti delovnega lista in nastavitvi strani. Vendar sta to nalogi uporabnosti. V trenutku, ko je zahteva zaupnost, je edini vmesnik, ki nanjo odgovori, SaveAsEncrypted

Kaj SaveAsEncrypted dejansko zapiše

Izvedba sledi standardnemu šifriranju ECMA-376, določenemu v [MS-OFFCRYPTO], razdelek 2.3.4. Geslo teče skozi 50.000 ponovitev SHA-1, da se izpelje ključ AES-128. Preverjevalni blok, šifriran z AES-128 v načinu ECB, odjemalcu omogoči potrditev gesla, preden karkoli dešifrira, celoten paket delovnega zvezka pa je nato šifriran z AES-128 v načinu CBC. Kar pristane na disku, sploh ni zip. Je sestavljena datoteka OLE, ki nosi tokove EncryptionInfo, EncryptedPackage in DataSpaces, brez mape xl/, ki bi jo arhivsko orodje lahko izpisalo, zato preizkus s preimenovanjem zdaj ne najde nič berljivega. Excel 2007 in novejši jo odpre že s samim geslom, sodobni LibreOffice pa standardno šifriranje prav tako bere

Diagram cevovoda klica HotXLS SaveAsEncrypted v Delphiju: geslo iz trezorja, pognano skozi 50.000 krogov SHA-1 v ključ AES-128, preverjevalni blok ECB in šifriranje paketa CBC, kar da sestavljeno datoteko OLE, preverjeno s CanReadEncrypted
En sam klic SaveAsEncrypted spremeni geslo iz trezorja v ključ AES-128 in sestavljeno datoteko OLE. CanReadEncrypted shranjevanju da strojno preverljiva prevzemna vrata
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 spremenljivko za geslo ravnajte enako skrbno kot s povezovalnim nizom. Pridobite jo iz trezorja ali storitve za ustvarjanje skrivnosti v zadnjem trenutku, nikoli je ne beležite in nikoli je ne zapišite v delovni zvezek. Preverjanje vrnjene kode ni neobvezna ceremonija. Šifrirano shranjevanje, ki na pol poti odpove, mora dostavo prekiniti, saj je edina rezervna možnost, ki jo klicna koda lahko ponudi, nešifrirana kopija, prav ta kopija pa je natanko tisti incident, ki naj bi ga ta zmožnost preprečila

Obstaja tudi strojno preverljiv prevzemni preizkus, ki stane skoraj nič: na datoteki, ki ste jo pravkar zapisali, pokličite CanReadEncrypted. Vrne true le tedaj, ko je izhod resnično šifrirni vsebnik, zato trditev za vsakim šifriranim shranjevanjem ujame nazadovanje, ki šteje največ, torej kodno pot, ki je tiho padla nazaj na navadni SaveAs, in to v trenutku, ko se to zgodi, ne pa tedne pozneje v strankinem nabiralniku. Zadnja beseda še vedno pripada ročnemu odpiranju v Excelu z resničnim geslom med preizkušanjem izdaje

Samo za pisanje po zasnovi: ravnanje z EXlsxEncryptionNotImplemented

Tu je asimetrija, ki naj oblikuje arhitekturo vašega cevovoda: HotXLS ob shranjevanju šifrira, ob odpiranju pa ne dešifrira. OpenEncrypted sproži EXlsxEncryptionNotImplemented, kadar je usmerjen na resnično šifriran paket; pri navadnem delovnem zvezku preprosto pade skozi v običajni Open. Spremljevalna sonda CanReadEncrypted šifrirni vsebnik OLE zazna poceni, tako da lahko sprejemna koda take datoteke preusmeri, ne da bi sprožila izjemo:

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    if Book.CanReadEncrypted(FileName) then
    begin
      // Šifriran vsebnik: HotXLS ga ne zna dešifrirati.
      Writeln(FileName + ': needs manual decryption in Excel first');
      Exit;
    end;
    try
      Book.OpenEncrypted(FileName, '');   // navadne datoteke padejo skozi v 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;

Ta asimetrija ima eno jasno arhitekturno branje: šifrirajte na robu dostave, čisto nazadnje. Izvirnik v čistopisu ohranite znotraj svoje meje zaupanja, v podatkovni zbirki, shrambi dokumentov ali deljeni mapi z nadzorovanim dostopom, šifrirano kopijo pa ustvarite kot zadnji korak, preden datoteka zapusti sistem. Cevovod, ki arhivira le šifriran izhod, se je zaklenil stran od lastnih podatkov, saj nobena poznejša stopnja istega sistema teh datotek ne more znova odpreti. Ko poznejši proces HotXLS delovni zvezek spet potrebuje, mu izročite izvirnik v čistopisu, nikoli dostavnega izdelka

Arhitekturni diagram za storitve v Delphiju: izvirnik delovnega zvezka v čistopisu ostane znotraj meje zaupanja, HotXLS SaveAsEncrypted teče kot zadnji korak na robu dostave, opozorilo pa svari pred arhiviranjem zgolj šifrirane kopije
Šifrirajte na robu dostave, čisto nazadnje, iz izvirnika v čistopisu, ki ostane znotraj meje zaupanja. Arhiviranje zgolj šifrirane kopije vsako poznejšo stopnjo zaklene stran od lastnih podatkov

Standardno šifriranje AES-128 in skladnostna črta AES-256

Šifriranje datotek v Officeu prihaja v dveh rodovih. Standardno šifriranje, tisto, ki ga zapisuje HotXLS, uporablja AES-128 z izpeljavo ključa SHA-1. Agilno šifriranje je prišlo pozneje in prehaja na AES-256 s SHA-512 ter na drugačen vsebnik ključa, opisan v XML. Oba se v Excelu odpreta pregledno, AES-128 pa je za zaščito datoteke na poti do stranke še vedno računsko trden

Razlika neha biti akademska tistega dne, ko varnostni vprašalnik zahteva »šifriranje datotek v mirovanju z AES-256«. Standardno šifriranje te črte ne doseže, ne glede na to, kako močno je geslo, in noben parameter metode SaveAsEncrypted algoritma, ki ga oddaja, ne spremeni. Zato v svoji varnostni dokumentaciji profil navedite natančno: AES-128, standardno šifriranje ECMA-376, izpeljava ključa SHA-1 pri 50.000 ponovitvah. Trditev, ki preživi pregled, je vredna več kot optimistična, ki se sesuje pod revizijo

Podedovana pot XLS: RC4 ven, RC4 in XOR nazaj noter

Fasada BIFF ima nasprotno obliko. Njeno šifriranje je starejše in šibkejše, a krog je sklenjen: kar zapiše, zna tudi prebrati nazaj. Nastavitev lastnosti EncryptionPassword pred klicem SaveAs ustvari .xls, šifriran z RC4, prek mehanizma BIFF FilePass, klic Open s parametrom gesla pa bere vse tri podedovane sheme, RC4, RC4 CryptoAPI in starodavno zakrivanje XOR:

var
  Writer, Reader: IXLSWorkbook;   // reference vmesnikov: brez ročnega 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);  // vnosi se štejejo od 1
end;

RC4 je zastarela kriptografija in danes nikoli ne bi smel ščititi podatkov, ki kaj pomenijo; njegova edina preostala vrednost je združljivost s sistemi, ki še vedno izmenjujejo .xls. Bralna stran pa se izplača pri delu s selitvami. Z geslom zaščitena podedovana datoteka se odpre s klicem Open(FileName, Password), se premosti v model OOXML in se znova zavaruje po poti AES; gre za enosmerno nadgradnjo, ki teče brez Excela kjer koli v zanki. Za šifrirane dostave v velikih količinah veljajo opombe o prepustnosti na strani shranjevanja iz našega članka o pretočnem pisanju za paketna strežniška opravila, ki se nanašajo na fazo gradnje vsebine pred šifriranjem

Šifriranje in zaščita nista tekmeca

Še ena točka, ki jo je vredno razrešiti, saj se pojavi v trenutku, ko kdo opozorilo na vrhu te strani prebere kot »zaščita je brez vrednosti«. Ni. Šifriranje in zaščita odgovarjata na različni vprašanji in se čisto zlagata drug na drugega. Šifriranje odloči, kdo lahko datoteko odpre; zaščita odloči, kaj sme spremeniti bralec, ki je že notri. Dostava plačilne liste lahko razumno počne oboje: paket šifrirajte, tako da ga vidi le imetnik gesla, nato pa zaklenite celice s formulami, da lahko prejemnik filtrira in razvršča, ne more pa tiho prepisati izračunov. Napaka ni v tem, da se zaščita doda. Napaka je, da njena prisotnost nadomesti šifriranje, kadar je bila zahteva zaupnost

Stran hrambe nima varnostne mreže, in to je namerno. Izpeljava ključa s 50.000 ponovitvami obstaja zato, da je ugibanje drago, nič znotraj datoteke pa skrivnosti ne shranjuje pri tretji osebi. Izgubljeno geslo pomeni izgubljene podatke. Ta gesla ustvarjajte, dostavljajte in hranite z enako disciplino, kot jo namenjate poverilnicam podatkovne zbirke, in šifriranje bo svoj del opravilo

Resnično šifriranje datotek je v HotXLS en sam klic. Disciplina živi v vsem okoli tega klica: v hrambi gesel, v meji samo za pisanje, ki HotXLS preprečuje ponovno odpiranje lastnega izhoda, in v trditvi o algoritmu, ki jo lahko zagovarjate v reviziji. SaveAsEncrypted in podedovani sklenjeni krog sta priložena paketu HotXLS Delphi Component, ki teče izvorno v procesih Delphi in C++Builder brez avtomatizacije Excela kjer koli na poti