لجعل التحقق من ملف PDF موقع صالحاً بعد سنوات من الآن، بعد انتهاء صلاحية شهادة التوقيع وتدوير المرجع المصدق (CA) الخاص بها، يمكن لمكون PDFium إنتاج تواقيع PAdES طويلة الأجل على نظام ويندوز: طابع زمني RFC 3161 للوقت الموثوق به، ومخزن أمان مستند (Document Security Store) يضمن مواد التحقق، وطابع زمني لأرشيف المستند (DocTimeStamp) فوق الملف بأكمله. هذه الإضافات الثلاث هي مستويات PAdES B-T و B-LT و B-LTA الأساسية، ويصل مكون PDFium إليها جميعاً من استدعاء توقيع واحد. هذه قدرة مخصصة لويندوز فقط، وتعتمد على PadesCryptoAvailable
هذا المقال هو الثالث في السلسلة. يغطي المقال الأول، توقيع ملفات PDF باستخدام PAdES B-B بواسطة PDFium VCL، التوقيع الأساسي؛ ويغطي المقال الثاني، فحص تواقيع PDF الرقمية ومستويات PAdES، قراءة التوقيع وتحديد المستوى الذي وصل إليه. ينصب الاهتمام هنا على الأرشيف: التواقيع التي يجب أن تنجو من انتهاء صلاحية الشهادة وتظل قابلة للتحقق لفترة احتفاظ تقاس بالسنوات، وليس بالأسابيع
لماذا يتوقف التحقق من توقيع PDF صالح بمرور الوقت؟
يجيب التوقيع الأساسي عن سؤال واحد فقط: هل تم تغيير هذه البايتات بعد التوقيع. وهو لا يثبت بمفرده متى حدث التوقيع، وتلك الفجوة هي ما تكسره لاحقاً. تحمل بنية CMS سمة وقت التوقيع، ولكن الموقع يكتب هذه القيمة من ساعته الخاصة، لذا ليس لدى المدقق سبب للثوق بها. وعندما تنتهي صلاحية شهادة التوقيع لاحقاً أو يلغيها المرجع المصدق، لا يعود بإمكان المدقق الصارم التمييز بين توقيع تم إجراؤه أثناء صلاحية الشهادة وتوقيع تم تزويره بعد زوالها. كان التوقيع جيداً يوم إنشائه ويصبح غير قابل للتحقق دون أي خطأ منه
يصلح الأرشفة طويلة الأجل هذا في خطوتين. أولاً، تؤكد جهة خارجية موثوقة، وهي سلطة الطوابع الزمنية (Time Stamping Authority)، الوقت تشفيراً بحيث لا يعود يعتمد على أمانة الموقع. ثانياً، يتم تضمين كل شهادة، واستجابة إلغاء، وقائمة CRL مطلوبة لبناء سلسلة الثقة وفحصها داخل ملف PDF نفسه، وبالتالي لا يعتمد التحقق على خوادم قد تزول بحلول الوقت الذي يبحث فيه شخص ما. يصنف معيار PAdES، المعتمد كـ ETSI EN 319 142-1، هذه كالمستويات الأساسية، ويكتب مكون PDFium الهياكل التي يتطلبها كل مستوى
ما هو توقيع PDF بطابع زمني للأرشيف أو LTV؟
يحدد PAdES أربعة مستويات أساسية تبنى على بعضها البعض، ويعرضها مكون PDFium من خلال التعداد TPadesLevel (وهي plB_B و plB_T و plB_LT و plB_LTA). التوقيع B-B هو التوقيع البسيط. ويضيف B-T طابعاً زمنياً موثوقاً فوق قيمة التوقيع. ويضيف B-LT (طويل الأجل) مواد التحقق المضمنة، وهي الخاصية التي يقصدها معظم الناس بـ "LTV". بينما يغلف B-LTA (طويل الأجل مع طابع زمني للأرشيف) كل شيء في طابع زمني آخر يغطي الملف بأكمله، وبالتالي تكون المواد المضمنة نفسها سليمة بشكل مثبت من لحظة الأرشفة
القراءة العملية هي بمثابة درج. يثبت B-T متى. ويثبت B-LT بماذا يمكن الاستمرار في فحص التوقيع. ويثبت B-LTA أن الحزمة بأكملها لم يتم العبث بها منذ ختمها، وهو المستوى الذي تجدده، عن طريق إضافة طابع DocTimeStamp جديد قبل انتهاء صلاحية السابق، لتمديد الأرشيف إلى ما لا نهاية. بالنسبة لعقد أو سجل امتثال ذي التزام طويل بالاحتفاظ، فإن B-LTA هو الهدف؛ وتعد B-LT هي الحد الأدنى العملي
إضافة وقت موثوق: PAdES B-T مع RFC 3161
يحول مكون PDFium توقيع B-B إلى B-T عن طريق تعيين حقلين في TPadesSignOptions: رفع Level إلى plB_T وتقديم TsaUrl. وعندما يكون كلاهما موجوداً، يقوم خط أنابيب التوقيع بتجزئة ثمانيات التوقيع الخام باستخدام SHA-256، وتغليف هذه الخلاصة كرسالة RFC 3161 messageImprint، وإرسال الطلب (POST) إلى TSA عبر WinHttp، وتضمين الرمز المرتجع كسمة غير موقعة للطابع الزمني للتوقيع (OID 1.2.840.113549.1.9.16.2.14) في unsignedAttrs [1] لـ SignerInfo، وفقاً لمعيار EN 319 142-1 الفقرة 6.3. يغطي الطابع الزمني قيمة التوقيع على وجه التحديد، وهو ما يربط الوقت الموثوق به بهذا التوقيع الدقيق
uses
PDFium, FPdfPades;
procedure SignWithTimestamp;
var
Pdf: TPdf;
Options: TPadesSignOptions;
begin
Pdf := TPdf.Create(nil);
try
if not Pdf.PadesCryptoAvailable then
raise Exception.Create('PAdES signing backend is Windows-only');
Pdf.FileName := 'contract.pdf';
Pdf.Active := True;
Options := TPadesSignOptions.Default;
Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
Options.Level := plB_T;
Options.TsaUrl := 'http://timestamp.example-tsa.com/tsr';
Options.Reason := 'Contract execution';
// Nonce left at 0: the component derives a unique anti-replay value.
Pdf.SignPades('contract-bt.pdf', Options);
finally
Pdf.Free;
end;
end;
بصمة الشهادة (CertificateThumbprint) هي تجزئة SHA-1، بالنظام السداسي عشري، لشهادة في مخزن المستخدم الحالي "MY" والتي يمكنك استخدام مفتاحها الخاص. وحقل Nonce هو قيمة مضادة لإعادة التشغيل لمعيار RFC 3161؛ اتركه صفراً ويشتق المكون قيمة فريدة لكل طلب من طية SHA-256 لعداد، وساعة، وعدد التكات، ومعرف العملية، بحيث لا يتصادم طلبان يتم إصدارهما في نفس الميلي ثانية. لا تمرر قيمتك الخاصة إلا عندما يكون لديك RNG تشفيري تفضل الثقة به. تحذير صادق واحد: يتطلب B-T سلطة TSA قابلة للوصول، لذا فإن التوقيع الآن يجري مكالمة شبكة ويرث توفر TSA وزمن الوصول الخاص بها
تضمين مواد التحقق: B-LT و B-LTA في استدعاء واحد
الخطوة نحو التحقق طويل الأجل هي تغيير واحد: اضبط Level على plB_LTA واحتفظ بـ TsaUrl. ثم يقوم مكون PDFium بتشغيل الدرج بأكمله داخل استدعاء SignPades واحد. فهو يوقع B-B، ويضع الطوابع الزمنية لـ B-T، ويحقن مخزن أمان المستند لـ B-LT، ويلحق الطابع الزمني للأرشيف لـ B-LTA، كل منها كتحديث متزايد خاص به بحيث تظل البايتات السابقة سليمة بايت ببايت
procedure SignForArchive;
var
Pdf: TPdf;
Options: TPadesSignOptions;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'contract.pdf';
Pdf.Active := True;
Options := TPadesSignOptions.Default;
Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
Options.Level := plB_LTA; // drives B-B -> B-T -> B-LT -> B-LTA
Options.TsaUrl := 'http://timestamp.example-tsa.com/tsr';
Options.Location := 'Head Office';
// One call writes the timestamp, the DSS and the archive DocTimeStamp.
Pdf.SignPades('contract-lta.pdf', Options);
finally
Pdf.Free;
end;
end;
لمرحلة B-LT، يبني مكون PDFium سلسلة الشهادات باستخدام CertGetCertificateChain ويكتب قاموس /DSS يحمل شهادة الموقع بالإضافة إلى كل مرجع مصدق وسيط في مصفوفة /Certs (مع مصفوفتي /OCSPs و /CRLs متوازيتين)، جنباً إلى جنب مع علامة /Extensions /ESIC في المستوى 1، تماماً كما تفرض الفقرة 5.4.2 من معيار EN 319 142-1. يتم حذف الجذر الموقع ذاتياً عمداً، نظراً لأن الفقرة 10.2.3 من RFC 5652 تسمح بذلك والجذر هو بالفعل مرساة ثقة يمتلكها المدقق. والنتيجة هي توقيع يمكن للقارئ التحقق منه دون وجود شيء سوى الملف في يده
بالنسبة لـ B-LTA، يلحق المكون طابعاً زمنياً للمستند: وهو قاموس توقيع مع /SubFilter /ETSI.RFC3161 يغطي /ByteRange الخاص به الملف بأكمله، وتحمل /Contents الخاصة به رمز RFC 3161 فوق هذا النطاق، ويرقي علامة ESIC إلى المستوى 2. هذه هي خطوة الأرشفة وفقاً للفقرة 5.4.3 ومعيار TS 119 142-3. ونظراً لأن DocTimeStamp يغطي DSS بالإضافة إلى التوقيع، فإنه يثبت أن مواد التحقق المضمنة كانت موجودة وغير معدلة في وقت الأرشفة، وهو بالضبط ما يجب أن تكون سياسة الاحتفاظ الطويلة قادرة على إظهاره
توسيع توقيع موجود بالفعل
في بعض الأحيان يكون التوقيع موجوداً بالفعل في المستند ولا تحتاج إلا إلى إضافة أو تحديث مخزن التحقق، على سبيل المثال لرفع توقيع B-B لطرف ثالث إلى B-LT لأرشيفك. يعرض مكون PDFium حاقن DSS مباشرة من خلال SaveAsPadesDss، والذي يلحق هياكل /DSS و /Extensions كتحديث متزايد دون لمس بايتات التوقيع الحالية
procedure AddValidationStore;
var
Pdf: TPdf;
DssOpts: TPadesDssOptions;
Cert: TPadesDssMaterial;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'already-signed.pdf';
Pdf.Active := True;
DssOpts := TPadesDssOptions.Default;
DssOpts.EsicExtensionLevel := 1; // 1 for B-LT, 2 for B-LTA
Cert.DerBytes := LoadSignerCertDer; // your DER-encoded certificate
SetLength(DssOpts.Certs, 1);
DssOpts.Certs[0] := Cert;
Pdf.SaveAsPadesDss('already-signed-lt.pdf', DssOpts);
finally
Pdf.Free;
end;
end;
أنت تقدم الشهادات المشفرة بـ DER، واختيارياً استجابات OCSP وقوائم CRL، التي سيحتاجها المدقق. اضبط EsicExtensionLevel على 1 لمخزن B-LT أو 2 عندما يتبع ذلك طابع DocTimeStamp. اترك IncludeVri عند قيمته الافتراضية False: فالفقرة 5.4.2.3 من معيار EN 319 142-1 تعامل قاموس /VRI الخاص بكل توقيع كأمر اختياري وتنصح بعدم استخدامه ما لم يتطلبه قارئ محدد تستهدفه
التكاليف والحدود التي تستحق التخطيط لها
تشكل ثلاثة حدود صادقة المكان الذي تناسبه هذه المستويات. أولاً، الخلفية التشفيرية مخصصة لويندوز فقط: حيث يمر التوقيع والطوابع الزمنية عبر مخازن CNG و WinHttp للنظام الأساسي، لذا تعيد PadesCryptoAvailable القيمة False في مكان آخر وتثير SignPades استثناءً. يظل فحص جانب القراءة المغطى في المقال المصاحب متعدد الأنظمة الأساسية؛ فقط كتابة التواقيع هي المقيدة بويندوز. ثانياً، يعتمد كل من B-T و B-LTA على سلطة طوابع زمنية (TSA)، مما يعني رحلة ذهاب وإياب عبر الشبكة في وقت التوقيع وخدمة خارجية يصبح وقت تشغيلها وحدود معدلها جزءاً من مسار التوقيع الخاص بك
ثالثاً، كل مستوى يكلف مساحة تخزين. تضيف كل مرحلة تحديثاً متزايداً بدلاً من إعادة كتابة الملف، ويقوم DSS بتضمين سلسلة شهادات كاملة، ويحجز طابع أرشيف DocTimeStamp مساحة لرمزه، لذا فإن ملف B-LTA أكبر بكثير من ملف B-B الأصلي. هذه هي المقايضة المتعمدة: أنت تنفق البايتات الآن لتشتري إمكانية التحقق لاحقاً. بالنسبة لمعظم أرشيفات العقود والامتثال، فهي المقايضة الصحيحة، ولكن الأمر يستحق القياس على مستنداتك الخاصة بدلاً من الافتراض. وعندما تحتاج إلى تأكيد وصول ملف منتهٍ بالفعل إلى المستوى الذي قصدته، تحقق منه باستخدام التقنيات الواردة في فحص تواقيع PDF الرقمية ومستويات PAdES، وإذا كنت تقوم بتقوية خط أنابيب المستندات بشكل أوسع، فإن الملاحظات حول تدقيق مخاطر أمان PDF تغطي الفحوصات المحيطة
إن ميزات توقيع PAdES وحقن DSS وطابع الأرشيف الزمني المعروضة هنا هي جزء من مكون PDFium لـ Delphi و C++Builder، الذي تحمل صفحة منتجه مرجع التوقيع الكامل ومتطلبات النظام الأساسي