Το Excel εκθέτει δύο πράγματα που ονομάζονται και τα δύο "κωδικός πρόσβασης" (password), και μόνο ένα από αυτά είναι πραγματική κρυπτογράφηση. Ο κωδικός πρόσβασης ανοίγματος (open password) κλειδώνει έναν πραγματικό κρυπτογραφικό αλγόριθμο: χωρίς αυτόν το αρχείο δεν μπορεί να διαβαστεί καθόλου. Οι κωδικοί προστασίας φύλλου εργασίας και βιβλίου εργασίας δεν κάνουν τίποτα τέτοιο. Θέτουν απλώς μια σημαία (flag) την οποία ένας συνεργαζόμενος επεξεργαστής συμφωνεί να σεβαστεί, και ένα βιβλίο εργασίας που φέρει μόνο αυτή τη σημαία είναι ένα απλό, αναγνώσιμο αρχείο zip με τα δεδομένα σε μορφή απλού κειμένου. Επιλέξτε το λάθος και θα στείλετε μια μισθοδοσία που φαίνεται κλειδωμένη στο Excel αλλά διαβάζεται σε οποιονδήποτε επεξεργαστή κειμένου
Η απόδειξη διαρκεί δέκα δευτερόλεπτα. Μετονομάστε ένα προστατευμένο .xlsx σε .zip, ανοίξτε το σε οποιοδήποτε εργαλείο αρχειοθέτησης και κοιτάξτε το xl/worksheets/sheet1.xml. Εάν οι τιμές των κελιών είναι εκεί σε απλό UTF-8, το αρχείο δεν είναι κρυπτογραφημένο, ανεξάρτητα από το πόσες προτροπές κωδικού πρόσβασης εμφανίζει το Excel όταν κάποιος προσπαθεί να επεξεργαστεί ένα κελί. Αυτό το κενό επιβιώνει για χρόνια σε ομάδες που υποθέτουν ότι η προστασία φύλλου σημαίνει εμπιστευτικότητα, και συνήθως έρχεται στην επιφάνεια τη μέρα που μια αξιολόγηση ασφαλείας εκτελεί ακριβώς αυτή τη μετονομασία
Το HotXLS είναι μια εγγενής βιβλιοθήκη υπολογιστικών φύλλων για Delphi και C++Builder, και κρατά τα δύο αυτά χαρακτηριστικά σε αντίθετες πλευρές αυτής της γραμμής. Η προστασία φύλλου εργασίας και βιβλίου εργασίας είναι περιορισμοί επεξεργασίας που υποστηρίζονται από έναν σκόπιμα αδύναμο παλαιό κατακερματισμό (hash). Η SaveAsEncrypted παράγει ένα κρυπτογραφημένο με AES πακέτο που τίποτα λιγότερο από τον κωδικό πρόσβασης δεν θα ανοίξει. Οι παρακάτω ενότητες καλύπτουν τι γράφει αυτή η κλήση, την ασυμμετρία γύρω από την οποία πρέπει να σχεδιάσετε (το HotXLS γράφει κρυπτογραφημένα αρχεία αλλά δεν μπορεί να τα διαβάσει πίσω) και πώς διαφέρει η παλαιότερη διαδρομή XLS
Γιατί η προστασία φύλλου δεν είναι κρυπτογράφηση
Οι μέθοδοι Protect στα φύλλα και η ProtectWorkbook στο βιβλίο εργασίας αποθηκεύουν έναν δεκαεξαδικό κατακερματισμό 4 ψηφίων του κωδικού πρόσβασης. Αυτός είναι ο παλαιός αλγόριθμος που κληρονόμησαν το OOXML και το BIFF από το Excel της δεκαετίας του 1990, και η τεκμηρίωση της μορφής δεν ισχυρίστηκε ποτέ ότι κάνει κάτι περισσότερο από το να σταματά τις τυχαίες επεξεργασίες. Το πακέτο παραμένει ένα συνηθισμένο αναγνώσιμο zip: δεδομένα κελιών, τύποι και κοινόχρηστες συμβολοσειρές (shared strings) όλα σε XML απλού κειμένου. Η προεπιλογή το κάνει χειρότερο, όχι καλύτερο. Κάθε κελί ξεκινά με Locked=True, επομένως η κλήση της Protect χωρίς προηγούμενο ξεκλείδωμα ενός εύρους εισαγωγής παγώνει ολόκληρο το φύλλο έναντι επεξεργασίας, αφήνοντας παράλληλα κάθε τιμή σε κοινή θέα
Τίποτα από αυτά δεν καθιστά την προστασία άχρηστη. Η καθοδήγηση των χρηστών σε επεξεργάσιμα εύρη και η σταθεροποίηση μιας διάταξης για εκτύπωση είναι πραγματικές εργασίες, που καλύπτονται στο άρθρο μας για την προστασία φύλλου εργασίας και τη διαμόρφωση σελίδας. Αλλά αυτές είναι εργασίες ευχρηστίας. Τη στιγμή που η απαίτηση είναι η εμπιστευτικότητα, το μόνο API που απαντά σε αυτήν είναι το SaveAsEncrypted
Τι γράφει πραγματικά το SaveAsEncrypted
Η υλοποίηση ακολουθεί την Τυπική Κρυπτογράφηση (Standard Encryption) ECMA-376, που ορίζεται στο [MS-OFFCRYPTO] ενότητα 2.3.4. Ο κωδικός πρόσβασης περνά από 50.000 επαναλήψεις SHA-1 για την παραγωγή ενός κλειδιού AES-128. Ένα μπλοκ επαλήθευσης (verifier block), κρυπτογραφημένο με AES-128 σε λειτουργία ECB, επιτρέπει σε έναν καταναλωτή να επιβεβαιώσει τον κωδικό πρόσβασης πριν αποκρυπτογραφήσει οτιδήποτε, και ολόκληρο το πακέτο του βιβλίου εργασίας κρυπτογραφείται στη συνέχεια με AES-128 σε λειτουργία CBC. Αυτό που καταλήγει στο δίσκο δεν είναι καθόλου αρχείο zip. Είναι ένα σύνθετο αρχείο OLE (OLE compound file) που περιέχει τις ροές EncryptionInfo, EncryptedPackage και DataSpaces, χωρίς κατάλογο xl/ για να τον καταγράψει ένα εργαλείο αρχειοθέτησης, γι' αυτό και η δοκιμή μετονομασίας τώρα δεν εμφανίζει τίποτα αναγνώσιμο. Το Excel 2007 και οι μεταγενέστερες εκδόσεις το ανοίγουν μόνο με τον κωδικό πρόσβασης, και το τρέχον LibreOffice διαβάζει επίσης την Τυπική Κρυπτογράφηση
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;
Αντιμετωπίστε τη μεταβλητή του κωδικού πρόσβασης με την ίδια προσοχή όπως μια συμβολοσειρά σύνδεσης (connection string). Ανακτήστε την από ένα θησαυροφυλάκιο (vault) ή μια υπηρεσία παραγωγής μυστικών την τελευταία στιγμή, μην την καταγράφετε ποτέ σε αρχεία καταγραφής (logs), και μην τη γράφετε ποτέ μέσα στο ίδιο το βιβλίο εργασίας. Ο έλεγχος του κωδικού επιστροφής δεν είναι προαιρετική τελετή. Μια κρυπτογραφημένη αποθήκευση που αποτυγχάνει στη μέση πρέπει να διακόψει την παράδοση, επειδή η μόνη εναλλακτική λύση που μπορεί να προσφέρει ο καλών κώδικας είναι ένα μη κρυπτογραφημένο αντίγραφο, και αυτό το αντίγραφο είναι ακριβώς το περιστατικό που αυτή η δυνατότητα υπάρχει για να αποτρέψει
Υπάρχει επίσης μια αυτοματοποιημένα ελέγξιμη δοκιμή αποδοχής που δεν κοστίζει σχεδόν τίποτα: καλέστε την CanReadEncrypted στο αρχείο που μόλις γράψατε. Επιστρέφει true μόνο όταν η έξοδος είναι όντως ένα κοντέινερ κρυπτογράφησης, οπότε η επαλήθευσή της μετά από κάθε κρυπτογραφημένη αποθήκευση εντοπίζει την πιο κρίσιμη παλινδρόμηση — μια διαδρομή κώδικα που σιωπηρά επέστρεψε σε απλή SaveAs — τη στιγμή που συμβαίνει και όχι εβδομάδες αργότερα στα εισερχόμενα ενός πελάτη. Ο τελικός λόγος εξακολουθεί να ανήκει σε ένα χειροκίνητο άνοιγμα στο Excel με τον πραγματικό κωδικό πρόσβασης κατά τις δοκιμές έκδοσης
Μόνο για εγγραφή από σχεδιασμό: χειρισμός της EXlsxEncryptionNotImplemented
Εδώ είναι η ασυμμετρία που θα πρέπει να διαμορφώσει την αρχιτεκτονική της ροής εργασίας σας: το HotXLS κρυπτογραφεί κατά την αποθήκευση αλλά δεν αποκρυπτογραφεί κατά το άνοιγμα. Η OpenEncrypted εγείρει την εξαίρεση EXlsxEncryptionNotImplemented όταν δείχνει σε ένα πραγματικά κρυπτογραφημένο πακέτο· σε ένα απλό βιβλίο εργασίας απλώς μεταβαίνει σε ένα κανονικό Open. Η συνοδευτική δοκιμή CanReadEncrypted ανιχνεύει το κοντέινερ κρυπτογράφησης OLE οικονομικά, έτσι ώστε ο κώδικας εισαγωγής να μπορεί να δρομολογήσει τέτοια αρχεία χωρίς να προκαλέσει την εξαίρεση:
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;
Αυτή η ασυμμετρία έχει μια ξεκάθαρη αρχιτεκτονική ερμηνεία: κρυπτογραφήστε στο άκρο παράδοσης, τελευταία. Κρατήστε το πρωτότυπο απλού κειμένου (plaintext master) εντός του ορίου εμπιστοσύνης σας, σε μια βάση δεδομένων, ένα αποθετήριο εγγράφων ή έναν κοινόχρηστο φάκελο με ελεγχόμενη πρόσβαση, και δημιουργήστε το κρυπτογραφημένο αντίγραφο ως το τελικό βήμα πριν το αρχείο φύγει από το σύστημα. Μια ροή εργασίας που αρχειοθετεί μόνο την κρυπτογραφημένη έξοδο έχει αποκλείσει τον εαυτό της από τα ίδια της τα δεδομένα, επειδή κανένα μεταγενέστερο στάδιο του ίδιου συστήματος δεν μπορεί να ξανανοίξει αυτά τα αρχεία. Όταν μια κατάντη διαδικασία HotXLS χρειαστεί ξανά το βιβλίο εργασίας, δώστε της το πρωτότυπο απλού κειμένου, ποτέ το τελικό προϊόν παράδοσης
Τυπική Κρυπτογράφηση AES-128 και η γραμμή συμμόρφωσης AES-256
Η κρυπτογράφηση αρχείων Office διατίθεται σε δύο γενιές. Η Τυπική Κρυπτογράφηση (Standard Encryption), αυτή που γράφει το HotXLS, χρησιμοποιεί AES-128 με παραγωγή κλειδιού SHA-1. Η κρυπτογράφηση Agile έφτασε αργότερα και μεταβαίνει σε AES-256 με SHA-512 και ένα διαφορετικό κοντέινερ κλειδιού που περιγράφεται σε XML. Και οι δύο ανοίγουν με διαφανή τρόπο στο Excel, και το AES-128 εξακολουθεί να είναι υπολογιστικά ασφαλές για την προστασία ενός αρχείου κατά τη μεταφορά σε έναν πελάτη
Η διαφορά παύει να είναι ακαδημαϊκή τη μέρα που ένα ερωτηματολόγιο ασφαλείας ζητά "κρυπτογράφηση AES-256 των αρχείων σε αδράνεια (at rest)". Η Τυπική Κρυπτογράφηση δεν πληροί αυτή τη γραμμή, ανεξάρτητα από το πόσο ισχυρός είναι ο κωδικός πρόσβασης, και καμία παράμετρος της SaveAsEncrypted δεν αλλάζει τον αλγόριθμο που εκπέμπει. Επομένως, δηλώστε το προφίλ με ακρίβεια στην τεκμηρίωση ασφαλείας σας: AES-128, Τυπική Κρυπτογράφηση ECMA-376, παραγωγή κλειδιού SHA-1 σε 50.000 επαναλήψεις. Ακόμη και ένας ισχυρισμός που επιβιώνει από τον έλεγχο αξίζει περισσότερο από έναν αισιόδοξο που καταρρέει κάτω από έναν έλεγχο
Η παλαιά διαδρομή XLS: RC4 για έξοδο, RC4 και XOR για είσοδο
Η πρόσοψη του BIFF έχει το αντίθετο σχήμα. Η κρυπτογράφηση της είναι παλαιότερη και ασθενέστερη, αλλά ο κύκλος είναι πλήρης: ό,τι γράφει, μπορεί επίσης να το διαβάσει πίσω. Η ρύθμιση του EncryptionPassword πριν από τη SaveAs παράγει ένα κρυπτογραφημένο με RC4 αρχείο .xls μέσω του μηχανισμού FilePass του BIFF, και η Open με μια παράμετρο κωδικού πρόσβασης διαβάζει και τα τρία παλαιά σχήματα, RC4, RC4 CryptoAPI και την αρχαία συσκότιση (obfuscation) 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 είναι ξεπερασμένη κρυπτογραφία και δεν θα πρέπει ποτέ να προστατεύει δεδομένα που έχουν σημασία σήμερα· η μόνη εναλλακτική αξία του είναι η διαλειτουργικότητα με συστήματα που εξακολουθούν να ανταλλάσσουν .xls. Η πλευρά της ανάγνωσης, ωστόσο, αξίζει τα λεφτά της σε εργασίες μετανάστευσης. Ένα προστατευμένο με κωδικό πρόσβασης παλαιό αρχείο ανοίγει με Open(FileName, Password), γεφυρώνεται στο μοντέλο OOXML, και επανασφαλίζεται μέσω της διαδρομής AES, μια μονόδρομη αναβάθμιση που εκτελείται χωρίς το Excel πουθενά στη διαδικασία. Για παραδόσεις κρυπτογραφημένων αρχείων μεγάλου όγκου, οι σημειώσεις απόδοσης της πλευράς αποθήκευσης στο άρθρο μας σχετικά με τις ροές εγγραφής για μαζικές εργασίες διακομιστή ισχύουν για τη φάση δημιουργίας περιεχομένου που συμβαίνει πριν από την κρυπτογράφηση
Η κρυπτογράφηση και η προστασία δεν είναι αντίπαλοι
Ένα ακόμη σημείο που αξίζει να ξεκαθαριστεί, επειδή προκύπτει τη στιγμή που κάποιος διαβάζει την προειδοποίηση στην κορυφή αυτής της σελίδας ως "η προστασία είναι άχρηστη". Δεν είναι. Η κρυπτογράφηση και η προστασία απαντούν σε διαφορετικά ερωτήματα, και συνδυάζονται καθαρά. Η κρυπτογράφηση αποφασίζει ποιος μπορεί να ανοίξει το αρχείο· η προστασία αποφασίζει τι μπορεί να αλλάξει ένας αναγνώστης που βρίσκεται ήδη μέσα. Μια παράδοση μισθοδοσίας μπορεί εύλογα να κάνει και τα δύο: να κρυπτογραφήσει το πακέτο ώστε μόνο ο κάτοχος του κωδικού πρόσβασης να το βλέπει, και στη συνέχεια να κλειδώσει τα κελιά των τύπων ώστε ο παραλήπτης να μπορεί να φιλτράρει και να ταξινομεί αλλά όχι να ξαναγράφει σιωπηρά τους υπολογισμούς. Το σφάλμα δεν είναι ποτέ η προσθήκη προστασίας. Το σφάλμα είναι να αφήνουμε την παρουσία της να υποκαθιστά την κρυπτογράφηση όταν η απαίτηση ήταν η εμπιστευτικότητα
Η πλευρά της φύλαξης δεν έχει δίχτυ ασφαλείας, και αυτό γίνεται από σχεδιασμό. Η παραγωγή κλειδιού με 50.000 επαναλήψεις υπάρχει για να κάνει τη μαντεψιά ακριβή, και τίποτα μέσα στο αρχείο δεν δεσμεύει το μυστικό. Ένας χαμένος κωδικός πρόσβασης είναι χαμένα δεδομένα. Δημιουργήστε, παραδώστε και αποθηκεύστε αυτούς τους κωδικούς πρόσβασης με την ίδια πειθαρχία που εφαρμόζετε στα διαπιστευτήρια βάσεων δεδομένων, και η κρυπτογράφηση θα κάνει τη δουλειά της
Η πραγματική κρυπτογράφηση αρχείων είναι μία κλήση στο HotXLS. Η πειθαρχία ζει σε όλα γύρω από την κλήση: τη φύλαξη κωδικών πρόσβασης, το όριο μόνο για εγγραφή που εμποδίζει το HotXLS να ξανανοίξει τη δική του έξοδο, και έναν ισχυρισμό αλγορίθμου που μπορείτε να υπερασπιστείτε σε έναν έλεγχο. Η SaveAsEncrypted και ο παλαιός κύκλος ανάγνωσης-εγγραφής αποστέλλονται με το HotXLS Component, εκτελώντας εγγενώς διεργασίες Delphi και C++Builder χωρίς αυτοματοποίηση του Excel πουθενά στη διαδρομή