التشفير: AES-256 (CBC) وAES-256-GCM
لمحة سريعة
قسم بعنوان «لمحة سريعة»يشفّر Core ملفات PDF باستخدام AES-256 (معيار التشفير المتقدم بمفاتيح طولها 256 بت) ضمن معالِج الأمان القياسي في ISO 32000-2:2020 §7.6. الوضع الافتراضي هو V=5 / R=6 / AESV3 (AES-256-CBC، تسلسل كتل التشفير). أما الوضع المُصادَق الاختياري فهو مسار ISO/TS 32003:2023 V=6 / R=7 AES-256-GCM (وضع غالوا/العدّاد). توضّح هذه الصفحة اشتقاق المفتاح، وتنسيق النقل، وحدّ الأذونات، وحدود النشر.
التثبيت
قسم بعنوان «التثبيت»composer require nextpdf/core:^3يتطلّب المسار الافتراضي امتداد openssl. يستخدم مسار AES-256-GCM إمّا openssl أو ext-sodium. على المضيفين الذين لا يتوفر لديهم عتاد AES-NI، يرفض libsodium وضع GCM؛ فيعود Core إلى تنفيذ OpenSSL الأبطأ من دون تغيير الخوارزمية.
نظرة مفاهيمية عامة
قسم بعنوان «نظرة مفاهيمية عامة»يستخدم المعالِج الافتراضي معالِج الأمان القياسي V=5 / R=6 مع مرشّح التشفير AESV3. عند استدعاء setEncryption()، يولّد Core مفتاح ملف عشوائيًا بطول 256 بت من مصدر عشوائية تعموي في المنصّة (random_bytes()). يبلغ طول المفتاح 32 بايت، بما يطابق طول مفتاح FIPS 197. يشفّر Core محتوى كل كائن على حدة باستخدام AES-256-CBC. ويسبق كل نص مشفَّر بمتجِّه تهيئة بطول 16 بايت، كما يوجّه ISO 32000-2:2020 §7.6.4.
يتّبع اشتقاق المفتاح الخوارزمية 2.B عند المراجعة 6. يطبّع Core كلمة المرور أولًا باستخدام SASLprep (RFC 4013)، ثم يقتطعها إلى 127 بايت من UTF-8 عند حدّ محرف، كما يوجّه ISO 32000-2:2020 §7.6.4.3.3. ويحسب التجزئة المشتقّة بروتين مكرَّر من SHA-256 / SHA-384 / SHA-512 تقوده خطوة AES-128-CBC، مما يرفع تكلفة تخمين كلمة المرور دون اتصال. يولّد Core أملاح المستخدم والمالك وكل مفتاح مرة واحدة لكل نسخة من المُشفِّر، فتُنتج النسخة الواحدة بايتات قاموس حتمية، وهو شرط مسبق للكاتب متعدّد التمريرات.
useAesGcm() يفعّل مسار AES-256-GCM الاختياري. ينفّذ هذا المسار مرشّح التشفير ISO/TS 32003:2023 V=6 / R=7 AESV4. الخوارزمية هي AES-256-GCM بمعاملات من NIST SP 800-38D. لكل كائن مشفَّر، يتكوّن تخطيط النقل من متجِّه تهيئة بطول 12 بايت، ثم النص المشفَّر، ثم وسم مصادقة بطول 16 بايت. تكون البيانات المُصادَقة الإضافية فارغة، كما يوجّه ملف تعريف TS 32003 §5.2. يتحقّق فكّ التشفير من الوسم ويثير TamperedDataException عند عدم التطابق؛ ولا يُرجع أبدًا نصًا صريحًا بعد فشل الوسم. يضيف هذا المسار كشف التعديل، وهو ما لا يوفّره مسار CBC الافتراضي من تلقاء نفسه.
يتّبع مسار GCM انضباط تفرّد متجِّه التهيئة في NIST SP 800-38D §8. تمثّل البايتات الأربعة العليا من متجِّه التهيئة حقلًا ثابتًا لكل نسخة، ويُضبط هذا الحقل من مصدر عشوائي أثناء الإنشاء. أما البايتات الثمانية السفلى فهي عدّاد كبير النهاية يتزايد بعد كل متجِّه تهيئة يُصدر. يتّبع ذلك نهج الإنشاء الحتمي في §8.2.1، إلا أن الحقل الثابت يُعشَّى لمنع التصادمات عبر المستندات بدلًا من تعداده. ويسجّل حارس ثانٍ كل متجِّه تهيئة مُصدَر في مجموعة تصادم، ويثير NonceReuseException إذا تكرّرت قيمة. كذلك يثير تجاوز سعة العدّاد NonceReuseException، لأنّ تجاوز السعة نمط فشل لإعادة استخدام متجِّه التهيئة الذي يحذّر منه §8.
ينطبق حدّان للطول على مسار GCM. سقف النص الصريح لكل كائن هو 2^39 − 256 بايت، وهو الحدّ المشتق لكل استدعاء في NIST SP 800-38D §5.2.1.1. يثير الإدخال الأكبر استثناء طول مع إرشاد إلى تقسيم البيانات عبر الكائنات. حدّ أمان الاستدعاء هو 2^32 استدعاء لكل مفتاح. assertWithinSafetyBound() فحص اختياري يثير GcmInvocationLimitExceededException، مما يتيح للمستدعي تدوير مفتاح المستند قبل عتبة §8.3. يعدّ NIST SP 800-57 الجزء 1 §4 قرار عمر المفتاح هذا مسؤولية نشر.
أعلام الأذونات إرشادية. يكتب Core قناع البتات في مدخل /Perms المشفَّر وقيمة /P، ثم يسترده عبر validatePerms() عند القراءة، ويفشل مغلقًا عند وجود علامة تالفة. يُتوقّع من القارئ المتوافق أن يحترم الأعلام. الأعلام غير مفروضة بالتعمية: فالمعالِج الذي يملك مفتاح فكّ التشفير ويتجاهل البتات يمكنه قراءة المحتوى أو نسخه أو تعديله. صِف أعلام الأذونات باعتبارها عُرفًا للقارئ، لا تحكّمًا في الوصول.
سطح واجهة البرمجة
قسم بعنوان «سطح واجهة البرمجة»| النوع | الصنف | الأعضاء الرئيسيون | الاستقرار | منذ |
|---|---|---|---|---|
Aes256Encryptor | صنف | encrypt(), decrypt(), encryptForObject(), buildEncryptionDictionary(), verifyUserPassword(), verifyOwnerPassword(), validatePerms(), getEncryptionKey() | مستقر | 1.0.0 |
Aes256GcmEncryptor | صنف | encrypt(), decrypt(), encryptStream(), assertWithinSafetyBound(), invocationCount(), isAvailable() | مستقر | 2.18.0 |
KeyMaterial | صنف نهائي للقراءة فقط | generate(), exposeKey(), fingerprint() | مستقر | 2.18.0 |
EncryptedPayloadSpec | صنف نهائي للقراءة فقط | toDict() | مستقر | 2.18.0 |
CryptoCapabilities | صنف نهائي | hasAesGcm(), detectFipsMode(), assertFipsAvailableForProfile() | مستقر | 2.0.0 |
NonceReuseException | استثناء | — | مستقر | 2.18.0 |
TamperedDataException | استثناء | — | مستقر | 2.18.0 |
DecryptionFailedException | استثناء | — | مستقر | 2.18.0 |
GcmInvocationLimitExceededException | استثناء | — | مستقر | 3.0.0 |
مثال برمجي — بداية سريعة
قسم بعنوان «مثال برمجي — بداية سريعة»<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
// AES-256-CBC, V=5/R=6. Call before addPage().$doc->setEncryption( userPassword: 'demo', ownerPassword: 'admin', permissions: 4, // printing only; copy/modify denied for a conforming reader);
$doc->addPage();$doc->setFont('helvetica', '', 12);$doc->cell(0, 8, 'Confidential', newLine: true);
$doc->save(__DIR__ . '/output/22-protection.pdf');مثال برمجي — للإنتاج
قسم بعنوان «مثال برمجي — للإنتاج»<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Security\CryptoCapabilities;use NextPDF\Security\Encryption\Aes256GcmEncryptor;use NextPDF\Security\Exception\TamperedDataException;use NextPDF\Security\KeyMaterial;use Psr\Log\LoggerInterface;
final readonly class AuthenticatedBlobCipher{ public function __construct(private LoggerInterface $logger) {}
/** * Seal a payload with AES-256-GCM and return the wire-format bytes. * * @param non-empty-string $plaintext The payload to protect. * * @return non-empty-string IV(12) || ciphertext || tag(16). */ public function seal(string $plaintext, KeyMaterial $key): string { if (!CryptoCapabilities::hasAesGcm()) { throw new \RuntimeException('Host cannot perform AES-256-GCM.'); }
$cipher = new Aes256GcmEncryptor($key); // Opt-in NIST SP 800-38D §8.3 key-rotation guard. $cipher->assertWithinSafetyBound();
$wire = $cipher->encrypt($plaintext);
$this->logger->info('Payload sealed', [ 'key_fingerprint' => $key->fingerprint(), 'invocations' => $cipher->invocationCount(), ]);
return $wire; }
/** * Open a sealed payload; a modified payload raises, never returns plaintext. * * @param non-empty-string $wire IV(12) || ciphertext || tag(16). */ public function open(string $wire, KeyMaterial $key): string { try { return (new Aes256GcmEncryptor($key))->decrypt($wire); } catch (TamperedDataException $e) { $this->logger->warning('Tampered payload rejected', [ 'key_fingerprint' => $key->fingerprint(), ]);
throw $e; } }}يتحقّق المُشفِّر من قدرة المضيف، ويطبّق حارس الاستدعاء الاختياري، ولا يسجّل إلا بصمة المفتاح غير القابلة للعكس، ويعيد إثارة رفض العبث بدلًا من إرجاع بايتات مشبوهة.
الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- يوفّر مسار AES-256-CBC الافتراضي السرّية فقط. ولا يكشف النص المشفَّر المعدَّل من تلقاء نفسه. استخدم مسار AES-256-GCM عندما تحتاج إلى كشف التعديل.
- يثير
useAesGcm()استثناءً عندما يكون وضع PDF/A نشطًا، وعندما لا يوفّر أيٌّ منopensslولاext-sodiumوضع AES-256-GCM. التقط كلتا الحالتين واعرض رسالة قابلة للتنفيذ من قِبل المشغّل. - على المضيفين الذين لا يتوفر لديهم AES-NI، يرفض libsodium وضع GCM. يعود Core إلى OpenSSL GCM، وهو صحيح لكنه أبطأ؛ فتنخفض الإنتاجية لا الأمان.
- سقف النص الصريح لكل كائن في GCM هو
2^39 − 256بايت. يثير الإدخال الأكبر استثناء طول؛ فقسّم المحتوى عبر كائنات متعدّدة باستخدامencryptStream(). - يجب أن تكون نسخة
KeyMaterialبطول 32 بايت بالضبط. يرفض الإنشاء الطول الخاطئ بدلًا من اقتطاعه. - مسار القراءة (
verifyUserPassword()،verifyOwnerPassword()،validatePerms()) يستخدم مقارنة بزمن ثابت للمواد التعموية ويفشل مغلقًا عند علامة أذونات تالفة.
الأداء
قسم بعنوان «الأداء»تشفير AES-256-CBC لكل كائن هو استدعاء OpenSSL واحد، وزمنه O(n) في جسم الكائن. يشغّل اشتقاق المفتاح روتين الخوارزمية 2.B المكرَّر مرة واحدة لكل نسخة من المُشفِّر؛ والتكلفة محدودة وثابتة لكل مستند. يقسّم مسار بثّ AES-256-GCM الإدخال إلى أجزاء بحجم 16 ميبي بايت، فيحدّ استخدام الكومة الحيّة إلى نحو 64 ميغابايت بصرف النظر عن الحجم الكلّي للإدخال، ويبقى دون ميزانية الذروة الموثّقة البالغة 64 ميغابايت. يضيف كل كائن GCM عبئًا قدره 28 بايت (متجِّه تهيئة بطول 12 بايت زائد وسم بطول 16 بايت). يحسّن عتاد AES-NI إنتاجية GCM تحسينًا ملموسًا؛ وبدونه تنخفض الإنتاجية فقط.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»لهذا السطح التشفيري نموذج تهديد صريح. يرفع تطبيع SASLprep مع اشتقاق المفتاح المكرَّر بالمراجعة 6 تكلفة تخمين كلمة المرور دون اتصال، لكن كلمة المرور الضعيفة تظلّ الخطر المتبقّي المهيمن. لا يزيل أي اشتقاق ذلك الخطر. يكشف مسار GCM تعديل النص المشفَّر عبر التحقّق من الوسم؛ أما مسار CBC الافتراضي فلا يفعل. في مسار GCM، يمنع عدّاد مع مجموعة تصادم إعادة استخدام متجِّه التهيئة، بما يتّسق مع انضباط متجِّه التهيئة في NIST SP 800-38D §8.1. يرفض تجاوز سعة العدّاد بدلًا من الالتفاف. يخفّف حجب KeyMaterial وسمة #[\SensitiveParameter] على كلمات المرور كشفَ المفتاح عبر السجلّات. تُصفَّر مواد المفتاح المشتقّة بعد الاستخدام حيث تسمح المنصّة بذلك.
الحدّ صريح أيضًا. يطبّق Core تشفير AES-256 كما هو معرَّف في ISO 32000-2:2020 §7.6، ويطبّق للمسار الاختياري ISO/TS 32003:2023 §5.2. تعتمد الحماية الفعّالة على قوّة كلمة المرور، وإدارة المفاتيح، وبيئة النشر، والقارئ المستهلِك. يحترم القرّاء المتوافقون أعلام الأذونات، لكن التعمية لا تفرضها. يفرض ISO 32000-2:2020 §7.6.4.4.10 خطوة AES-ECB المستخدمة لقيمة /Perms لكتلة واحدة بطول 16 بايت. وهي ليست وضعًا عامّ الأغراض. يكشف Core فحصًا لتدوير المفتاح قبل حدّ الاستدعاء 2^32، لكنه لا يفرضه افتراضيًا؛ وذلك التدوير مسؤولية نشر.
مقرّ البيانات وتخفيفات معلومات التعريف الشخصية
قسم بعنوان «مقرّ البيانات وتخفيفات معلومات التعريف الشخصية»يجري التشفير وفكّ التشفير داخل العملية؛ ولا تغادر المضيف عبر هذا السطح أي بايتات للمستند أو كلمة مرور أو قيمة مفتاح. تستند مجموعة تصادم متجِّه التهيئة في GCM إلى بصمة مفتاح غير قابلة للعكس، لا إلى بايتات المفتاح. إذا وضع نشرٌ ما المفتاح خلف نظام خارجي لإدارة المفاتيح أو رمز PKCS#11، فإنّ تلك الخلفية مسؤولة عن المقرّ؛ ويكون OASIS PKCS#11 v3.1 C_GenerateKey نقطة الربط لتوليد مفتاح مقيم في الرمز.
القياس الآمن عن بُعد وتنقية السجلّات
قسم بعنوان «القياس الآمن عن بُعد وتنقية السجلّات»سجّل اسم السياسة وبصمة المفتاح المكوّنة من 8 محارف، ولا تسجّل المفتاح أو كلمة المرور أبدًا. يُرجع KeyMaterial::__toString() و__debugInfo() عنصرًا نائبًا محجوبًا. تتضمّن الاستثناءات من هذا السطح تسمية العملية والبصمة، لا بايتات المفتاح. عدّاد استدعاء GCM قياسٌ آمن عن بُعد للوحات معلومات تدوير المفتاح.
نموذج التهديد
قسم بعنوان «نموذج التهديد»| التهديد | التخفيف في Core | الحدّ المتبقّي |
|---|---|---|
| تخمين كلمة المرور دون اتصال | SASLprep مع الاشتقاق المكرَّر بالمراجعة 6 | كلمة المرور الضعيفة لا تزال الخطر المهيمن |
| تعديل النص المشفَّر | التحقّق من وسم GCM (المسار الاختياري) | مسار CBC للسرّية فقط |
| إعادة استخدام متجِّه التهيئة (GCM) | حقل ثابت عشوائي مع عدّاد مع مجموعة تصادم؛ تجاوز السعة يرفض | — |
| نص صريح مفرط الطول في GCM | فحص الطول عند 2^39 − 256؛ إرشاد التقسيم | على المستدعي بثّ الإدخال الكبير |
| الإفراط في استخدام المفتاح (GCM) | assertWithinSafetyBound() عند 2^32 | اختياري؛ غير مفروض افتراضيًّا |
| تجاوز أعلام الأذونات | لا شيء — الأعلام إرشادية | القارئ غير المتوافق يتجاهل الأعلام |
| كشف المفتاح عبر السجلّات | حجب KeyMaterial؛ #[\SensitiveParameter] | المستدعي الذي يسجّل exposeKey() يُبطل هذا |
سلوك وضع FIPS
قسم بعنوان «سلوك وضع FIPS»Core ليس وحدة تشفير مُصدَّقة وفق FIPS وليس معتمدًا وفق FIPS. CryptoCapabilities::detectFipsMode() فحصٌ بأفضل جهد يُبلّغ بأنّ الوضع نشط أو غائب أو غير محدَّد. assertFipsAvailableForProfile() يفشل مغلقًا عند تحديد ملف تعريف FIPS على مضيف لا يثبت وجود مزوّد FIPS. يعمل السطح التشفيري في وضع متوافق مع FIPS عندما يُشغَّل على بنية OpenSSL مضيفة حمّلت مزوّدًا مُصدَّقًا وفق FIPS. الوضعية المُصدَّقة والمعتمدة شأن خاص بإصدار Enterprise.
التوافق
قسم بعنوان «التوافق»| الادّعاء | المعيار | البند | الدليل |
|---|---|---|---|
| كل متجِّه تهيئة في GCM فريد لكل استدعاء عبر إنشاء حتمي من حقل ثابت مع عدّاد. | NIST SP 800-38D | §8.2.1 | |
| انضباط إنشاء متجِّه التهيئة يمنع إعادة الاستخدام عبر الاستدعاءات على مفتاح واحد. | NIST SP 800-38D | §8.1 | |
| سقف النص الصريح لكل كائن يطابق حدّ الطول لكل استدعاء. | NIST SP 800-38D | §5.2.1.1 | |
| مدّة صلاحية المفتاح وتدويره مسؤولية النشر. | 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 وISO/TS 32003:2023 §5.2 هما الأساس المعياري للمعالِجات الموثّقة هنا. نصّهما مقيَّد بالترخيص. تعيد هذه الصفحة صياغة تلك المعايير، وتستشهد بالبنود بالأرقام، ولا تقتبس أيًا منها. يوفّر اختبار معايير الخوارزمية 2.B وأداة الوحي الخارجي في ذيل دليل الصفحة الدليل الزمني المتحقَّق منه للاشتقاق الدقيق للمفتاح بايتًا ببايت.
السياق التجاري
قسم بعنوان «السياق التجاري»يوفّر Core مسار AES-256-CBC الافتراضي، ومسار AES-256-GCM الاختياري، وسطح المفتاح المحلّي، وبوابة سياسة التشفير. يضيف إصدار Enterprise خلفية حفظ مفاتيح HSM/PKCS#11 وملف تعريف سياسة تشفير بوضع FIPS خلف العقود نفسها. واجهة برمجة التطبيقات العامة (API) متطابقة؛ وتختلف خلفية حفظ المفاتيح وتنفيذ السياسة.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- الأمان — نظرة عامة على وحدة الأمان وحدّ الأذونات.
- العقود / سياسة الأمان — عقد سياسة التشفير الذي يبوّب الخوارزمية.
- الأمان / التوقيع — التواقيع والطوابع الزمنية، السطح التشفيري الشقيق.
- التوافق — حظر PDF/A لمفتاح
Encrypt.