تخطَّ إلى المحتوى

الأمان: التشفير وسياسة التعمية وسطح التوقيع

تطبّق وحدة أمان ⁨Core⁩ تشفير المستندات بمعيار التشفير المتقدم بطول 256 بت (⁨AES-256⁩)، وتوجّه كل اختيار خوارزمية عبر عقد سياسة تعمية، وتتيح نقاط تكامل مع خدمة إدارة مفاتيح تديرها بيئة النشر. تعتمد الحماية الفعلية للمستند على التعامل مع المفاتيح وقوة كلمة المرور والقارئ المستهلِك وبيئة النشر. توضّح هذه الصفحة تلك الحدود صراحة.

Terminal window
composer require nextpdf/core:^3

تتكوّن وحدة الأمان من ثلاثة أسطح. يستخدم سطح التشفير نقطة دخول المستند setEncryption() لتهيئة معالج الأمان القياسي ⁨AES-256.⁩ وتستخدم بوابة سياسة التعمية CryptoPolicyInterface لتحديد دوال التجزئة والتواقيع والشيفرات وقوة المفاتيح التي تسمح بها بيئة النشر. يُشار إلى سطح التوقيع هنا، لكنه موثَّق على حدة؛ راجع التوقيع.

يستخدم التشفير ⁨AES-256⁩ كما هو معرَّف في ⁨ISO 32000-2⁩:2020 §7.6. المسار الافتراضي هو معالج الأمان القياسي ⁨V⁩=5 / ⁨R⁩=6 مع مرشّح التعمية ⁨AESV3.⁩ يبلغ طول مفتاح الملف 32 بايت (256 بت)، وهو ما يطابق معايير معالجة المعلومات الفيدرالية (⁨FIPS⁩) 197. يضيف مسار اختياري التشفير المُصادَق ⁨ISO/TS 32003⁩:2023 ⁨V⁩=6 / ⁨R⁩=7 بمعيار ⁨AES-256⁩ في نمط ⁨Galois/Counter⁩‏ (⁨AES-256-GCM⁩). توثّق الصفحة المعمّقة كلا المسارين: التشفير.

تعمل بوابة سياسة التعمية كنقطة قرار للرفض أو السماح. يستشير ⁨Core⁩ CryptoPolicyInterface قبل أي خطوة توقيع أو تشفير أو تجزئة. إذا لم تُضبط أي سياسة، يسمح ⁨Core⁩ بكل خوارزمية. هذا الإعداد الافتراضي المفتوح مناسب للتطوير، لا للإنتاج. يجب على بيئة النشر الخاضعة للتنظيم ضبط سياسة صريحة. توثّق ⁨Contracts⁩ / ⁨Security Policy⁩ سطح العقد.

أعلام الأذونات من أكثر مصادر المبالغة في الادعاء شيوعًا، لذلك تصوغها هذه الصفحة بوضوح. يُخزَّن قناع البتات الخاص بالأذونات في المُدخل المشفَّر /Perms وفي القيمة /P. يُتوقَّع من القارئ المتوافق أن يحترم هذه القيود. الأعلام لا تفرضها التعمية. يمكن للمعالِج الذي يتجاهل البتات أن يقرأ المحتوى أو ينسخه أو يعدّله بعد امتلاكه مفتاح فك التعمية. اذكر هذا الحد لأي طرف يعتمد على أعلام الأذونات.

تكامل إدارة المفاتيح ومعايير تشفير المفتاح العام #11 (⁨PKCS⁩#11) يتم عبر نقاط عقد. يأتي ⁨Core⁩ بمسار مفتاح محلي. يغلّف كائن القيمة KeyMaterial مفتاحًا بطول 256 بت مدقَّق الطول، ويقاوم الكشف في مخرجات السلاسل والتنقيح. حفظ المفاتيح عبر وحدة أمان العتاد (⁨HSM⁩)/⁨PKCS⁩#11 قدرة ⁨Enterprise⁩ مُقيَّدة خلف العقود نفسها؛ تسمّي هذه الصفحة نقطة التكامل لكنها لا توثّق تطبيق ⁨Enterprise.⁩

