مقاله فنی

فهرست‌های مطمئن eIDAS و امضاهای PDF موصوف

تصمیم‌گرفتن اینکه یک امضای PDF تحت eIDAS موصوف است یعنی پاسخ‌دادن به پرسشی که هیچ ربطی به رمزنگاری ندارد: آیا گواهی توسط یک سرویس اعتماد صادر شده که یک کشور عضو به‌عنوان موصوف فهرست کرده، در لحظه‌ای که امضا انجام شد. پاسخ در یک فهرست مطمئن زندگی می‌کند، یک سند XML که به‌ازای هر قلمرو منتشر می‌شود، و کل ارزش آن سند به اصالتش وابسته است. پس مؤلفه PDFium حاضر نیست داخل یکی را نگاه کند تا وقتی کسی برایش ضمانت کرده باشد. TPdfEuropeanTrustedList.ParseAuthenticated بایت‌های خام کامل را پیش از تجزیه حتی یک سرویس به یک IPdfTrustedListAuthenticator تأمین‌شده توسط فراخواننده می‌دهد، و فقط وقتی آن احرازکننده صریحاً قبول کند یک snapshot می‌سازد

جریان احراز-پیش-از-تجزیه برای یک فهرست مطمئن اروپایی در دلفی: XML خام از یک واکشی تازه یا یک snapshot کش‌شده از IPdfTrustedListAuthenticator می‌گذرد پیش از آنکه TPdfEuropeanTrustedList چیزی تجزیه کند
فهرست‌های تازه و کش‌شده به همان احرازکننده می‌رسند، و یک snapshot فقط بعد از قبولی آن وجود دارد

آن ترتیب خودِ طراحی است. همه‌چیز دیگر در این ویژگی از آن پیروی می‌کند، شامل بخش‌هایی که ناخوشایند به‌نظر می‌رسند

تجزیه‌شده یعنی مطمئن نیست

فهرست مطمئنی که تمیز تجزیه می‌شود به شما می‌گوید XML خوش‌فرم است. درباره اینکه چه کسی نوشته‌اش هیچ نمی‌گوید. چون فهرست همان چیزی است که کل تصمیم وضعیت-موصوف شما رویش تکیه دارد، پذیرفتنش به‌خاطر تجزیه‌شدن تصمیم را بی‌معنا می‌کند: مهاجمی که می‌تواند فهرست را جایگزین کند می‌تواند مرجع گواهی خودش را موصوف اعلام کند

همان استدلال روی کش‌کردن هم صدق می‌کند، و این تله‌ای است که ارزش نام‌بردن دارد. حافظه کش snapshot XML اصلی را همراه با یک digest مربوط به SHA-256 ذخیره می‌کند، و به‌آسانی می‌توان یک digest منطبق هنگام بارگذاری را مدرن اصالت فهرست دانست. نیست. یک digest که توسط همان فرایندی که فایل را ذخیره کرد محاسبه شده، بدون دخالت هیچ کلیدی، فقط راستی‌آزمایی می‌کند که بایت‌ها از وقتی نوشتید تغییر نکرده‌اند؛ اگر فهرست هنگام کش‌شدن متقلبانه بود، digest تأیید می‌کند که همان فهرست متقلبانه است. پس بارگذاری یک snapshot کش‌شده از همان احرازکننده‌ای می‌گذرد که تجزیه یک نمونه تازه. یکپارچگی و اصالت دو پراپرتی متفاوت‌اند و فقط یکی از آن‌ها به کلید نیاز دارد

uses
  FPdfTrustedList;

type
  TListAuthenticator = class(TInterfacedObject, IPdfTrustedListAuthenticator)
  public
    function Authenticate(const XmlData: TBytes;
      out AuthenticationDetails: string): Boolean;
  end;

function TListAuthenticator.Authenticate(const XmlData: TBytes;
  out AuthenticationDetails: string): Boolean;
begin
  // خط‌مشی شما اینجا زندگی می‌کند: امضای پوشیده XMLDSIG را در برابر
  // گواهی امضاکننده فهرستی که بیرون از باند پین کرده‌اید راستی‌آزمایی کنید،
  // و توصیف کنید چه را برای رد ممیزی بررسی کردید
  Result := VerifyEnvelopedXmlSignature(XmlData, FPinnedListSigner);
  if Result then
    AuthenticationDetails := 'XMLDSIG verified against pinned LOTL signer';
end;

var
  List: TPdfEuropeanTrustedList;
  Cache: TFileStream;
begin
  List := TPdfEuropeanTrustedList.ParseAuthenticated(RawXml,
    TListAuthenticator.Create, TPdfTrustedListOptions.Default);
  // snapshot فقط به این دلیل وجود دارد که احرازکننده گفت بله
  Cache := TFileStream.Create('tl-de.snapshot', fmCreate);
  try
    List.SaveCache(Cache);
  finally
    Cache.Free;
  end;
