مقال تقني

تعتيم XOR في ملفات XLS مع HotXLS: اشتقاق المفتاح و XorRor

يكتب HotXLS مصنفات BIFF5 ‏(Excel 5.0/95) معتمّة بـ XOR لا يفتحها Excel 16 إلا إذا تطابقت ثلاث تفاصيل مع [MS-OFFCRYPTO] تماماً: يجب أن يكون مفتاح FILEPASS هو CreateXorKey_Method1(password)، وبناء مصفوفة XOR ذات الـ 16 بايتة بـ XorRor ‏(تدوير يمين بمقدار بتة واحدة)، واستخدام كل بايتةٍ XorArrayIndex = ‏(إزاحة التدفق + طول السجل) mod 16. أصاب HotXLS الفهرس في v2.384.47 والمفتاح والتدوير في v2.384.54. وقبل ذلك كان كل ملف BIFF5 محمي بكلمة سر ينتجه يفتح في HotXLS بلا مشكلة ويفشل في Excel

تلك الجملة الأخيرة هي الحكاية كلها في صورة مصغرة. القارئ والكاتب اللذان يتقاسمان الفكرة الخاطئة نفسها يوافق كل منهما الآخر توافقاً تاماً، فتبقى اختبارات الدورة خضراء بينما المستهلك الوحيد المهم يقول لا. وقال Excel 16 لا مرتين، برسالتين مختلفتين، وأشارت كل رسالة إلى طبقة مختلفة من المخطط. تمشي هذه المقالة في تلك الطبقات بترتيب فحص Excel لها، بتفصيل على مستوى البايتة ينفعك سواء استدعيت HotXLS أو كتبت قارئ BIFF خاص بك

ماذا يخزن تعتيم BIFF XOR فعلاً؟

لا يخزن تعتيم BIFF XOR في الملف إلا كلمتين 16-بت، وكل ما عداهما يعاد حسابه من كلمة السر. يجلس سجل FILEPASS ‏($002F) بعد BOF لمتغيرات المصنف العامة مباشرةً، وجسمه في ملف BIFF5 ‏4 بايتات بالضبط: مفتاح XOR يليه المُتحقِّق من كلمة السر. ولا ملح، ولا معرّف خوارزمية، ولا كتلة تحقق مشفرة من النوع الذي تحمله مخططات RC4 و AES

من تلك الكلمتين يعيد القارئ بناء ثلاثة أشياء:

  • المُتحقِّق، تجزئة 16-بت لبايتات كلمة السر مؤثَّرة بـ XOR مع $CE4B. ومقارنته بالكلمة المخزنة هي فحص كلمة السر، والفحص الوحيد
  • مفتاح XOR، قيمة 16-بت من CreateXorKey_Method1 في [MS-OFFCRYPTO] §2.3.7.2، يقودها جدولان ثابتان ‏(InitialCode بـ 15 كلمة و XorMatrix بـ 105 كلمات)
  • مصفوفة XOR، 16 بايتة من بايتات كلمة السر مدعومة بوسادة ثابتة من 16 بايتة، تؤثر كل بايتة بـ XOR مع بايتة المفتاح الدنيا (المواضع الزوجية) أو العليا (المواضع الفردية)، ثم تُدوَّر يميناً بمقدار بتة واحدة

تبقى ترويسات السجلات نصاً صريحاً، وكذلك حفنة سجلات كاملة يعفيها المخطط، من بينها BOF و FILEPASS و INTERFACEHDR. وكل جسم سجل آخر يتحول بايتةً بايتة: تدوير يسار بمقدار 5 بتات، ثم XOR مع مدخل واحد من مصفوفة الـ 16 بايتة. وفك التشفير، الذي يهجئه [MS-OFFCRYPTO] §2.3.7.3 باسم DecryptData_Method1، هو الصورة المعكوسة: XOR أولاً، ثم تدوير يمين بمقدار 5