النوعالصنفالأعضاء الرئيسيونالاستقرارمنذ
Document::setEncryption()دالة (للاهتمام HasSecurity)userPassword، ownerPassword، permissionsمستقر1.0.0
Document::useAesGcm()دالة (للاهتمام HasSecurity)?bool $enabled — اختياري ⁨ISO/TS 32003 V⁩=6/⁨R⁩=7مستقر2.18.0
Aes256Encryptorصنفencrypt()، decrypt()، buildEncryptionDictionary()، verifyUserPassword()، verifyOwnerPassword()، validatePerms()مستقر1.0.0
Aes256GcmEncryptorصنفencrypt()، decrypt()، encryptStream()، assertWithinSafetyBound()، invocationCount()مستقر2.18.0
KeyMaterialصنف نهائي للقراءة فقط (⁨final readonly class⁩)generate()، exposeKey()، fingerprint()مستقر2.18.0
CryptoPolicyInterfaceواجهةisHashAlgorithmAllowed()، isSignatureAlgorithmAllowed()، isEncryptionAlgorithmAllowed()، isKeyStrengthAllowed()، getPreferredHashAlgorithm()، getName()مستقر1.9.0
Config::withCryptoPolicy()دالةCryptoPolicyInterface $policyمستقر1.9.0
CryptoCapabilitiesصنف نهائي (⁨final class⁩)hasAesGcm()، detectFipsMode()، assertFipsAvailableForProfile()مستقر2.0.0
examples/22-protection.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Encrypted Document — Restricted Permissions');
// Call setEncryption() BEFORE addPage().
// Permission bit 3 (value 4) = printing allowed; all other operations denied.
$doc->setEncryption(
userPassword: 'demo',
ownerPassword: 'admin',
permissions: 4,
);
$doc->addPage();
$doc->setFont('helvetica', 'B', 20);
$doc->cell(0, 14, 'Encrypted PDF Document', newLine: true);
$doc->save(__DIR__ . '/output/22-protection.pdf');

تفتح كلمة مرور المستخدم المستند. تمنح كلمة مرور المالك وصولًا كاملًا. لا تقيّد أعلام الأذونات إلا القارئ المتوافق.

examples/security/policy-gated-encryption.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\CryptoPolicyInterface;
use NextPDF\Core\Document;
use Psr\Log\LoggerInterface;
final readonly class PolicyGatedEncryption
{
public function __construct(
private CryptoPolicyInterface $cryptoPolicy,
private LoggerInterface $logger,
) {}
/**
* Encrypt only when the active policy permits AES-256-CBC.
*
* @param non-empty-string $userPassword Opens the document.
* @param non-empty-string $ownerPassword Grants full access.
*/
public function protect(
Document $doc,
string $userPassword,
string $ownerPassword,
int $permissions,
): void {
if (!$this->cryptoPolicy->isEncryptionAlgorithmAllowed('aes-256-cbc')) {
$this->logger->error('Encryption refused by crypto policy', [
'policy' => $this->cryptoPolicy->getName(),
]);
throw new \RuntimeException('AES-256-CBC denied by the active crypto policy.');
}
$doc->setEncryption($userPassword, $ownerPassword, $permissions);
$this->logger->info('Document encrypted', [
'policy' => $this->cryptoPolicy->getName(),
'algorithm' => 'aes-256-cbc',
]);
}
}

تستشير البوابة السياسة قبل التشفير، وتسجّل اسم السياسة لأغراض التدقيق، وتطرح استثناءً محددًا عندما ترفض السياسة الشيفرة.

  • استدعِ setEncryption() قبل addPage(). لا يشفّر الاستدعاء اللاحق بأثر رجعي المحتوى الذي أصدره الكاتب بالفعل.
  • نمط ⁨PDF/A⁩ والتشفير متنافيان. يحظر ⁨ISO 19005⁩ مفتاح المقطورة Encrypt في كل نكهات ⁨PDF/A⁩، لذلك تطرح setEncryption() وuseAesGcm() استثناءً عندما يكون مدير ⁨PDF/A⁩ نشطًا.
  • داخل setEncryption()، تعود كلمة مرور المالك الفارغة إلى كلمة مرور المستخدم. المستند ذو كلمة المرور المشتركة الواحدة يمنح حامل كلمة مرور المستخدم وصولًا بمستوى المالك.
  • عندما لا تُحقَن أي سياسة، يسمح CryptoPolicyInterface بكل خوارزمية. تعامل مع الإعداد الافتراضي المفتوح بوصفه راحة للتطوير، واضبط سياسة صريحة في أي بيئة نشر خاضعة للتنظيم.
  • أعلام الأذونات إرشادية للقارئ. لا تصفها بأنها تحكم في الوصول لا يستطيع معالِج معادٍ تجاوزه.