end;

اعتبارسنج مالک خط‌مشی شبکه نیست

یک اعتبارسنج PAdES کاری با تصمیم‌گرفتن ندارد که چطور به فهرست فهرست‌های مطمئن برسد، آیا از پروکسی بگذرد، چند وقت یک‌بار تلاش مجدد کند، یا وقتی یک قلمرو در دسترس نیست چه کند. آن‌ها تصمیم‌های برنامه و استقرارند، و در محیط‌های مقرره‌ای اغلب ممیزی می‌شوند. پس به‌روزرسانی‌ها از طریق IPdfTrustedListSource می‌رسند، که یک URI و یک سقف بایتی به آن داده و بایت برمی‌گرداند

آنچه مؤلفه اجرا می‌کند ناورداهایی است که یک به‌روزرسانی را به‌روزرسانی نگه می‌دارند نه جایگزینی. Update می‌طلبد که قلمرو تغییرنکرده باشد، که شماره دنباله اکیداً افزایش یابد، و که زمان صدور به عقب حرکت نکند. آن سه بررسی، آشکارترین حملات تنزل‌دادن را شکست می‌دهند: بازپخش فهرستی قدیمی‌تر که هنوز سرویسی را فهرست می‌کند که از آن پس پس‌گرفته شده، یا جازدن فهرست قلمرو دیگری که سرویس‌هایش هرگز قصد اعتمادشان را نداشتید

ناورداهای به‌روزرسانی که مؤلفه فهرست مطمئن PDFium اجرا می‌کند: قلمرو بدون تغییر، شماره دنباله اکیداً افزایشی و زمان صدوری که هرگز به عقب نمی‌رود، که با هم حملات تنزل‌دادن را می‌بندند
سه بررسی یکنوا یک به‌روزرسانی واقعی را از فهرستی بازپخش‌شده یا جایگزین‌شده جدا می‌کنند

حدود تجزیه‌گر، و اصلاً هیچ DTDای نیست

TPdfTrustedListOptions اندازه XML، تعداد توکن، عمق تودرتو، تعداد سرویس‌ها، تعداد گواهی‌ها و اندازه یک گواهی منفرد را سقف می‌زند، با تابع کلاس Default که مقادیر قابل استفاده فراهم می‌کند. فهرست‌های مطمئن اسناد منتشرشده‌ای با اندازه قابل پیش‌بینی‌اند، پس گذاشتن کران‌ها ارزان است و هیچ فهرست مشروعی نیست که لازم داشته باشد از آن‌ها فراتر رود

جداگانه و بدون قید و شرط، تجزیه‌گر اعلان‌های DTD و entity را رد می‌کند. آن هم انکار سرویس توسعه-entity و هم مسیر افشای entity خارجی را در یک رد می‌بندد، و هیچ هزینه‌ای ندارد چون فهرست‌های مطمئن از entity استفاده نمی‌کنند. هر تجزیه‌گر XMLای که از ورودی نامطمئن قابل‌رسیدن است باید این‌شکل پیکربندی شود؛ تفاوت اینجا این است که رد قابل پیکربندی نیست، پس نمی‌توان با یک تغییر گزینه خیرخواهانه خاموشش کرد

وضعیت موصوف کنار اعتماد زنجیره ثبت می‌شود، نه ادغام در آن

سمت ارزیابی عمداً جداگانه است. TPadesTrustValidationOptions.QualifiedTrustEvaluator یک IPdfQualifiedTrustEvaluator می‌گیرد، که snapshot فهرست مطمئن پیاده‌سازی‌اش می‌کند. حین اعتبارسنجی ارزیاب گواهی برگ، زنجیره و یک زمان اعتبارسنجی می‌گیرد، گواهی‌های سرویس را با مقایسه دقیق DER در برابر امضاکننده و زنجیره تطبیق می‌دهد، وضعیت سرویس، شناسه نوع سرویس و URIهای qualifier را در آن مقطع زمانی ترکیب می‌کند، و یک رکورد ارزیابی برمی‌گرداند

نتیجه روی هر امضا در دو جا فرود می‌آید: QualifiedTrustStatus به‌عنوان یک وضعیت درشت، و QualifiedTrust به‌عنوان ارزیابی کامل با قلمرو، نام ارائه‌دهنده، نام سرویس، شناسه نوع، وضعیت و زمان شروع وضعیت. کاری که نمی‌کند تغییر CertificateTrustStatus است. اعتماد زنجیره سیستمی و وضعیت موصوف به پرسش‌های متفاوتی پاسخ می‌دهند، و گزارشی که آن‌ها را فرومی‌ریزد نمی‌تواند «مطمئن ولی موصوف نیست» را از «موصوف ولی زنجیره اعتبارسنجی نمی‌شود» تمیز دهد، که هر دو واقعی‌اند و هر دو به برخورد متفاوت نیاز دارند

