يكتب HotXLS كتلة dataIntegrity مطابقة للمواصفة داخل حزم XLSX المشفّرة رشيقاً ويتحقق منها عند الفتح. يغطي HMAC-SHA-512 تيار EncryptedPackage بأكمله، بما في ذلك بادئة StreamSize ذات الثمانية بايتات، ويُفحص على النص المشفَّر قبل فك تشفير أي مقطع، بحيث تُكتشف كلمة مرور خاطئة أو حزمة مُعدَّلة بدلاً من فك تشفيرها إلى بيانات عشوائية
التشفير دون تكامل نصف إجابة، وصيغ ملفات Office تجعل هذه الثغرة سهلة التغافل عنها لأن التشفير يبدو شاملاً جداً من الخارج. فهم ما تعد به كل طبقة هو ما يبقي مراجعة الأمان قصيرة
ماذا يعد به مصنف عمل مشفَّر فعلياً؟
التشفير الرشيق، المعرَّف في [MS-OFFCRYPTO]، يمنحك السرية عبر AES في وضع CBC بمفتاح مشتق من تجزئة كلمة مرور SHA-512 مكررة. السرية هي الوعد الكامل لهذا البناء. CBC ليس وضعاً موثَّقاً: فهو لا يقول شيئاً عمّا إذا كان النص المشفَّر الذي تفك تشفيره هو النص المشفَّر الذي كُتب فعلاً
النتيجة العملية محددة. اقلب بتات في حزمة مشفَّرة وسيفك CBC تشفيرها بسعادة إلى نص صريح مختلف. ستحصل عادة على خطأ تحليل ZIP في مكان ما لاحقاً في المسار، لأن تيار deflate تالفاً نادراً ما ينجو، لكن كلمة «عادة» تحمل الكثير من العبء في تلك الجملة، وخطأ محلل لاحق مكان فظيع لتعلم أن ملفاً قد عُدِّل. يوجد عنصر dataIntegrity للإجابة على السؤال مباشرة، قبل فك التشفير، عبر MAC على البايتات بالضبط
كيف يعمل الفحص، وبأي ترتيب
الترتيب هو الجزء المثير للاهتمام. يشتق HotXLS المفتاح الوسيط من كلمة المرور، ويفك تشفير مفتاح وقيمة HMAC المشفَّرين من سمات dataIntegrity باستخدام متجهات تهيئة مشتقة من مفتاح الكتلة، ويحسب HMAC-SHA-512 على الحزمة المشفَّرة كما هي مخزَّنة، ثم يقارن. فقط بعد ذلك يبدأ فك تشفير المقاطع
فحص MAC على النص المشفَّر بدلاً من النص الصريح هو انضباط «التشفير ثم MAC» المعياري، وهو ما يجعل الفحص ذا معنى: تُرفض الحزمة المتلاعب بها دون تمرير أي بايتات يتحكم بها المهاجم عبر مسار فك التشفير وفك الضغط. تراكم كلا المقارنتين في مسار الفتح، تجزئة التحقق من كلمة المرور وقيمة HMAC، الاختلافات باستخدام XOR وOR عبر الملخص الكامل بدلاً من العودة مبكراً عند أول بايت غير متطابق، بحيث لا تسرّب أي منهما موضع بايت عبر التوقيت
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
// يعمل مع الملفات العادية والمشفَّرة قياسياً والمشفَّرة رشيقاً
if Book.OpenEncrypted('incoming.xlsx', PasswordFromVault) = 1 then
ProcessWorkbook(Book)
else
// كلمة مرور خاطئة، أو حزمة لم يتطابق HMAC الخاص بـ dataIntegrity فيها
Quarantine('incoming.xlsx');
except
on E: Exception do
Quarantine('incoming.xlsx: ' + E.Message);
end;
Book.Free;
end;
على جانب الكتابة لا يتغير شيء في كودك. تُصدر SaveAsEncrypted الكتلة تلقائياً، وتأتي الأملاح ومدخل التحقق ومفتاح HMAC من CryptGenRandom. إذا فشل ذلك الاستدعاء، يثير HotXLS استثناءً بدلاً من التراجع إلى مصدر أضعف. مولّد أرقام عشوائية مشفَّر بمبدأ الفشل المغلق ليس تحسباً مبالغاً فيه؛ فالتراجع الصامت إلى مصدر عشوائي يمكن التنبؤ به ينتج ملفات تبدو مشفَّرة، وتجتاز كل اختبار وظيفي، وتكون بلا قيمة
لماذا تُفتح الملفات الخالية من الكتلة على أي حال؟
لأن عدداً كبيراً جداً من مصنفات العمل المشفَّرة رشيقاً المتداولة كُتبت بواسطة مولّدات تحذف dataIntegrity تماماً، ورفضها سيُعطِّل عملاً مشروعاً أكثر بكثير مما سيحميه. يعامل HotXLS التكامل على أنه موجود فقط عندما يكون كلا السمتين، مفتاح HMAC المشفَّر وقيمة HMAC المشفَّرة، موجودتين وسليمتي البنية. وإلا يُتخطى التحقق ويُفتح الملف كما كان من قبل
هذا قرار توافق له نتيجة أمنية يجب أن تُسميها صراحةً في نموذج التهديد الخاص بك: لا يمكن التمييز بين غياب الكتلة وبين مهاجم أزالها، لأن السمات تقع خارج MAC الذي كانت ستحمله. إذا كنت تتحكم في طرفي خط الأنابيب، عامل الكتلة المفقودة كفشل سياسة على مستوى التطبيق. أما إذا كنت تقبل ملفات من العالم الخارجي، فعامل الفحص كما هو: إشارة قيّمة عند وجودها ولا إشارة على الإطلاق عند غيابها
كلمة مرور التعديل اتفاقية، لا حاجز حماية
تدعم مصنفات XLS الكلاسيكية آلية منفصلة يُخلط بينها وبين التشفير بشكل روتيني: حجز الكتابة، أي مطالبة إكسل بـ«كلمة مرور للتعديل». يعرضها HotXLS عبر SetModifyPassword، التي تأخذ كلمة المرور، وعلامة توصية بالقراءة فقط، واسم المستخدم الحاجز، وتُبلغ عن الحالة عبر IsWriteReserved. تمرير كلمة مرور فارغة يمسح الحجز
ما يُكتب هو زوج سجلات WRITEPROT وFILESHARING يحمل علامة التوصية بالقراءة فقط، وتجزئة كلمة مرور قديمة من 16 بت، واسم المستخدم كسلسلة يونيكود من نوع BIFF8. تلك التجزئة ذات الـ16 بت مجموع تحقق، لا ملخص تشفيري، ومحتوى المستند غير مشفَّر على الإطلاق. أي شخص يفتح الملف بأي أداة أخرى يقرأ كل شيء. المهمة الحقيقية لهذه الميزة هي التنسيق: فهي تخبر الشخص التالي أن أحدهم يعتبر هذا الملف ملكه ليحرّره، ضمن الفئة نفسها التي تندرج تحتها ضوابط مستوى الورقة الموضحة في حماية أوراق XLSX وخيارات السماح
var
Book: IXLSWorkbook; // معدود بالواجهة: لا تستدعِ Free
begin
Book := TXLSWorkbook.Create;
if Book.Open('shared-model.xls') = 1 then
begin
// توصية بالقراءة فقط، محجوز من قِبل خدمة إعداد التقارير
Book.SetModifyPassword('edit-me', True, 'Reporting Service');
if Book.IsWriteReserved then
Book.SaveAs('shared-model.xls', xlExcel97);
end;
end;
استخدم كلتا الطبقتين لما تجيده كل منهما. السرية الحقيقية تأتي من SaveAsEncrypted بكلمة مرور لا يمتلكها أحد خارج الجمهور المقصود، وهو ما ينتج مخرجات AES-256 الموضحة في مخرجات XLSX المحمية بـ AES. أما حجز الكتابة فيُضاف فوق ذلك عندما يكون مصنف العمل قطعة أثرية للتحرير المشترك وتريد من إكسل أن يسأل قبل أن يحفظ أحدهم فوقه
ما الذي يجب فحصه في مسار استيعاب غير موثوق
يحمي التحقق من التكامل الحمولة المشفَّرة، لا الحاوية المحيطة بها. ملف XLSX هو أرشيف ZIP، وتُحلَّل بنية الأرشيف قبل تشغيل أي منطق تشفير، لذا فإن التحقق على مستوى الحاوية ينتمي أولاً في السلسلة؛ وأنماط الفشل المحددة موضحة في التحقق من نهاية الدليل المركزي لـ ZIP لملفات XLSX غير الموثوقة. بعد ذلك، عامل فشل التكامل وكلمة المرور الخاطئة كالحدث التشغيلي نفسه، لأنهما من جانبك لا يمكن تمييزهما بالتصميم، وكلاهما يعني أنه لا يمكن الوثوق بأن الملف هو ما يظنه المرسل
سجّل أي الملفات حملت كتلة dataIntegrity أصلاً. عبر بضعة آلاف من المستندات، تخبرك هذه الإحصائية بشيء مفيد عن أدوات مُرسِليك، وتحوّل فحصاً لكل ملف على حدة إلى ملاحظة على مستوى الأسطول يمكنك التصرف بناءً عليها
يقرأ HotXLS ويكتب XLS وXLSX وODS من Delphi وC++Builder دون تثبيت إكسل، وينفّذ مساري تشفير [MS-OFFCRYPTO] القياسي والرشيق بلغة Pascal. واجهات برمجة التشفير والحماية ومصنف العمل موثَّقة على صفحة مكون HotXLS لجداول البيانات في Delphi