في HotXLS لا تلمس شيئاً من هذا مباشرةً قط. تضبط كلمة سر وتختار الصيغة، فيبث SaveAs ‏FILEPASS ويحول التدفق:

uses
  SysUtils, lxHandle;

procedure SaveLegacyProtectedBook(const FileName: string);
var
  Wb: IXLSWorkbook;
begin
  Wb := TXLSWorkbook.Create;
  Wb.Sheets.Add.Name := 'Ledger';
  Wb.Sheets[1].Range['A1', 'A1'].Value := 'Account';
  Wb.Sheets[1].Range['B1', 'B1'].Value := 1250.75;

  // ‏BIFF5 يدعم تعتيم XOR وحده؛ وكان xletAuto سيختاره هو أيضاً
  Wb.EncryptionType := xletXor;
  // أبقه ASCII وبخمسة عشر محرفاً على الأكثر (انظر أدناه)
  Wb.EncryptionPassword := 'secret';

  if Wb.SaveAs(FileName, xlExcel5) <> 1 then
    raise Exception.Create('BIFF5 save failed');
end;

لماذا يقول Excel إن كلمة السر خاطئة والمُتحقِّق مطابق؟

يرفض Excel كلمة السر لأنه لا يثق بالمفتاح المخزن: يشتق Excel المفتاح من كلمة السر المكتوبة بـ CreateXorKey_Method1 ويقارنه بكلمة مفتاح FILEPASS، فالملف الذي يكون مفتاحه غير ذلك يرسب فحص كلمة السر حتى لو كان المُتحقِّق صائباً. وتصف المواصفة المفتاح بوصفه ناتجاً عن كلمة السر، لا وسيطاً حراً، ويُلزم Excel 16 بذلك القراءة

كان كاتب HotXLS قبل v2.384.54 يملأ كلمة المفتاح بايتتين عشوائيتين. يبدو ذلك غير مؤذٍ على الورق، فالمُتحقِّق هو فحص كلمة السر الموثق والمصفوفة تُبنى من المفتاح الذي يعلنه الملف أياً كان. وكان HotXLS نفسه يقرأ تلك الملفات بلا عناء، لأن قارئه يأخذ المفتاح من FILEPASS على أنه معطى. وسُلّم Excel 16 الملف نفسه وكلمة السر الصحيحة فأجاب أن كلمة السر غير صحيحة. ومنذ v2.384.54 يُشتق المفتاح، فيحمل FILEPASS دائماً لكلمة السر secret المفتاح $014D والمُتحقِّق $DAA7، قيمتين قورنتا ضربياً بتنفيذ مستقل للمواصفة

مخطط HotXLS لسجل FILEPASS الخاص بتعتيم XOR في BIFF5 الذي يفحصه Excel 16 عند الفتح: الجسم الصريح ذو البايتات الأربع يحمل مفتاح XOR والمُتحقِّق من كلمة السر، ويشتق Excel المفتاح من كلمة السر المكتوبة بـ CreateXorKey_Method1 ويرفض مفتاحاً عشوائياً بخطأ كلمة سر حتى لو طابق المُتحقِّق؛ يخزن HotXLS المفتاح المشتق 014D للكلمة secret
جسم FILEPASS كلمتان فقط، لكن Excel يشتق المفتاح من كلمة السر ثم يقارن؛ والمفتاح المملوء عشوائياً يرسب الفحص حتى مع مُتحقِّق صحيح، ولهذا يشتقه HotXLS منذ v2.384.54

الاشتقاق نفسه قصير متى وضعت الجدولين. تجول على كلمة السر بالعكس، وانظر بتة 6 من كل بايتة سبع مرات مع إزاحتها يساراً، وأثر بـ XOR مدخل XorMatrix واحداً كلما ارتفعت البتة. والتالي رسم مبدئي يعيد خوارزمية المواصفة ويطابق تنفيذ HotXLS؛ وليس واجهة HotXLS:

// رسم مبدئي لـ [MS-OFFCRYPTO] 2.3.7.2 ‏CreateXorKey_Method1
// و CreateXorArray_Method1 ‏(توضيح فقط، وليس واجهة HotXLS)
type
  TXorArray = array [0..15] of Byte;

