علامة إذن (permission flag) PDF ليست قفلاً. إنها طلب يقدمه الملف لأي شيء يفتحه، وللعارض حرية تجاهله. هذه الحقيقة الوحيدة تقرر كيف يجب أن تفكر في كل خيار آخر في هذه الصفحة. السرية الحقيقية تأتي من مكان واحد فقط: تشفير AES-256 يتم ربط مفتاحه بكلمة مرور لا يمتلكها القارئ. كل شيء آخر، مربعات اختيار "عدم الطباعة" و "عدم النسخ"، هي سياسة يوافق البرنامج المطابق (conforming software) على احترامها بينما البرامج المعادية لا تفعل ذلك. اخلط بين هاتين الطبقتين وستقوم بشحن شيء يبدو آمناً في العرض التوضيحي ولكنه يسرب في الميدان
HotPDF هو مكون VCL PDF أصلي لـ Delphi و C++Builder، وهو يعرض نموذج حماية ISO 32000 من خلال مجموعة صغيرة من الخصائص. من السهل تعيين الخصائص. الجزء الصعب هو معرفة أيهما يشتري لك حماية التشفير وأيهما يشتري لك اقتراحاً مهذباً، وتصحيح ترتيب التعيين بحيث يكون التشفير الذي طلبته هو التشفير الذي تحصل عليه بالفعل
ما تعد به حقاً كلمتا المرور
يحدد تشفير PDF بياناتي اعتماد (credentials) بوظيفتين مختلفتين، والخلط بينهما هو خطأ التصميم الأكثر شيوعاً في كود الإخراج المحمي. كلمة مرور المستخدم (user password) تحرس فك التشفير. بدونها، أو بدون كلمة مرور المالك، لا يمكن لقارئ مطابق إعادة بناء مفتاح الملف ويبقى المحتوى غير قابل للقراءة من ناحية التشفير. تحرس كلمة مرور المالك (owner password) إعدادات الأذونات بدلاً من ذلك: يتم منح القارئ الذي يتلقى كلمة مرور المالك وصولاً كاملاً بغض النظر عما تقوله علامات التقييد
تجلس بتات الإذن (permission bits) على أرضية أضعف. الطباعة، واستخراج المحتوى، وتعبئة النموذج: كل منها عبارة عن علامة يقرأها العارض ويختار احترامها (ISO 32000-2 §7.6.4). التشفير يحمي البايتات. علامات الأذونات توجه فقط البرامج المطابقة، وتوجهها بعد فوات الأوان. أي شخص يفتح المستند بكلمة مرور المستخدم يحمل بالفعل المحتوى الذي تم فك تشفيره في الذاكرة، لذا فإن "عدم النسخ" و "عدم الطباعة" تعني شيئاً لعارض حسن السلوك ولا شيء لعارض مصمم. ابنِ نموذج التهديد (threat model) حول هذا الخط. السرية تعيش في كلمة مرور المستخدم. تشكل الأذونات ما يقدمه العارضون الرئيسيون، وهذا كل ما يفعلونه
ترتيب التكوين: كل شيء قبل BeginDoc
يقوم HotPDF ببناء قاموس التشفير ويستمد مفتاح الملف في اللحظة التي يتم فيها تشغيل BeginDoc. مهما كانت خصائص الحماية التي يحملها في تلك اللحظة هي ما يحصل عليه المستند، وتغييرها بعد ذلك لا يغير شيئاً. الخاصية الأكثر أهمية هنا هي CryptKeyLength، والتي تختار المخطط (scheme) من قيم THPDFKeyType: k40 و k128 و aes128 و aes256. قم بتعيينها بعد BeginDoc ولن تحصل على أي استثناء، ولا أي تحذير، مجرد ملف احتفظ بهدوء بما بدأ به. هذا النوع من التباعد الصامت (silent divergence) هو أسوأ نوع: فهو يمرر كل اختبار محلي ويظهر بعد أشهر كنتيجة مطابقة على مكتب العميل
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'statement.pdf';
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256; // must be set before BeginDoc
Pdf.UserPassword := 'open-secret';
Pdf.OwnerPassword := 'admin-secret';
Pdf.UseAES256R6 := False; // R=5: widest viewer support
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 720, 0, 'Account statement, June 2026');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
كلمات المرور هي UTF-8 ويبلغ حدها الأقصى 127 بايت، وهو حد ISO 32000-2 لمخططات AES-256. إذا كانت سياسة كلمة المرور الخاصة بك تسلمك أسراراً أطول، فقم بالاقتطاع (truncation) بنفسك، من جانبك، حيث تتحكم بالضبط في مكان القطع. اتركه للصدفة ويمكن أن تختلف المكتبة وعارض مستقبلي حول القطع، مما ينتج ملفاً يفتح لك ويرفض نفس كلمة المرور في مكان آخر
المراجعة 5 أو المراجعة 6 (Revision 5 or revision 6): منطقي (boolean) واحد، نظامان بيئيان
يختار UseAES256R6 بين مصافحتي (handshakes) AES-256، والنتيجة أكثر أهمية مما يوحي به النوع المنطقي (boolean). اتركه False وسيكتب HotPDF المراجعة 5، مخطط AES-256 الذي وصل كملحق لـ PDF 1.7 والذي يمكن لحوالي خمسة عشر عاماً من العارضين فتحه. قم بتعيينه إلى True وستحصل على المراجعة 6، وهو اشتقاق المفتاح المقسى (hardened key derivation) الموحد في ISO 32000-2 لـ PDF 2.0، والذي يغلق نقطة ضعف معروفة في كيفية تحقق المراجعة 5 من كلمة المرور
لذلك تعتبر المراجعة 6 هي القصة الأفضل من الناحية التشفيرية. إنها أيضاً التي تكسر الأشياء. يحتاج ملف المراجعة 6 إلى عارض مبني لـ PDF 1.7 Extension Level 3 أو PDF 2.0، والكثير من البرامج المنشورة ليست أياً منهما: أرشيفات إدارة السجلات، وأدوات العرض المضمنة في منتجات أخرى، وأدوات خط الأعمال (line-of-business tools) التي لم يلمسها أحد منذ سنوات. سترفض هذه الملف تماماً، وسيفعلون ذلك على جهاز العميل، وليس على جهازك أبداً. الإعداد الافتراضي العملي هو بالتالي المراجعة 5. لا تصل إلى المراجعة 6 إلا عندما تسمي سياسة الأمان ISO 32000-2 بالمراجعة، وعندما تؤكد بالفعل أن كل مستهلك يمكنه قراءته. في كلتا الحالتين، اكتب أي واحد اخترته ولماذا، لأن الشخص التالي الذي يلمس هذا الكود سيتساءل
تستحق أنواع المفاتيح القديمة جملة حتى تعرف أن تتخطاها. لا يزال THPDFKeyType يسرد k40 و k128 و aes128، لكنها موجودة لإعادة إنتاج الأرشيفات التاريخية، وليس لحماية الأرشيفات الجديدة. يقع RC4 بتشفير 40 بت فريسة للأجهزة السلعية (commodity hardware)، والمخططات 128 بت تسبق مراجعات AES-256 التي سيتوقعها أي تقييم أمني حالي. بالنسبة للمستند الذي تقوم بإنشائه في عام 2026، فإن السؤال الحقيقي هو فقط المراجعة 5 مقابل المراجعة 6؛ إذا وجدت نفسك تصل إلى الأنواع القديمة في تصميم جديد، فهناك شيء ما في المراحل الأولى (upstream) قد سار بشكل خاطئ
علامات الأذونات بدون كلمة مرور للفتح
غالباً ما يكون المطلب هو عكس السرية. يجب أن يكون أي شخص قادراً على قراءة المستند، ولكن يقصد بالطباعة أو الاستخراج أن يكونا محدودين. أنت تعبر عن ذلك بكلمة مرور مستخدم فارغة وكلمة مرور مالك غير فارغة، والتي يطلق عليها PDF اسم وضع كلمة المرور المفتوحة (open-password mode)، وتقوم بإدراج العمليات التي ترغب في السماح بها في ProtectOptions
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.UserPassword := ''; // anyone can open the file
Pdf.OwnerPassword := 'rotate-me-quarterly'; // guards the permission set
Pdf.ProtectOptions := [prPrint, prPrint12bit, prExtractContent];
Pdf.BeginDoc;
// ... page content ...
Pdf.EndDoc;
ترسم مجموعة THPDFProtectOptions على بتات أذونات ISO: خصائص prPrint و prPrint12bit للطباعة عالية الدقة، و prInformationCopy للنسخ والاستخراج العام، و prExtractContent لاستخراج التكنولوجيا المساعدة، بالإضافة إلى prModifyStructure و prEditAnnotations و prFillAnnotations و prAssemble. اثنان منها يستحقان التحذير. اترك prExtractContent قيد التشغيل في كل ملف تعريف (profile) تبنيه تقريباً. إنها البت التي يحتاجها قارئ الشاشة للوصول إلى النص، وإزالتها بهدوء تحول قرار الحقوق إلى عيب في إمكانية الوصول (accessibility defect) يصيبه شخص من ذوي الإعاقة ولا تراه أنت أبداً. الفخ الآخر هو prPrint بمفرده، بدون prPrint12bit: يستجيب العديد من العارضين عن طريق خفض جودة الطباعة، وسيقوم المستخدمون بتقديم ذلك على أنه خطأ عرض (rendering bug) بدلاً من إعداد الإذن الذي هو عليه في الواقع
يستغرق التحقق خمس دقائق وينتمي إلى قائمة التحقق من الإصدار (release checklist) الخاصة بك. افتح عينة من كل ملف تعريف في Acrobat، وافتح خصائص المستند (Document Properties)، واقرأ علامة تبويب الأمان (Security)، التي توضح الخوارزمية ("AES 256-bit") وتسرد العمليات المسموح بها واحدة تلو الأخرى. ثم افتح نفس الملف في أقدم عارض يقوم عملاؤك بتشغيله بالفعل، وليس الأحدث على جهازك. هذا الفتح الثاني هو التأمين الرخيص ضد إبحار ملف المراجعة 6 عبر التطوير وموته عند عميل لم يقم بالترقية أبداً
إزالة الحماية من الملفات الموجودة
يعمل فك التشفير على نفس نموذج الخاصية بشكل عكسي. قم بتحميل المستند ببيانات اعتماد صالحة، وقم بإيقاف تشغيل الحماية، واحفظ النتيجة بدونه
var
Pdf: THotPDF;
PageCount: Integer;
begin
Pdf := THotPDF.Create(nil);
try
PageCount := Pdf.LoadFromFile('encrypted.pdf', 'open-secret');
if PageCount > 0 then
begin
Pdf.ActivateProtection := False; // drop encryption on save
Pdf.SaveLoadedDocument('plain.pdf');
end;
finally
Pdf.Free;
end;
end;
يحلل هذا المسار المستند بأكمله في الذاكرة، وهو أمر جيد للملفات العادية ومسرف للملفات الضخمة. عندما يصل الإدخال إلى مئات الميجابايت، فإن DecryptFile هو الخيار الأرخص: فهو يفك التشفير أثناء النسخ على مستوى الملف، ويأخذ مسار إعادة كتابة مباشر لـ AES-256 يتخطى بناء شجرة الكائنات الكاملة (object tree) كلما سمح الإدخال بذلك. إنه جزء من Direct File API المغطى في المقال المرافق حول معالجة ملفات PDF الكبيرة من Delphi
القيود التي تتفاعل مع التشفير
حدان يستحقان المعرفة قبل التصميم حول التشفير بدلاً من بعده. الأول هو مطابقة الأرشيف (archival conformance). يحظر ISO 19005 التشفير في PDF/A، لذلك فإن أي سير عمل يشفر مستنداً ويطالب أيضاً بـ مطابقة PDF/A هو متناقض من حيث البناء؛ لن يسمح لك HotPDF بوجود كليهما في ملف واحد. عندما تحتاج حقاً إلى كليهما، فإن الإجابة هي اثنان من القطع الأثرية (artifacts): نسخة مشفرة للتوزيع ونسخة غير مشفرة منفصلة للأرشيف
الحد الثاني أكثر صرامة. تشفير PDF ليس له ضمان (escrow) ولا استرداد. افقد كلمة مرور المستخدم في ملف R5 أو R6 وستكون خياراتك هي القوة الغاشمة (brute force) أو الاستسلام. لذا تعامل مع أسرار المالك والمستخدم بالطريقة التي تتعامل بها مع أي بيانات اعتماد إنتاج. قم بتوليدها، وتخزينها في قبو، وتدويرها وفقاً لجدول زمني. الشيء الوحيد الذي يجب ألا تفعله أبداً هو ترميزها (hard-code) كثوابت في وحدة، حيث تنتقل مباشرة إلى التحكم في الإصدار (version control) وتجلس في نسخة عمل كل مطور إلى الأبد
رد فعل أخير يستحق البناء. تغيير الحماية في ملف لم تقم بإنشائه هو نفس آلية فك التشفير، وليس ميزة منفصلة: قم بتحميله بكلمة المرور الخاصة به من خلال LoadFromFile، وقم بتحرير ProtectOptions أو كلمات المرور في مكانها، واكتبه مرة أخرى باستخدام SaveLoadedDocument. إذا كان بإمكانك فك تشفير ملف، فيمكنك إعادة منحه الإذن (re-permission it)، ويبدو الكود مطابقاً تقريباً للمثال أعلاه
خصائص الحماية الموضحة هنا هي جزء من مكون HotPDF القياسي لـ Delphi و C++Builder؛ تحمل صفحة المنتج مرجع التشفير الكامل، بما في ذلك التعداد الكامل للأذونات (permission enumeration)