ارزیابی اعتماد موصوف PAdES در دلفی: IPdfQualifiedTrustEvaluator گواهی‌های سرویس را با مقایسه دقیق DER تطبیق و QualifiedTrustStatus و QualifiedTrust را پر می‌کند در حالی که CertificateTrustStatus دست‌نخورده می‌ماند
اعتماد زنجیره و وضعیت موصوف eIDAS کنار هم ثبت می‌شوند تا هر دو یافته مرئی بمانند
var
  Options: TPadesTrustValidationOptions;
  Report: TPadesValidationResult;
  I: Integer;
begin
  Options := TPadesTrustValidationOptions.Default;
  Options.CheckRevocation := True;
  Options.QualifiedTrustEvaluator := List;      // snapshot احرازشده
  Options.QualifiedValidationTime := SigningTime; // نه Now
  Report := Pdf.ValidatePadesTrust(Options);

  for I := 0 to High(Report.Signatures) do
    if Report.Signatures[I].QualifiedTrustStatus = pcsValid then
      Writeln(Format('signature %d qualified by %s / %s (%s)',
        [I, Report.Signatures[I].QualifiedTrust.Territory,
         Report.Signatures[I].QualifiedTrust.ProviderName,
         Report.Signatures[I].QualifiedTrust.ServiceName]))
    else if Report.Signatures[I].QualifiedTrustStatus = pcsIndeterminate then
      // بدون سرویس منطبق، یا snapshot نمی‌تواند برای این زمان پاسخ دهد
      Writeln(Format('signature %d: qualified status undetermined', [I]));
end;

چرا زمان اعتبارسنجی همین حالا نیست

چون موصوف‌بودن یک پراپرتیِ یک لحظه است. یک سرویس اعتماد می‌تواند وضعیت موصوف بگیرد، بعداً پس گرفته شود، و بعدتر از آن دوباره برقرار شود، و هر یک از آن گذرها یک زمان شروع در فهرست حمل می‌کند. امضایی که هنگام موصوف‌بودن سرویس انجام شده بعدش موصوف می‌ماند؛ امضایی که پیش از اعطا انجام شده به‌طور گذشته‌نگر موصوف نمی‌شود. پس ارزیابی در برابر زمان جاری در هر دو جهت پاسخ غلط می‌دهد

فهرست آنچه برای این لازم است را حمل می‌کند: هر رکورد سرویس یک زمان شروع وضعیت و یک پرچم که entryهای تاریخی را از جاری‌ها تفکیک می‌کند دارد، و ارزیاب آن‌ها را در برابر زمانی که شما تأمین می‌کنید ترکیب می‌کند. در عمل آن زمان از یک مهر زمانی مطمئن روی امضا می‌آید نه از زمان امضای ادعاشده در CMS، که دلیل این است که مواد اعتبارسنجی بلندمدت حتی برای پرسشی که شبیه یک جست‌وجوی خط‌مشی است اهمیت دارد؛ سمت مهر زمانی و DSS در مقاله امضای بلندمدت پوشش داده شده است

چه چیزهایی هنوز باید بسازید

سه چیز، و هیچ‌کدام جایشان در یک کتابخانه PDF نیست. احرازکننده، یعنی راستی‌آزمایی واقعی XMLDSIG در برابر گواهی امضاکننده فهرستی که از طریق مجرایی که به آن اعتماد دارید گرفته‌اید. خط‌مشی واکشی، یعنی چطور و چقدر اغلب تازه می‌کنید، و برنامه شما وقتی یک تازه‌سازی شکست می‌خورد چه می‌کند. و دامنه سرزمینی، یعنی اصلاً کدام فهرست‌ها را حمل می‌کنید، که یک تصمیم تجاری درباره اینکه طرف‌های حساب شما در کدام کشورهای عضو امضا می‌کنند است

آنچه از مؤلفه می‌گیرید بخشی است که به‌آسانی می‌توان به‌شکل ظریف غلطش گرفت: ترتیب احراز-پیش-از-تجزیه، تجزیه XML کران‌دار و عاری از entity، ناورداهای به‌روزرسانی یکنوا، تطبیق سرویس با DER دقیق، ارزیابی وضعیت تاریخی، و نتیجه‌ای که از اعتماد زنجیره عادی جدا می‌ماند. اگر مشکل فوری شما بنیادی‌تر است، اینکه اعتبارسنج امضایی را که فکر می‌کنید سالم است رد می‌کند، علت‌های معمول در چرا اعتبارسنج‌ها امضاهای PAdES را رد می‌کنند فهرست شده، و سطح بازرسی امضا در بازرسی امضاها و سطوح PAdES توصیف شده است. قابلیت‌های مؤلفه در صفحه محصول PDFium Delphi component فهرست شده است