function DemoCreateXorKey(const Password: AnsiString): Word;
const
  InitialCode: array [0..14] of Word = ($E1F0, $1D0F, $CC9C, $84C0, $110C,
    $0E10, $F1CE, $313E, $1872, $E139, $D40F, $84F9, $280C, $A96A, $4EC3);
  XorMatrix: array [0..104] of Word = (
    $AEFC, $4DD9, $9BB2, $2745, $4E8A, $9D14, $2A09,
    $7B61, $F6C2, $FDA5, $EB6B, $C6F7, $9DCF, $2BBF,
    $4563, $8AC6, $05AD, $0B5A, $16B4, $2D68, $5AD0,
    $0375, $06EA, $0DD4, $1BA8, $3750, $6EA0, $DD40,
    $D849, $A0B3, $5147, $A28E, $553D, $AA7A, $44D5,
    $6F45, $DE8A, $AD35, $4A4B, $9496, $390D, $721A,
    $EB23, $C667, $9CEF, $29FF, $53FE, $A7FC, $5FD9,
    $47D3, $8FA6, $0F6D, $1EDA, $3DB4, $7B68, $F6D0,
    $B861, $60E3, $C1C6, $93AD, $377B, $6EF6, $DDEC,
    $45A0, $8B40, $06A1, $0D42, $1A84, $3508, $6A10,
    $AA51, $4483, $8906, $022D, $045A, $08B4, $1168,
    $76B4, $ED68, $CAF1, $85C3, $1BA7, $374E, $6E9C,
    $3730, $6E60, $DCC0, $A9A1, $4363, $86C6, $1DAD,
    $3331, $6662, $CCC4, $89A9, $0373, $06E6, $0DCC,
    $1021, $2042, $4084, $8108, $1231, $2462, $48C4);
var
  Len, I, Bit, Element: Integer;
  Ch: Byte;
begin
  Result := 0;
  Len := Length(Password);
  if Len > 15 then
    Len := 15;                       // المفتاح لا يرى إلا 15 بايتة
  if Len = 0 then
    Exit;
  Result := InitialCode[Len - 1];
  Element := $68;                    // آخر مدخل في XorMatrix
  for I := Len downto 1 do
  begin
    Ch := Ord(Password[I]);
    for Bit := 1 to 7 do
    begin
      if (Ch and $40) <> 0 then
        Result := Result xor XorMatrix[Element];
      Ch := Byte(Ch shl 1);
      Dec(Element);
    end;
  end;
end;

function XorRor(B, KeyByte: Byte): Byte;
begin
  B := B xor KeyByte;
  Result := Byte((B shr 1) or (B shl 7));   // تدوير يميناً بمقدار بتة واحدة
end;

procedure DemoCreateXorArray(const Password: AnsiString; out Arr: TXorArray);
const
  PadArray: TXorArray = ($BB, $FF, $FF, $BA, $FF, $FF, $B9, $80,
    $00, $BE, $0F, $00, $BF, $0F, $00, $00);
var
  Key: Word;
  Len, I: Integer;
begin
  Key := DemoCreateXorKey(Password);
  Len := Length(Password);
  if Len > 16 then
    Len := 16;
  for I := 0 to Len - 1 do
    Arr[I] := Ord(Password[I + 1]);
  for I := Len to 15 do
    Arr[I] := PadArray[I - Len];
  for I := 0 to 15 do
    if Odd(I) then
      Arr[I] := XorRor(Arr[I], Byte(Key shr 8))
    else
      Arr[I] := XorRor(Arr[I], Byte(Key and $FF));
end;

للكلمة secret ينتج هذا المصفوفة 1F 32 17 B9 14 BA 7B 7F 59 DD 59 7F 7A C0 A6 DF، وهي عينة ثابتة مفيدة إن كنت تختبر قارئك الخاص

