Excel tarjoaa kaksi asiaa, joita molempia kutsutaan nimellä "salasana", ja vain toinen niistä on salaus. Avaussalasana avaa todellisen salauksen: ilman sitä tiedostoa ei voida lukea lainkaan. Laskentataulukon ja työkirjan suojauksen salasanat eivät tee mitään sellaista. Ne asettavat lipun (flag), jota yhteensopiva editori suostuu kunnioittamaan. Työkirja, joka sisältää vain tuon lipun, on tavallinen luettava zip-tiedosto, jonka tiedot ovat selväkielisenä XML-muodossa. Valitse väärä salasana, ja toimitat palkkatiedot, jotka näyttävät lukituilta Excelissä mutta ovat luettavissa millä tahansa tekstieditorilla
Tämän todistaminen vie kymmenen sekuntia. Nimeä suojattu .xlsx-tiedosto muotoon .zip, avaa se millä tahansa arkistotyökalulla ja katso tiedostoa xl/worksheets/sheet1.xml. Jos solujen arvot ovat siellä selväkielisessä UTF-8-muodossa, tiedostoa ei ole salattu — riippumatta siitä, kuinka monta salasanakehotetta Excel näyttää, kun joku yrittää muokata solua. Tämä aukko säilyy vuosia tiimeissä, jotka olettavat sivujen suojauksen tarkoittavan luottamuksellisuutta, ja se tulee yleensä ilmi sinä päivänä, kun tietoturvatarkastus tekee juuri tämän uudelleennimeämisen
HotXLS is a native Delphi and C++Builder spreadsheet library, and it keeps the two features on opposite sides of that line. Worksheet and workbook protection are editing restrictions backed by a deliberately weak legacy hash. SaveAsEncrypted produces an AES-encrypted package that nothing short of the password will open. The sections below cover what that call writes, the asymmetry you have to design around (HotXLS writes encrypted files but cannot read them back), and how the older XLS path differs
Miksi sivun suojaus ei ole salaus
Taulukoiden Protect-metodit ja työkirjan ProtectWorkbook tallentavat salasanan 4-heksadesimaalisen tiivisteen. Tämä on perinteinen algoritmi, jonka sekä OOXML että BIFF perivät 1990-luvun Excelistä, eikä formaatin dokumentaatio koskaan väitä sen tekevän muuta kuin estävän vahingossa tapahtuvat muokkaukset. Paketti pysyy tavallisena luettavana zip-tiedostona: solutiedot, kaavat ja jaetut merkkijonot ovat selväkielisessä XML:ssä. Oletusasetus tekee siitä huonomman, ei parempaa. Jokainen solu alkaa arvolla Locked=True, joten Protect-kutsun tekeminen avaamatta ensin syötealueen lukitusta jäädyttää koko taulukon muokkauksilta jättäen jokaisen arvon täysin näkyville
Tämä ei kuitenkaan tee suojauksesta hyödytöntä. Käyttäjien ohjaaminen muokattaville alueille ja asettelun vakauttaminen tulostusta varten ovat todellisia tehtäviä, joita käsitellään artikkelissamme laskentataulukon suojauksesta ja sivunasetuksista. Nämä ovat kuitenkin käytettävyyteen liittyviä tehtäviä. Sillä hetkellä, kun vaatimuksena on tietojen luottamuksellisuus, ainoa tähän vastaava API on SaveAsEncrypted
Mitä SaveAsEncrypted todellisuudessa kirjoittaa
Toteutus noudattaa standardin ECMA-376 Standard Encryption -määrittelyä, joka on kuvattu [MS-OFFCRYPTO]-dokumentin osiossa 2.3.4. Salasana kulkee 50 000 SHA-1-iteraation läpi AES-128-avaimen johtamiseksi. Varmistelohko (verifier block), joka on salattu AES-128-algoritmilla ECB-tilassa, antaa kuluttajan vahvistaa salasanan ennen kuin se purkaa mitään. Tämän jälkeen koko työkirjapaketti salataan AES-128-algoritmilla CBC-tilassa. Levylle päätyvä tiedosto ei ole lainkaan zip-tiedosto. Se on OLE-yhdistetiedosto (OLE compound file), joka sisältää virrat EncryptionInfo, EncryptedPackage ja DataSpaces. Siinä ei ole xl/-hakemistoa, jota arkistotyökalu voisi listata, minkä vuoksi uudelleennimeämistesti ei enää paljasta mitään luettavaa. Excel 2007 ja uudemmat avaavat sen pelkällä salasanalla, ja myös nykyinen LibreOffice lukee Standard-salausta
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;
Käsittele salasanamuuttujaa yhtä varovasti kuin yhteysmerkkijonoa. Hae se holvista tai luodusta salaisuuspalvelusta viime hetkellä, älä koskaan kirjaa sitä lokiin äläkä koskaan kirjoita sitä itse työkirjaan. Paluukoodin tarkistus ei ole vapaaehtoista seremoniaa. Osittain epäonnistunut salattu tallennus on keskeytettävä, koska ainoa vararatkaisu, jonka kutsuva koodi voi tarjota, on salaamaton kopio — ja tämä kopio on juuri se tapaus, jonka estämiseksi tämä ominaisuus on olemassa
On myös olemassa koneellisesti tarkistettava hyväksyntätesti, joka ei maksa lähes mitään: kutsu CanReadEncrypted-metodia juuri kirjoittamallesi tiedostolle. Se palauttaa arvon tosi vain silloin, kun tuloste todella on salaus-säiliö. Tämän varmistaminen jokaisen salatun tallennuksen jälkeen paljastaa kriittisimmän regression — eli koodipolun, joka hiljaa palasi tavalliseen SaveAs-tallennukseen — heti kun se tapahtuu, eikä viikkoja myöhemmin asiakkaan saapuneissa viesteissä. Lopullinen sana on kuitenkin edelleen manuaalisella avaamisella Excelissä oikealla salasanalla julkaisutestauksen aikana
Suunnittelultaan vain kirjoitettava: EXlsxEncryptionNotImplemented-poikkeuksen käsittely
Tässä on epäsymmetria, jonka tulisi muovata putkiarkkitehtuuriasi: HotXLS salaa tallennettaessa, mutta ei pura salausta avattaessa. OpenEncrypted nostaa poikkeuksen EXlsxEncryptionNotImplemented, kun se kohdistetaan todelliseen salattuun pakettiin; tavallisessa työkirjassa se siirtyy suoraan normaaliin Open-metodiin. Kumppanitesti CanReadEncrypted havaitsee OLE-salaussäiliön helposti, joten vastaanottokoodi voi reitittää tällaiset tiedostot ilman poikkeuksen laukeamista:
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ällä epäsymmetrialla on yksi selkeä arkkitehtuurinen merkitys: salaa vasta toimitusvaiheen lopussa, viimeisenä. Pidä selväkielinen pääversio luottamusrajasi sisäpuolella, tietokannassa, asiakirjavarastossa tai pääsyvalvotussa jaossa, ja tuota salattu kopio vasta viimeisenä vaiheena ennen kuin tiedosto lähtee järjestelmästä. Putki, joka arkistoi vain salatun tulosteen, on lukinnut itsensä ulos omasta datastaan, koska mikään saman järjestelmän myöhempi vaihe ei voi avata näitä tiedostoja uudelleen. Kun myöhempi HotXLS-prosessi tarvitsee työkirjaa uudelleen, anna sille selväkielinen pääversio, älä koskaan toimitustuotetta
AES-128 Standard -salaus ja AES-256-yhteensopivuusraja
Officen tiedostojen salaus jakautuu kahteen sukupolveen. Standard Encryption, jota HotXLS kirjoittaa, käyttää AES-128-salausta SHA-1-avaimenjohtamisella. Agile Encryption saapui myöhemmin ja siirtyy AES-256-salausmenetelmään SHA-512-hajautuksella ja erilaiseen, XML-muotoiseen avainsäiliöön. Molemmat avautuvat saumattomasti Excelissä, ja AES-128 on edelleen laskennallisesti vahva suojamaan siirrettävää tiedostoa asiakkaalle
Ero lakkaa olemasta akateeminen sinä päivänä, kun tietoturvakyselyssä vaaditaan "tallennustilassa olevien tiedostojen AES-256-salausta". Standard-salaus ei täytä tätä vaatimusta, oli salasana kuinka vahva tahansa, eikä mikään SaveAsEncrypted-metodin parametri muuta sen käyttämää algoritmia. Ilmoitettiimpa profiili tarkasti tietoturvadokumentaatiossasi: AES-128, ECMA-376 Standard Encryption, SHA-1-avaimenjohtaminen 50 000 iteraatiolla. Tarkka väite, joka selviää arvioinnista, on arvokkaampi kuin optimistinen oletus, joka kaatuu tarkastuksessa
Perinteinen XLS-polku: RC4 ulos, RC4 ja XOR takaisin sisään
BIFF-rajapinnalla on vastakkainen muoto. Sen salaus on vanhempaa ja heikompaa, mutta round-trip on täydellinen: mitä se kirjoittaa, sen se voi myös lukea takaisin. Ominaisuuden EncryptionPassword asettaminen ennen SaveAs-tallennusta tuottaa RC4-salatun .xls-tiedoston BIFF FilePass -mekanismin kautta, ja Open salasanaparametrilla lukee kaikki kolme perinteistä mallia: RC4, RC4 CryptoAPI ja ikivanha XOR-sotkeminen
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 on vanhentunutta kryptografiaa eikä sen pitäisi koskaan suojata tietoja, joilla on merkitystä nykyään. Sen ainoa jäljellä oleva arvo on yhteensopivuus järjestelmien kanssa, jotka edelleen vaihtavat .xls-tiedostoja. Lukupuoli kuitenkin puolustaa paikkaansa migraatiotyössä. Salasanasuojattu vanha tiedosto avautuu kutsulla Open(FileName, Password), siirtyy OOXML-malliin ja suojataan uudelleen AES-polun kautta — tämä on yksisuuntainen päivitys, joka toimii ilman Exceliä. Suuria määriä salattuja toimituksia varten tallennuspuolen suorituskykyohjeet, joita käsitellään artikkelissamme suoratoistokirjoituksesta palvelimen eräajoissa, koskevat sisällönrakennusvaihetta, joka tapahtuu ennen salausta
Salaukset ja suojaukset eivät ole kilpailijoita
Vielä yksi asia on syytä selvittää, koska se nousee esiin heti, kun joku lukee tämän sivun yläosassa olevan varoituksen muodossa "suojaus on hyödytöntä". Se ei ole. Salaus ja suojaus vastaavat eri kysymyksiin, ja ne täydentävät toisiaan saumattomasti. Salaus päättää, kuka voi avata tiedoston; suojaus päättää, mitä jo sisällä oleva lukija saa muuttaa. Palkka-aineiston toimituksessa on järkevää tehdä molemmat: salata paketti niin, että vain salasanan haltija näkee sen, ja sitten lukita kaavasolut niin, että vastaanottaja voi suodattaa ja lajitella, mutta ei hiljaa kirjoittaa laskelmia uudelleen. Virhe ei ole koskaan suojauksen lisääminen. Virhe on antaa suojauksen korvata salaus silloin, kun vaatimuksena on tietojen luottamuksellisuus
Salauksen hallinnassa ei ole turvaverkkoa, ja tämä on suunniteltu ominaisuus. 50 000 iteraation avaimenjohtaminen on olemassa tekemään arvaamisesta kallista, eikä mikään tiedoston sisällä talleta salaisuutta. Kadotettu salasana tarkoittaa kadotettua dataa. Luo, toimita ja säilytä nämä salasanat samalla kurinalaisuudella, jota sovelletat tietokannan tunnistetietoihin, ja salaus hoitaa oman osuutensa
Oikea tiedostojen salaus on yksi kutsu HotXLS-komponentissa. Kurinalaisuus asuu kaikessa kutsun ympärillä: salasanojen hallinnassa, vain kirjoitettavassa rajassa (joka estää HotXLS:ää avaamasta omaa tulostettaan) ja salausväitteessä, jota voit puolustaa tarkastuksessa. SaveAsEncrypted ja perinteinen round-trip toimitetaan HotXLS Component -kirjaston mukana, ja ne toimivat natiivisti Delphi- ja C++Builder-prosesseissa ilman Excel-automaatiota missään vaiheessa polkua