يشغّل setEncryption() روتين اشتقاق مفاتيح تكراريًّا (الخوارزمية 2.⁨B⁩، النسخة المنقحة 6) أثناء بناء المستند. التكلفة محدودة وثابتة لكل مستند؛ ولا تتناسب مع عدد الصفحات. ينفّذ التشفير لكل كائن عملية ⁨AES⁩ واحدة لكل دفق أو سلسلة. يضيف مسار ⁨AES-256-GCM⁩ الاختياري حملًا قدره 28 بايت لكل كائن (متجه تهيئة (⁨IV⁩) بطول 12 بايت إضافة إلى وسم بطول 16 بايت)، ويبثّ المحتوى الكبير في كتل بحجم 16 ميبي‌بايت. يُبقي هذا تمريرة البثّ دون ذروة الـ64 ميغابايت الموثَّقة. يهيمن عرض المستند، لا التشفير، على قيمة performance_budget البالغة 1500 مللي ثانية لزمن الجدار و64 ميغابايت للذروة.

نموذج التهديد صريح. تخفّف بوابة سياسة التعمية من تخفيض مستوى الخوارزمية برفض الشيفرات الضعيفة ودوال التجزئة الضعيفة والمفاتيح القصيرة قبل أي عملية. لا يستبدل المحرك بدائيًّا أضعف بصمت عندما يكون المطلوب غائبًا؛ بل يطرح استثناءً ليتمكّن المشغّل من التصرف. يخفّف KeyMaterial من كشف المفاتيح عبر التسجيل: تنقّح صيغته النصية وصيغة التنقيح البايتات ولا تكشفان إلا بصمة غير قابلة للعكس. لا يُكتشف العبث بالنص المشفَّر إلا على مسار ⁨AES-256-GCM⁩ الاختياري، حيث يُتحقَّق من وسم المصادقة ويطرح عدم التطابق استثناءً بدلًا من إعادة النص الصِّرف. مسار التسلسل بربط كتل الشيفرة ⁨AES-256⁩ الافتراضي (⁨AES-256-CBC⁩) مخصص للسرّية فقط ولا يكتشف التعديل بمفرده. على مسار ⁨GCM⁩، يُخفَّف من إعادة استخدام متجه التهيئة عبر عدّاد رتيب إضافة إلى مجموعة تصادم للدفاع المتعمّق، بما يتسق مع متطلب تفرّد متجه التهيئة في ⁨NIST SP 800-38D⁩ §8.

الحدّ صريح بالقدر نفسه. يُطبَّق تشفير ⁨AES-256⁩ كما هو معرَّف في ⁨ISO 32000-2⁩:2020 §7.6. تعتمد الحماية الفعلية على قوة كلمة المرور وإدارة المفاتيح وبيئة النشر والقارئ المستهلِك. يحترم القرّاء المتوافقون أعلام الأذونات، لكن التعمية لا تفرضها. يبلّغ مِسبار نمط ⁨FIPS⁩ عمّا إذا كانت بنية ⁨OpenSSL⁩ المضيفة قد حمّلت مزوّد ⁨FIPS.⁩ تعمل المكتبة في نمط متوافق مع ⁨FIPS⁩ عندما يوفّر المضيف وحدة مُصادَقًا عليها؛ وهي لا تشهد لأي وحدة. يؤطّر ⁨NIST SP 800-57⁩ الجزء 1 §4 عمر المفتاح وفترة التعمية بوصفهما مسؤوليتي بيئة النشر. يتيح ⁨Core⁩ عناصر التحكم، وتضبط بيئة النشر سياسة التدوير.

إقامة البيانات وتخفيفات معلومات التعريف الشخصية

قسم بعنوان «إقامة البيانات وتخفيفات معلومات التعريف الشخصية»

لا ينقل سطح التشفير بايتات المستند، بما فيها أي معلومات تعريف شخصية (⁨PII⁩) يحتويها، إلى خارج المضيف. يجري اشتقاق المفاتيح والتشفير وفك التعمية ضمن العملية نفسها. يفهرس مسار ⁨GCM⁩ الاختياري مجموعة تصادم متجهات التهيئة الموجودة في الذاكرة وفق بصمة مفتاح غير قابلة للعكس، لا وفق بايتات المفتاح. لا تكتب وحدة الأمان أي كلمة مرور أو قيمة مفتاح إلى القرص. تتحمل بيئة النشر التي توجّه المفاتيح عبر خدمة إدارة مفاتيح خارجية مسؤولية إقامة بيانات تلك الخدمة.

القياس عن بُعد الآمن وتنقيح السجلات

قسم بعنوان «القياس عن بُعد الآمن وتنقيح السجلات»

تعيد KeyMaterial::__toString() و__debugInfo() عنصرًا نائبًا منقَّحًا، بحيث يُنتج التسجيل العَرَضي لكائن مفتاح بصمةً، لا بايتات مفتاح. تحمل كلمات المرور المُمرَّرة إلى setEncryption() السمة #[\SensitiveParameter] التي تنقّحها من تتبّع المكدّس. للتدقيقات، استخدم اسم السياسة من CryptoPolicyInterface::getName() وبصمة المفتاح المؤلَّفة من 8 محارف بوصفهما مُعرِّفي عملية التعمية. سجّل تلك القيم، ولا تسجّل المفتاح أو كلمة المرور أبدًا.