مخطط HotXLS لبناء مصفوفة XOR لتعتيم BIFF5: ست عشرة بايتة مزروعة من كلمة السر ووسادة ثابتة تؤثر بـ XOR مع بايتة المفتاح الدنيا في المواضع الزوجية والعليا في المواضع الفردية، ثم تدور يميناً بمقدار بتة واحدة بـ XorRor، فينتج العينة الثابتة 1F 32 17 B9 لكلمة السر secret
بايتات المصفوفة تأتي من كلمة السر والوسادة وبايتتي المفتاح، وتدوير واحد في النهاية؛ وتدوير يسار 2 لم ينجح إلا حين جرى تحويل البايتة بالترتيب المعاكس، و Excel يتبع ترتيب المواصفة

لماذا ينتج المفتاح الصحيح ملفاً تالفاً مع ذلك؟

ينتج المفتاح الصحيح ملفاً تالفاً حين تُدوَّر مصفوفة XOR بالاتجاه الخطأ: تعرّف [MS-OFFCRYPTO] خطوة المصفوفة بوصفها XorRor، تدويراً يميناً بمقدار بتة واحدة، ومصفوفة مدورة يساراً بمقدار اثنين تفك كل جسم سجل إلى ضجيج. وأصلح المفتاح نقل Excel 16 من سؤال كلمة السر إلى خطأ مختلف تماماً، بلاغ بأن للملف مشكلة ولا يمكن فتحه

كان كود HotXLS القديم يدور كل بايتة مصفوفة يساراً بمقدار بتتين، وهي صيغة تتناقلها عدة تنفيذات لـ BIFF. ولأن HotXLS استخدم الدوران نفسه على الجانبين، لم ينتبه قارئه الخاص قط. لم يعد Excel 16 قادراً على حفظ ملفات Excel 5.0/95، ولا يعرض XOR عند حفظ BIFF8، فلم يكن ثمة نموذج Excel أصلي يُقارن به. اضطر الدليل أن يأتي من الاتجاه الآخر: اكتب تدفق BIFF5 نصاً صريحاً واحداً، وأعد ترميزه بثماني صور، ودع Excel 16 يفتح كل نسخة. عبرت الصور الثماني ثلاثة خيارات مستقلة:

الخيارالخيار Aالخيار B
دوران المصفوفة‏XorRor (تدوير يمين 1)تدوير يسار 2
فهرس المصفوفة‏(offset + record length) mod 16‏offset mod 16
ترتيب تحويل البايتةتدوير يسار 5 ثم XOR‏XOR ثم تدوير يسار 5

فتح Excel 16 اثنتين من الثماني بالضبط: ‏XorRor مع تدوير-ثم-XOR وفهرس طول السجل، ونسخة لا تختلف إلا في المظهر. وتدوير-يسار-2 مع XOR-ثم-تدوير والفهرس نفسه هي الدالة نفسها متنكرة. الدوران يتوزع على XOR، فـ rol5(p xor rol2(b)) يساوي rol5(p) xor rol7(b)، وعلى قيمة 8-بت يكون التدوير يساراً بمقدار 7 تدويراً يميناً بمقدار 1. باختصار، ‏rol5 ∘ rol2 = ror1، ولهذا تبدو مصفوفة التدوير-يسار-2 معقولة على انفراد: إنها صائبة فقط مع ترتيب التحويل المعاكس. ومقرونة بترتيب المواصفة تفسد كل بايتة محولة

حسم التجريب نفسه سؤالاً ثانياً. النسخ التي أسقطت طول السجل من الفهرس فشلت كلها، وهو ما أكد قاعدة الفهرس التي تبنّاها HotXLS في إصدار سابق بالاستناد إلى نص المواصفة وحده

كيف يُحسب XorArrayIndex لكل بايتة؟

