Excel exponerar två saker som båda kallas ”lösenord”, och endast en av dem är kryptering. Lösenordet för öppning styr ett riktigt chiffer: utan det kan filen inte läsas alls. Lösenorden för arbetsblads- och arbetsboksskydd gör ingenting av det slaget. De sätter en flagga som en samarbetsvillig redigerare går med på att respektera, och en arbetsbok som bara bär på den flaggan är en vanlig läsbar zip-fil där data ligger i klartext. Välj fel och du skickar ut löneutbetalningar som ser låsta ut i Excel men kan läsas i vilken textredigerare som helst
Beviset tar tio sekunder. Döp om en skyddad .xlsx till .zip, öppna den i valfritt arkivverktyg och titta på xl/worksheets/sheet1.xml. Om cellvärdena finns där i vanlig UTF-8 är filen inte krypterad, oavsett hur många lösenordsprompter Excel visar när någon försöker redigera en cell. Det glappet överlever i åratal inom team som antar att bladskydd innebär sekretess, och det dyker vanligtvis upp den dag en säkerhetsgranskning gör just den här omdöpningen
HotXLS är ett inbyggt kalkylbladsbibliotek för Delphi och C++Builder, och det håller de två funktionerna på motsatta sidor av den linjen. Arbetsblads- och arbetsboksskydd är redigeringsbegränsningar som stöds av en medvetet svag äldre hash. SaveAsEncrypted producerar ett AES-krypterat paket som inget annat än lösenordet kan öppna. Avsnitten nedan beskriver vad det anropet skriver, asymmetrin du måste bygga din design kring (HotXLS skriver krypterade filer men kan inte läsa tillbaka dem) och hur den äldre XLS-sökvägen skiljer sig åt
Varför bladskydd inte är kryptering
Metoderna Protect på blad och ProtectWorkbook på arbetsboken sparar en 4-hexadecimal-siffrig hash av lösenordet. Det är den äldre algoritm som OOXML och BIFF båda ärvde från 1990-talets Excel, och formatdokumentationen påstår aldrig att den gör mer än att förhindra oavsiktliga redigeringar. Paketet förblir en vanlig läsbar zip-fil: celldata, formler och delade strängar i klartext XML. Standardinställningen gör det värre, inte bättre. Varje cell börjar med Locked=True, så att anropa Protect utan att först låsa upp ett inmatningsintervall fryser hela bladet mot redigering medan varje värde lämnas helt synligt
Inget av detta gör skydd värdelöst. Att styra användare till redigerbara intervall och stabilisera en layout för utskrift är verkliga uppgifter, vilka behandlas i vår artikel om arbetsbladsskydd och sidinställningar. Men detta är användbarhetsuppgifter. I samma ögonblick som kravet är konfidentialitet är det enda API som svarar mot det SaveAsEncrypted
Vad SaveAsEncrypted faktiskt skriver
Implementeringen följer ECMA-376 Standard Encryption, specifierad i [MS-OFFCRYPTO] avsnitt 2.3.4. Lösenordet körs genom 50 000 iterationer av SHA-1 för att härleda en AES-128-nyckel. Ett verifierarblock, krypterat med AES-128 i ECB-läge, låter en konsument bekräfta lösenordet innan den dekrypterar något, och hela arbetsbokspaketet krypteras sedan med AES-128 i CBC-läge. Det som hamnar på disken är inte alls en zip-fil. Det är en OLE Compound-fil som innehåller strömmarna EncryptionInfo, EncryptedPackage och DataSpaces, utan någon xl/-katalog som ett arkivverktyg kan lista, vilket är anledningen till att omdöpningstestet nu inte visar något läsbart. Excel 2007 och senare öppnar den med enbart lösenordet, och nuvarande LibreOffice läser också 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'; // Anställd
Sheet.Cells[1, 2].Value := 'Net pay'; // Nettolön
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;
Behandla lösenordsvariabeln med samma omsorg som en anslutningssträng. Hämta den från ett valv eller en tjänst för genererade hemligheter i sista sekunden, logga den aldrig och skriv den aldrig i själva arbetsboken. Kontrollen av returkoden är inte en valfri ceremoni. En krypterad sparning som misslyckas halvvägs måste avbryta leveransen, eftersom det enda reservalternativ som den anropande koden kan erbjuda är en okrypterad kopia, och den kopian är exakt den incident som denna funktion finns till för att förhindra
Det finns också ett maskinkontrollerbart acceptanstest som nästan inte kostar någonting: anropa CanReadEncrypted på filen du precis skrev. Det returnerar sant endast när utdata verkligen är en krypteringsbehållare, så att verifiera det efter varje krypterad sparning fångar den regression som spelar mest roll — en kodväg som tyst föll tillbaka på en vanlig SaveAs — i samma ögonblick som det inträffar istället för veckor senare i en kunds inkorg. Det som framgår i sista hand avgörs dock vid en manuell öppning i Excel med det riktiga lösenordet under releasetestning
Write-only av design: hantera EXlsxEncryptionNotImplemented
Här är den asymmetri som bör forma din pipeline-arkitektur: HotXLS krypterar vid sparning men dekrypterar inte vid öppning. OpenEncrypted utlöser EXlsxEncryptionNotImplemented när den pekar på ett faktiskt krypterat paket; på en vanlig kalkylbok faller den helt enkelt igenom till en normal Open. Den kompletterande sökningen CanReadEncrypted upptäcker OLE-krypteringsbehållaren billigt, så att mottagningskoden kan dirigera sådana filer utan att utlösa undantaget:
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.CanReadEncrypted(FileName) then
begin
// Krypterad behållare: HotXLS kan inte dekryptera den.
Writeln(FileName + ': needs manual decryption in Excel first');
Exit;
end;
try
Book.OpenEncrypted(FileName, ''); // vanliga filer faller igenom till Open
Writeln(FileName + ': opened, ' + IntToStr(Book.Sheets.Count) + ' sheet(s)');
except
on EXlsxEncryptionNotImplemented do
Writeln(FileName + ': krypterad - dirigerad till manuell kö');
end;
finally
Book.Free;
end;
end;
Den asymmetrin har en tydlig arkitektonisk tolkning: kryptera vid leveransgränsen, sist. Behåll plaintext-originalet inom din förtroendegräns, i en databas, ett dokumentarkiv eller en åtkomstkontrollerad delad resurs, och producera den krypterade kopian som det sista steget innan filen lämnar systemet. En pipeline som endast arkiverar de krypterade utdata har låst sig ute från sina egna data, eftersom inget senare skede i samma system kan öppna dessa filer igen. När en efterföljande HotXLS-process behöver arbetsboken igen, ge den plaintext-originalet, aldrig leveransartefakten
AES-128 Standard Encryption och överensstämmelsegränsen för AES-256
Kryptering av Office-filer finns i två generationer. Standard Encryption, den som HotXLS skriver, använder AES-128 med SHA-1-nyckelgenerering. Agile Encryption kom senare och går över till AES-256 med SHA-512 och en annan, XML-beskriven nyckelbehållare. Båda öppnas transparent i Excel, och AES-128 är fortfarande beräkningsmässigt säkert för att skydda en fil under överföring till en kund
Skillnaden upphör att vara akademisk den dag ett säkerhetsformulär frågar efter ”AES-256-kryptering av vilande filer (files at rest)”. Standard Encryption uppfyller inte den gränsen, oavsett hur starkt lösenordet är, och ingen parameter i SaveAsEncrypted ändrar algoritmen som den skickar ut. Ange därför profilen exakt i din säkerhetsdokumentation: AES-128, ECMA-376 Standard Encryption, SHA-1-nyckelgenerering med 50 000 iterationer. Ett påstående som överlever en granskning är mer värt än ett optimistiskt som faller samman under en revision
Den äldre XLS-sökvägen: RC4 ut, RC4 och XOR tillbaka in
BIFF-fasaden har motsatt form. Dess kryptering är äldre och svagare, men round-trip är komplett: det den skriver kan den också läsa tillbaka. Att ställa in EncryptionPassword före SaveAs producerar en RC4-krypterad .xls via BIFF FilePass-mekanismen, och Open med en lösenordsparameter läser alla tre äldre scheman: RC4, RC4 CryptoAPI och den urgamla XOR-obfuskeringen:
var
Writer, Reader: IXLSWorkbook; // gränssnittsreferenser: ingen manuell Free
begin
Writer := TXLSWorkbook.Create;
Writer.Sheets.Add.Cells.Item[1, 1].Value := 'Confidential'; // Konfidentiellt
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); // Poster är 1-baserade
end;
RC4 är föråldrad kryptografi och bör aldrig skydda data som har betydelse idag; dess endast kvarvarande värde är samverkan med system som fortfarande utbyter .xls. Lässidan gör dock nytta i migreringsarbete. En lösenordsskyddad äldre fil öppnas med Open(FileName, Password), bryggas över till OOXML-modellen och säkras på nytt via AES-sökvägen — en enkelriktad uppgradering som körs utan att Excel behövs någonstans i loopen. För krypterade leveranser med hög volym gäller anmärkningarna om genomströmning på sparningssidan i vår artikel om strömmande skrivningar för serverseriejobb för den fas där innehållet byggs upp, vilket sker före krypteringen
Kryptering och skydd är inte rivaler
Ytterligare en punkt är värd att reda ut, eftersom den dyker upp i samma ögonblick som någon läser varningen högst upp på denna sida som ”skydd är värdelöst”. Det är det inte. Kryptering och skydd besvarar olika frågor, och de kan kombineras rent. Kryptering avgör vem som kan öppna filen; skydd avgör vad en läsare som redan är inne i filen får ändra. En löneleverans kan rimligen göra båda: kryptera paketet så att endast innehavaren av lösenordet ser det, och sedan låsa formelcellerna så att mottagaren kan filtrera och sortera men inte i hemlighet skriva om beräkningarna. Felet är aldrig att lägga till skydd. Felet är att låta dess närvaro ersätta kryptering när kravet var konfidentialitet
Lösenordshanteringen har inget skyddsnät, och det är avsiktligt. Nyckelgenereringen med 50 000 iterationer finns till för att göra gissningar dyra, och ingenting inuti filen deponerar hemligheten. Ett förlorat lösenord är förlorade data. Generera, leverera och lagra dessa lösenord med samma disciplin som du tillämpar på databasautentiseringsuppgifter, så sköter krypteringen sin del
Riktig filkryptering är ett anrop i HotXLS. Disciplinen lever i allt runt anropet: lösenordshantering, gränsen för write-only som förhindrar HotXLS från att öppna sina egna utdata igen, och ett påstående om algoritm som du kan försvara i en granskning. SaveAsEncrypted och den äldre round-trip levereras med HotXLS Component, och körs inbyggt i Delphi- och C++Builder-processer utan någon Excel-automation någonstans i kedjan