التهديدالتخفيف في ⁨Core⁩الحدّ المتبقي
تخفيض مستوى الخوارزمية / استبدال شيفرة ضعيفةبوابة سياسة التعمية؛ لا تخفيض صامت (تطرح UnsupportedAlgorithmException)فعّال فقط عند حقن سياسة
كشف المفاتيح عبر السجلاتKeyMaterial تنقيح؛ #[\SensitiveParameter] على كلمات المرورالمتصل الذي يمرّر exposeKey() إلى مُسجِّل يُبطل هذا
العبث بالنص المشفَّرالتحقق من وسم ⁨GCM⁩ على المسار الاختياريمسار ⁨CBC⁩ الافتراضي مخصص للسرّية فقط
إعادة استخدام متجه التهيئة (⁨GCM⁩)عدّاد رتيب إضافة إلى مجموعة تصادم؛ يرفض عند الالتفاف
تجاوز أعلام الأذوناتلا شيء؛ الأعلام إرشاديةالقارئ غير المتوافق يتجاهل الأعلام
الهجوم بالقوة الغاشمة على كلمة مرور ضعيفة⁨SASLprep⁩ إضافة إلى اشتقاق المفاتيح التكراري يرفعان التكلفةكلمة المرور الضعيفة تبقى الخطر المهيمن

⁨Core⁩ ليس وحدة تعمية مُصادَقًا عليها وفق ⁨FIPS⁩، وليس معتمدًا وفق ⁨FIPS.⁩ CryptoCapabilities::detectFipsMode() مِسبار وقت تشغيل بأفضل جهد: يقرأ تجاوز المشغّل، ثم قائمة مزوّدي ⁨OpenSSL⁩، ثم استدعاء نمط ⁨FIPS⁩ القديم، ويبلّغ بحالة نشط أو غائب أو غير محدَّد. يفشل assertFipsAvailableForProfile() بصورة مغلقة عندما يُختار ملف تعريف ⁨FIPS⁩ على مضيف لا يمكنه إثبات وجود مزوّد ⁨FIPS.⁩ تعمل المكتبة في نمط متوافق مع ⁨FIPS⁩ عندما تُهيَّأ مقابل بنية ⁨OpenSSL⁩ مضيفة حمّلت مزوّدًا مُصادَقًا عليه وفق ⁨FIPS.⁩ الوضعية المُصادَق عليها والمعتمدة وفق ⁨FIPS⁩ هي اهتمام ⁨Enterprise⁩؛ راجع وثائق ⁨Enterprise.⁩

الادعاءالمعيارالبندالدليل
يُبقي مسار ⁨GCM⁩ كل متجه تهيئة فريدًا لكل استدعاء، بما يتسق مع متطلب التفرّد في المعيار.⁨NIST SP 800-38D⁩§8.2.1
يتيح ⁨Core⁩ عناصر تحكم في عمر المفتاح وفترة التعمية؛ وتملك بيئة النشر السياسة.⁨NIST SP 800-57⁩ الجزء 1 النسخة المنقحة 5§4
مفتاح ملف ⁨AES⁩ بطول 256 بت، وهو ما يطابق طول المفتاح في المعيار.⁨FIPS 197⁩§4.2.1
توليد المفاتيح المقيمة على الرمز المميَّز هو نقطة التكامل لمخزن مفاتيح خارجي.⁨OASIS PKCS⁩#11 ⁨v3.1⁩⁨C_GenerateKey⁩

⁨ISO 32000-2⁩:2020 §7.6 هو الأساس المعياري لمعالج الأمان القياسي. نصه مُقيَّد بالترخيص ومُعاد صياغته هنا، ولا يُقتبس أبدًا؛ تستشهد هذه الصفحة بالبند برقمه. كل نقطة أعلاه مُعاد صياغتها من المعيار المستشهَد به.

يعرّف ⁨Core⁩ عقد سياسة التعمية ويثبّته، ويأتي بمسار تشفير ⁨AES-256⁩، ويوفّر سطح مفتاح محلي. يوفّر إصدار ⁨Enterprise⁩ مسار ⁨HSM/PKCS⁩#11 لحفظ المفاتيح وملف تعريف سياسة تعمية بنمط ⁨FIPS⁩ خلف CryptoPolicyInterface نفسه. سطح العقد متطابق عبر الإصدارات؛ تحقن بيئة النشر تطبيق سياسة مختلفًا وخلفية مختلفة لحفظ المفاتيح.