‏XorArrayIndex لبايتةٍ ما هو إزاحتها في تدفق المصنف زائد طول بيانات السجل الكامل التي تنتمي إليها، محسوبة mod 16. فيبدأ الفهرس من جديد عند قيمة تعتمد على السجل لكل سجل، ويزيد واحداً لكل بايتة داخله. وتسمي الشيفرة الزائفة للمواصفة المدخلات FileOffset و Data.Length، ويسهل سوء قراءتها على أنها إزاحة بداية السجل وحدها، وذلك السوء في القراءة هو بالضبط ما شحنه HotXLS حتى v2.384.47

ثلاثة تفاصيل تحسم مواءمة فهارسك مع Excel:

  • ترويسة السجل ذات البايتات الأربع لا تُحوَّل قط، لكنها تشغل مواضع من التدفق مع ذلك، فأول بايتة جسم في السجل تجلس عند إزاحة الترويسة + 4
  • حد الطول هو طول بيانات السجل الكامل، لا عدد البايتات المحولة فعلاً
  • ‏BOUNDSHEET صريح جزئياً: أول 4 بايتات فيه، lbPlyPos، إزاحة تدفق BOF الورقة، تبقى مقروءة ليستطيع المحلل تحديد مواضع الأوراق. تلك البايتات الأربع تتخطاها عملية التحويل لكنها تحتسب في الإزاحة وطول السجل معاً
مخطط HotXLS لقاعدة XorArrayIndex لتعتيم XOR في BIFF5: كل بايتة جسم تستخدم إزاحة التدفق زائد طول بيانات السجل الكامل mod 16، وترويسة البايتات الأربع الصريحة وسابقة lbPlyPos في BOUNDSHEET تحتسبان في الإزاحة مع ذلك، وإغفال حد طول السجل كان العيب الذي أصلحه HotXLS في v2.384.47
فهرس المصفوفة يعيد البدء مرة لكل سجل لا مرة لكل تدفق: الترويسة وأي سابقة صريحة تشغل مواضع، وطول بيانات السجل يغذي الـ mod، وكلتا نصفَي HotXLS القديم اتفقا على الصيغة الخاطئة

مجتمعةً، التحويل لكل سجل بضعة أسطر. وأكرر، هذا رسم للقاعدة، لا شيء تحتاج لاستدعائه:

function Rol8(B: Byte; N: Integer): Byte;
begin
  Result := Byte((B shl N) or (B shr (8 - N)));
end;

// تعتيم جسم سجل واحد في موضعه. ‏BodyPos هو إزاحة التدفق لـ
// ‏Body[0]، أي إزاحة ترويسة السجل + 4. و PlainPrefix يساوي 4 لـ
// ‏BOUNDSHEET والطول الكامل لـ BOF / FILEPASS و 0 لأغلب السجلات
procedure DemoObfuscateRecord(var Body: array of Byte; RecordLength: Word;
  PlainPrefix: Integer; BodyPos: LongWord; const Arr: TXorArray);
var
  I: Integer;
begin
  for I := PlainPrefix to RecordLength - 1 do
    Body[I] := Rol8(Body[I], 5) xor
      Arr[(BodyPos + LongWord(I) + RecordLength) mod 16];
end;

// القراءة هي الصورة المعكوسة: B := Body[I] xor Arr[...]؛
// ثم تدوير يميناً بمقدار 5، أي Rol8(B, 3)

قبل v2.384.47 كان قارئ HotXLS يحسب الفهرس من موضع التدفق وحده وكان الكاتب يستخدم إزاحة البايتة الصريحة. كلاهما أغفل طول السجل، فاتفق نصفا المكتبة مجدداً مع بعضهما ولا أحد سواهما. وقرأ فاحص شيفرة مستقل ناتج v2.384.47 قراءة صحيحة والناتج الأقدم قراءة خردة، وأكد اختبار الصور الثماني في Excel 16 القاعدة لاحقاً أمام الهدف الحقيقي

ماذا يحدث لملفات XOR التي كتبتها إصدارات HotXLS الأقدم؟

