HotXLS, Excel 2010 ve sonraki tüm sürümlerin varsayılan olarak uyguladığı parola koruması olan Agile şifreli Excel dosyalarını tek bir çağrıyla okur: TXLSXWorkbook.OpenEncrypted. Bileşen, XML şifreleme tanımlayıcısını ayrıştırır, SHA-512 döndürme sayısı (spin-count) karma zinciriyle paroladan anahtarlar türetir, parolayı şifreli doğrulayıcıya karşı doğrular ve ardından paketi 4096 baytlık AES-CBC bölümleri halinde çözer. Excel kurulumu, COM veya harici kripto DLL'i gerekmez
Bu makale özellikle Agile şifrelemenin okuma tarafını ele almaktadır. Komşu iki sorunun kendi makaleleri vardır: eski BIFF .xls dosyalarının içindeki eski RC4 ve XOR şemalarıyla birlikte çalışabilirlik ECB ve RC4 birlikte çalışabilirlik makalesinde, ECMA-376 Standart Şifreleme ile parola korumalı çalışma kitapları üretmek ise AES korumalı XLSX çıktısı makalesinde ele alınmıştır. Burada ise dosya zaten mevcuttur, bir başkası şifrelemiştir or göreviniz onu açmaktır
Bu sorunu zorunlu kılan senaryo, belge iş hattı işleten herkese tanıdıktır. Sunucu tarafındaki bir içe aktarma hizmeti çalışma kitabı yüklemelerini kabul eder; makinede Excel yoktur ve hiçbir zaman olmayacaktır; ve bir sabah bir müşteri ZIP okuyucunun reddettiği tamamen sıradan bir .xlsx yükler çünkü o aslında bir ZIP değildir. Müşteri onu bir parolayla kaydetmiştir. O andan itibaren yükleyiciniz ya [MS-OFFCRYPTO] standardını anlar ya da dosyayı, kendi açısından sıra dışı hiçbir şey yapmamış olan kullanıcıya geri gönderir
Excel dosyasında Agile şifreleme nedir?
Agile şifreleme, [MS-OFFCRYPTO] §2.3.4.10 ila §2.3.4.15 bölümlerinde tanımlanan parola koruma şemasıdır ve Excel 2010 ve sonrasının bir çalışma kitabı parola ile kaydedildiğinde yazdığı şeydir. Şifrelenmiş dosya artık bir ZIP paketi değildir. İki akış tutan bir OLE Compound File Binary (CFB) kapsayıcısıdır: şifrelemenin nasıl yapıldığını açıklayan EncryptionInfo ve şifreli bir blob olarak gerçek .xlsx ZIP dosyasını tutan EncryptedPackage. CFB imzası (D0 CF 11 E0 A1 B1 1A E1), eski BIFF .xls dosyalarının taşıdığı sihirli değerle aynıdır, bu nedenle yeniden adlandırılmış veya şifrelenmiş bir dosya yalnızca uzantıya göre sınıflandırılamaz
Agile'ı öncekilerden ayıran şey, EncryptionInfo akışının kendi kendini açıklayan bir yapıda olmasıdır. Ana ve alt sürümü 4 olan 8 baytlık bir sürüm önekinden sonra, akış bir UTF-8 XML tanımlayıcısıdır. Bir keyData öğesi; şifreyi (AES), zincirleme modunu (ChainingModeCBC), karmayı (SHA512), bit cinsinden anahtar uzunluğunu, blok boyutunu ve Base64 tuzunu bildirir. Bir parola keyEncryptor öğesi; kendi tuzunu, spinCount değerini ve üç adet Base64 yükünü taşır: encryptedVerifierHashInput, encryptedVerifierHashValue ve encryptedKeyValue. Excel, 100.000 döndürme sayısı ile AES-256 yazar, ancak tanımlayıcı AES-128 veya AES-192 bildirebilir ve HotXLS, 256 olduğunu varsaymak yerine keyBits değerinin bildirdiği şeye uyar
Düz metin, Standart ve Agile çalışma kitapları için tek bir giriş noktası
TXLSXWorkbook.OpenEncrypted, çağıranın karşılaşabileceği üç durumu da (düz ZIP, Standart şifreli ve Agile şifreli) yönetir; böylece yükleme işleyicilerinin dosyaları yüklemeden önce sınıflandırmasına gerek kalmaz. Yöntem önce dosyayı koklar (sniff): eğer bir CFB imzası yoksa, normal Open yoluna geçer ve parola yok sayılır. Eğer dosya bir CFB kapsayıcısıysa, önce ECMA-376 Standart Şifrelemeyi dener ve EncryptionInfo sürüm imzası Agile 4.4 olduğunda Agile iş hattına gönderir. Dönüş değeri, Open ile aynı sözleşme olan 1 değeridir
var
Wb: TXLSXWorkbook;
begin
Wb := TXLSXWorkbook.Create;
try
// Works for plain .xlsx, Standard-encrypted and
// Agile-encrypted files alike
if Wb.OpenEncrypted('upload.xlsx', 'customer-password') = 1 then
Writeln(VarToWideStr(Wb.Sheets[1].Cells[1, 1].Value));
finally
Wb.Free;
end;
end;
Şifrelenmemiş girdi için geri dönüş seçeneği göründüğünden daha önemlidir. Her zaman OpenEncrypted çağıran bir toplu içe aktarıcının çağrı alanında dallanmaya ihtiyacı yoktur: hiç korunmamış dosyalar eskisi gibi yüklenir ve şifreli gelen dosyalar yerinde çözülür ve ardından sıradan ZIP yükleyicisine bellek içi bir akış olarak beslenir. Test edilecek üç kod yolu değil, tek bir kod yolu vardır
Bir parola nasıl bir AES anahtarına dönüşür?
Agile şifreleme parolayı asla doğrudan kullanmaz. HotXLS önce yinelenen bir karma hesaplar: ilk özet, parolanın UTF-16LE baytları ile birleştirilmiş parola tuzu üzerinde SHA-512'dir ve ardından özet spinCount kez yeniden karma işlemine tabi tutulur; her turda önceki özete 32 bitlik küçük endian yineleme sayacı eklenir. Excel'in varsayılan 100.000 döndürme sayısı ile bu, parola denemesi başına yüz bin ardışık SHA-512 çağrısı demektir ve asıl mesele de budur. Döndürme sayısı bir kaba kuvvet (brute-force) sınırlayıcıdır: meşru bir arayana bir kez birkaç milisaniyeye mal olurken, bir sözlük saldırganına her bir tahmin için aynı birkaç milisaniyeye mal olur
// [MS-OFFCRYPTO] iterated password hash:
// H(0) = SHA-512(salt + UTF-16LE(password))
// H(n) = SHA-512(LE32(n - 1) + H(n - 1)), repeated spinCount times
function AgilePasswordHash(const Password: WideString;
const Salt: TBytes; SpinCount: Integer): TBytes;
var
buf: TBytes;
i: Integer;
begin
Result := XlsSHA512(Concat(Salt, Utf16LEBytes(Password)));
SetLength(buf, 4 + 64);
for i := 0 to SpinCount - 1 do
begin
PutLE32(buf, 0, i); // iteration counter, little-endian
Move(Result[0], buf[4], 64); // previous digest
Result := XlsSHA512(buf);
end;
end;
Döndürülmüş karma hala bir anahtar değildir. Sonuna eklenen sabit bir blok anahtarı (amaç başına bir sabit) ile bir kez daha karma işlemine tabi tutularak ondan üç farklı anahtar türetilir: doğrulayıcı girdisinin şifresini çözmek için FE A7 D2 76 3B 4B 9E 79, doğrulayıcı karması için D7 AA 0F 6D 30 61 34 4E ve gerçek paket anahtarını açmak için 14 6E 0B E7 AB AC D0 D6. Her SHA-512 sonucu bildirilen anahtar uzunluğuna göre kesilir ve [MS-OFFCRYPTO] uyarınca, karmanın anahtardan daha kısa olduğu teorik durumda 0x36 baytlarıyla doldurulur. Aynı 0x36 dolgu kuralı, CBC başlatma vektörü olarak kullanılmak üzere parola tuzu blok boyutuna uzatıldığında da geçerlidir
Parola doğrulaması ve saltSize kesme tuzağı
HotXLS, tanımlayıcıdan gelen doğrulayıcı çiftini kullanarak pakete dokunmadan önce parolayı doğrular. İlk türetilmiş anahtarla encryptedVerifierHashInput değerinin şifresini çözer, sonucu SHA-512 ile karma işlemine tabi tutar, encryptedVerifierHashValue değerinin şifresini ikinci türetilmiş anahtarla çözer ve iki özeti bayt bayt karşılaştırır. Eşleşmeme durumu, parolanın yanlış olduğu anlamına gelir; bu durum bozuk bir çalışma kitabı yerine belirgin bir sonuç olarak bildirilir ve kritik olarak, paket gövdesinin yanlış bir parolayla asla çözülmediği anlamına gelir, böylece yanlış bir parolanın makul görünen bozuk veriler ürettiği bir senaryo yaşanmaz
Burada yanlış yapılması kolay bir spesifikasyon detayı vardır. [MS-OFFCRYPTO] §2.3.4.13, doğrulayıcıyı şifre blok boyutu değil, anahtar şifreleyicinin tuz uzunluğu olan saltSize baytlık rastgele veri olarak tanımlar. AES-CBC şifreli metni blok hizalamalı olduğundan, şifresi çözülen doğrulayıcı girdisi 16 baytın katına doldurulmuş olarak geri döner ve karma işleminden önce saltSize uzunluğuna kesilmelidir. Excel her zaman saltSize değerini blok boyutuna eşit yazar (her ikisi de 16), bu nedenle kesmeyi atlayan bir uygulama gerçek Excel çıktısına karşı her testi geçer ve ardından farklı bir tuz uzunluğu seçen bir üreticinin ilk dosyasında başarısız olur. HotXLS, tuz uzunluğuna göre keser çünkü spesifikasyonun gerçekten söylediği budur ve iki değerin uygulamada uyuşması bir sözleşme değil, bir tesadüftür
EncryptedPackage şifresi nasıl çözülür?
EncryptedPackage akışı 8 baytlık küçük endian düz metin boyutuyla başlar, ardından 4096 baytlık bölümler halinde şifreli metin gelir ve HotXLS her bölüm için yeni bir IV ile bölüm bölüm şifreyi çözer. Paket anahtarının kendisi paroladan türetilmez: yazarın encryptedKeyValue içine şifrelediği rastgele bir ara anahtardır ve HotXLS, bunu üçüncü türetilmiş anahtarla açarak keyData tarafından bildirilen anahtar uzunluğuna göre keser. Her bölümün IV'ü, segment dizini ile birleştirilmiş keyData tuzu üzerinde SHA-512'dir ve blok boyutuna göre kesilir. Bu yapı, herhangi bir 4096 baytlık bölümün bağımsız olarak çözülebileceği anlamına gelir; bu da formatı teoride rastgele erişime uygun kılan şeydir, ancak HotXLS paketin tamamını bellekte çözer ve dönen ZIP baytlarını normal XLSX yükleyicisine teslim eder
Bildirilen düz metin boyutu son işi yapar. AES-CBC çıktısı blok hizalamalıdır, bu nedenle son bölüm belgenin parçası olmayan 15 bayta kadar dolgu taşır; çözülen arabellek boyut önekine göre kesilir ve sonuç tam olarak Excel'in şifrelediği .xlsx ZIP dosyasıdır. HotXLS, şifreyi çözmeden önce öneki gerçek akış uzunluğuna karşı doğrular, böylece eksik bir yükleme veya kurcalanmış bir boyut alanı taşma yapmak yerine temiz bir şekilde başarısız olur
Hata raporlama ve dürüst sınırlar
Başarısızlık modları bilinçli olarak ayrı tutulur. Yanlış bir parola, doğrulayıcı uyuşmazlığının tetiklediği açık bir yanlış parola mesajıyla bir istisna fırlatır, böylece kullanıcı arayüzü kullanıcıdan yeniden denemesini isteyebilir. Agile tanımlayıcısındaki AES-CBC ve SHA-512 dışındaki algoritmaları bildiren bir CFB kapsayıcısı veya ne Standart ne de Agile olan bir kapsayıcı, şemayı desteklenmeyen olarak tanımlayan farklı bir istisna fırlatır. İkisi asla karıştırılmamalıdır: desteklenmeyen bir şemaya karşı parolayı yeniden denemek kullanıcının zamanını boşa harcar ve yanlış bir parolayı format hatası olarak bildirmek destek ekibinizi yanlış yola sokar
function LoadUploadedWorkbook(const FileName: WideString;
const Password: WideString; Wb: TXLSXWorkbook): Boolean;
begin
Result := False;
try
Result := Wb.OpenEncrypted(FileName, Password) = 1;
except
on E: EXlsxEncryptionNotImplemented do
// Raised for both a wrong password and an unsupported
// scheme; E.Message states which, so log it verbatim and
// only offer a password retry for the wrong-password case
RejectUpload(FileName, E.Message);
end;
end;
Sınırların açıkça belirtilmesi gerekir. HotXLS, Excel 2010'dan Excel 365'e kadar olan sürümlerin her üç anahtar boyutunda da yazdıklarını kapsayan, CBC modunda AES ve SHA-512 bildiren Agile tanımlayıcılarını okur. Diğer şifreleri veya karma algoritmalarını bildiren tanımlayıcılar tahmin yürütülmek yerine reddedilir ve yalnızca parola anahtar şifreleyicisine danışılır, sertifika tabanlı anahtar şifreleyicilerine danışılmaz. Yazma tarafında HotXLS şu anda Agile yerine Standart Şifreleme üretmektedir; bu ayrım ardıl araçların şemayı incelemesi durumunda önem kazanır; ayrıntılar AES korumalı XLSX çıktısı yazma makalesindedir
Parola korumalı yüklemeler, yükleyici şifrelemeyi bir istisna olarak değil, dosya biçiminin bir parçası olarak gördüğünde özel bir durum olmaktan çıkar. Burada açıklanan OpenEncrypted giriş noktası, SHA-512 döndürme sayısı türetimi ve segmentli AES-CBC iş hattı, Delphi ve C++Builder için yerel XLS ve XLSX okuma ve yazma motoruyla birlikte HotXLS Delphi Excel Bileşeni'nin bir parçası olarak sunulur