CSPRNG هو مولّد أعداد شبه عشوائية آمن تشفيرياً. يحسب قيماً جديدة انطلاقاً من حالة داخلية سرية وفق خطوات محددة. ولا تعني «شبه عشوائية» رداءة الجودة: يمكن تكرار الحساب، لكن ينبغي أن يصعب عملياً توقّع نتائجه من دون معرفة الحالة السرية. وهذا يحتاج إلى إنتروبيا كافية، أي عدم يقين بشأن المدخلات من منظور المهاجم، وإلى استخدام المولّد بطريقة صحيحة داخل التطبيق.
تخيّل برنامجاً ينشئ قيماً سرية لمحفظة، ثم يعرف المهاجم بعض مخرجاته السابقة. يجب ألا يتيح له المولّد الآمن استخدام هذه المعرفة لتسهيل تخمين البقية. وهذا شرط أشد من توزيع أرقام يبدو جيداً في رسم بياني. لذلك يميّز RFC 4086 التسلسلات القوية تشفيرياً عن مولّدات المحاكاة المعتادة. وحتى النجاح في اختبار إحصائي لا يكفي إذا أمكن تخمين seed، أي القيمة الابتدائية التي انطلق منها التوليد. [1]
تستخدم الوثائق التقنية أيضاً اسم DRBG، أي مولّد البتات العشوائية الحتمي. ومعنى «حتمي» أن الحالة والمدخلات نفسها تعطي النتيجة نفسها؛ ولذلك يجب أن تبقى الحالة سرية. تصف NIST SP 800-90A Rev. 1 آليات محددة هي Hash_DRBG وHMAC_DRBG وCTR_DRBG. هذه إجراءات تقنية، وليست شهادة جودة لكل برنامج يذكر أسماءها. ويجب فحص الإعدادات ومصدر الإنتروبيا والتنفيذ الفعلي في الشيفرة أيضاً. [2]
يطرح تسرب الحالة سؤالين مختلفين: هل يستطيع المهاجم إعادة حساب المخرجات السرية السابقة؟ وهل يستطيع توقّع التالية؟ تسمى حماية المخرجات الماضية Backtracking resistance، وحماية المستقبلية Prediction resistance. وتشترط NIST SP 800-90A للحماية الثانية إدخال إنتروبيا جديدة بفعالية، بحيث تنفصل النتائج الجديدة عن الحالة المكشوفة. مجرد إجراء الحساب مرة أخرى قد لا يعيد الأمان. كما أن وجود إحدى الحمايتين لا يثبت الأخرى تلقائياً. [2]
المكتبة مكوّن برمجي جاهز يمكن للمحفظة استخدامه، لكن استدعاءه قد يفشل. في OpenSSL 3.5، تعيد RAND_bytes() وRAND_priv_bytes() القيمة 1 عند النجاح، و0 عند فشل آخر، و-1 إذا كانت الطريقة الحالية غير مدعومة. وقد يُرفض التوليد عند تعطل مصدر الإنتروبيا. على البرنامج فحص هذه النتيجة قبل استخدام مساحة الذاكرة المحجوزة، التي تسمى المخزن المؤقت أو buffer. وإلا فقد يستخدم بيانات لم تُولّد بأمان أصلاً. [3]
إمكانية التكرار مفيدة للاختبارات؛ فالمطوّر يريد مقارنة النتيجة بما يتوقعه. لذلك تنتج الدالة randombytes_buf_deterministic() في libsodium التسلسل نفسه من seed نفسها. لكن التكرار غير المقصود مشكلة أثناء التشغيل الفعلي. لقطة الآلة الافتراضية تحفظ حالة الحاسوب بما فيها الذاكرة، وقد تؤدي استعادتها إلى تكرار حالة المولّد ومخرجاته أيضاً. لذلك لا تضمن نسخ بيئة التشغيل إنشاء أسرار مستقلة عن بعضها. [4]
قد يقدّم المولّد بيانات عشوائية جيدة ثم يعالجها التطبيق بطريقة خاطئة. تحويلها إلى نطاق مسموح أصغر باستخدام باقي القسمة وحده قد يجعل بعض النتائج أكثر تكراراً من غيرها. تعالج الدالة randombytes_uniform() في libsodium هذا الانحياز بالاختيار المنتظم تحت حد أعلى محدد. وللمفاتيح أيضاً قواعد تفرضها الخوارزمية المستخدمة. لا ينتهي الأمان بالحصول على بايتات عشوائية؛ بل يعتمد كذلك على ما يفعله البرنامج بها لاحقاً. [4]
nonce قيمة مخصصة لاستخدام منفرد في إجراء تشفيري، لكن البروتوكول هو الذي يحدد قواعدها. تتطلب RFC 8439 ألا تتكرر هذه القيمة مع المفتاح نفسه؛ فالمظهر العشوائي لا يضمن التفرد. أما RFC 6979 فتصف حساب القيمة k اللازمة للتوقيع الرقمي حتمياً من المفتاح السري والرسالة المراد توقيعها. هذا اختلاف في التصميم وليس تناقضاً. لذا لا تحل عبارة «أضف العشوائية في كل مكان» محل الإجراء الصحيح. [5] [6]
لا يكشف اسم CSPRNG وحده ما إذا كانت المحفظة تستخدم المنظومة كاملة بصورة صحيحة. يراجع الفحص التقني نسخة المكتبة المحددة، وبدء تشغيل المولّد، ومعالجة الأخطاء، والسلوك بعد استعادة الحالة أو نسخها. وتثبت وثائق OpenSSL وlibsodium خصائص دوالهما، لا أمان كل تطبيق يستدعيها. وما يحدث لاحقاً مهم للمستخدم أيضاً: فالسر الذي وُلّد على نحو سليم تماماً لا يعود يحمي الأموال إذا تسربت لاحقاً نسخة احتياطية تسمح باستعادة الوصول. [3] [4]
للحصول على صورة أوضح، اقرأ هذا المدخل مع Cryptographic Entropy, Random Number Generator, Deterministic RNG, Seed Generation. تشير إلى هذا المدخل أيضًا Dice Roll Entropy, Cryptographic Entropy, Random Number Generator, Deterministic RNG.