يواصل HotXLS قراءة ملفاته المعتمة بـ XOR السابقة لـ v2.384.54 بفحص مفتاح FILEPASS: حين يساوي المفتاح المخزن المفتاح المشتق من كلمة السر يبني القارئ مصفوفة XorRor المواصفية، وحين يخالفه يعامل الملف ملف HotXLS أقدم ويعيد بناء مصفوفة التدوير-يسار-2. أما الملفات المكتوبة من Excel فتحمل المفتاح المشتق دوماً، فتسلك المسار المواصفي دوماً

الفحص استدلالي بمعدل إخفاق محدد. ملف قديم صدف أن مفتاحه العشوائي ساوى المفتاح المشتق سيقرأ بالمصفوفة الخطأ، واحتمال ذلك 1 من 65,536. والبديل يغطي دوران المصفوفة فقط؛ قاعدة الفهرس لا تُبدَّل، فالملفات التي ينجدها هي المكتوبة بين v2.384.47 و v2.384.53. فإن كنت لا تزال تملك ملفات BIFF5 معتمة بـ XOR من تلك النافذة، افتحها بـ HotXLS الحالي واحفظها من جديد لتحصل على ملف يقبله Excel

تفصيلان لكلمة السر يسريان على كل ملف، قديماً كان أو جديداً:

  • الطول. لا يقرأ CreateXorKey_Method1 إلا أول 15 بايتة من كلمة السر، وهو حد المواصفة. يطبق HotXLS ذلك السقف على المفتاح ويبقي المُتحقِّق والمصفوفة على قاعدتيهما المعتادتين للطول الكامل والـ 16 بايتة، باتساق على الجانبين. ويرفض Excel نفسه كلمات سر أطول من 15 محرفاً لهذه الصيغة، فاعتبار 15 هو الحد الأقصى الحقيقي
  • مجموعة المحارف. يحول HotXLS كلمة السر إلى بايتات عبر صفحة الشيفرة ANSI للنظام. وتصف المواصفة أخذ البايتة الدنيا من كل محرف UTF-16، وهو ما يتوافق مع ASCII. ومن دون نماذج Excel محمية بكلمات سر غير ASCII لا يوجد مرجع حقيقي لما سواها، فالتزم كلمات سر ASCII لملفات XOR

على جانب القراءة تتيح لك TXLSWorkbook.OnPassword سؤال المستخدم عن كلمة سر حين يصطدم Open بسجل FILEPASS. الحدث هو TXLSPasswordEvent بمعاملَي var PassWord: WideString و var Retry: Boolean؛ اضبط Retry على True للمحاولة مجدداً، حتى ثلاث محاولات:

procedure TImportForm.WorkbookPassword(Sender: TObject;
  var PassWord: WideString; var Retry: Boolean);
var
  S: string;
begin
  S := '';
  Retry := InputQuery('Protected workbook', 'Password:', S);
  PassWord := S;
end;

procedure TImportForm.ImportLegacyFile(const FileName: string);
var
  Wb: IXLSWorkbook;
  Rc: Integer;
begin
  Wb := TXLSWorkbook.Create;
  Wb.OnPassword := WorkbookPassword;
  Rc := Wb.Open(FileName);
  // ‏-1003: كلمة سر مطلوبة ولم تزود؛ ‏-1005: كلمة سر خاطئة
  if Rc <> 1 then
    raise Exception.CreateFmt('Cannot open %s (code %d)', [FileName, Rc]);
  ShowMessage(VarToStr(Wb.Sheets[1].Range['A1', 'A1'].Value));
end;

وإن كنت تعرف كلمة السر سلفاً، تخطى Open(FileName, APassWord) الحدث كله

هل تعتيم XOR آمن بما يكفي لأي شيء؟

تعتيم BIFF XOR ليس تشفيراً ولا يحمي شيئاً من قارئ مصمم. فحص كلمة السر مُتحقِّق 16-بت، والمفتاح 16 بتة، ومصفوفة الـ 16 بايتة تتكرر عبر التدفق كله، فمحتويات سجلات BIFF المتوقعة تكشف بايتات المصفوفة دون أي كلمة سر أصلاً. لا يكتب HotXLS ‏XOR إلا لأن ملفات Excel 5.0/95 لا خيار آخر لها، وسبب إنتاج ملفات كهذه اليوم هو مستهلك قديم لا يقرأ شيئاً أحدث

يختار المحرك الكلاسيكي المخطط عبر TXLSWorkbook.EncryptionType، ويفحص التوافق مع صيغة الحفظ بصرامة:

  • ‏xletAuto ‏(الافتراضي) يكتب RC4 CryptoAPI لـ xlExcel97 و XOR لـ xlExcel5، موافقاً ما كتبه Excel نفسه لكل صيغة
  • ‏xletXor صالح لـ BIFF5 وحده؛ ومع xlExcel97 يرفع الحفظ استثناءً بدل التراجع بصمت
  • ‏xletRC4 و xletRC4CryptoAPI لـ BIFF8 وحده، وطلبهما على حفظ BIFF5 يرفع استثناءً كذلك

‏RC4 عتيق هو أيضاً، وتفاصيل مواءمته مغطاة في لماذا يرفض Excel مصنفاً مشفراً بكلمة سر صحيحة. وإن كان المستلم يقرأ XLSX فاستخدم محرك XLSX بدلاً منه: يكتب TXLSXWorkbook.SaveAsEncryptedAgile ‏Agile Encryption ‏(تجزئة كلمة سر SHA-512 بعدد دورات 100,000 و AES-256-CBC)، وهي الصيغة التي يكتبها Excel 2010 وما بعده افتراضياً، بينما يكتب SaveAsEncrypted ‏Standard Encryption الأقدم بـ AES-128. والموازنة بينهما في تشفير ملفات XLSX بـ AES في Delphi، وجانب القراءة مغطى في قراءة ملفات Excel المشفرة بـ Agile مع HotXLS

مرجع سريع: تعتيم BIFF XOR الذي يقبله Excel 16

  • ‏FILEPASS ‏($002F) يلي BOF المتغيرات العامة؛ وجسمه في BIFF5 ‏4 بايتات: المفتاح ثم المُتحقِّق
  • المفتاح = ‏CreateXorKey_Method1(password) وفق [MS-OFFCRYPTO] §2.3.7.2، لا عشوائي قط؛ ولـ secret هو $014D
  • المصفوفة = بايتات كلمة السر + الوسادة، ‏XOR مع بايتة المفتاح الدنيا في المواضع الزوجية والعليا في المواضع الفردية، ثم XorRor ‏(تدوير يمين 1)
  • تشفير بايتة: تدوير يسار 5 ثم XOR؛ وفك التشفير: ‏XOR ثم تدوير يمين 5 ‏(§2.3.7.3)
  • ‏XorArrayIndex = ‏(إزاحة بايتة التدفق + طول بيانات السجل) mod 16؛ والترويسات والسوابق الصريحة تحتسب في الإزاحة
  • يبقي BOUNDSHEET أول 4 بايتات صريحة؛ وتبقى BOF و FILEPASS و INTERFACEHDR صريحة كاملة
  • كلمات السر: ‏ASCII وبخمسة عشر محرفاً على الأكثر
  • ‏HotXLS: أصلح الفهرس في v2.384.47 والمفتاح و XorRor في v2.384.54، وملفات HotXLS القديمة المعتمة بـ XOR تُكشف باختلاف المفتاح
  • للحماية الحقيقية استخدم BIFF8 ‏RC4 CryptoAPI على الأقل، أو XLSX ‏Agile Encryption

يتولى HotXLS حماية كلمات السر في BIFF5 و BIFF8، وتشفير XLSX ‏Standard و Agile، واستدعاء كلمة السر عند القراءة من مكتبة واحدة لـ Delphi و C++Builder، مع تولي تفاصيل التوافق أعلاه عنك. راجع مكوّن HotXLS Delphi للجداول الحسابية للإصدارات والمنصات وتنزيل النسخة التجريبية