حول المحتوى:
تعرف على الفرق الجوهري بين مكتبة random ومكتبة secrets في بايثون، واكتشف متى تستخدم كل واحدة، ولماذا قد يؤدي الاستخدام الخاطئ إلى ثغرات أمنية خطيرة. المقال يشمل أمثلة عملية ومقارنة مباشرة.
في عالم البرمجة، التوليد العشوائي هو أحد الأدوات الأساسية التي تُستخدم في الكثير من التطبيقات. سواءً كنت تطوّر لعبة تحتاج إلى اختيار عشوائي لحركات الخصم، أو كنت تُجري محاكاة لبيانات عشوائية، أو حتى تبني نظامًا لتسجيل الدخول باستخدام رموز تحقق مؤقتة، فإنك ستحتاج إلى نوع من أنواع العشوائية. لكن ليس كل عشوائي يُعتبر "عشوائيًا" بالمعنى نفسه.
بايثون توفّر مكتبتين رئيسيتين للتعامل مع العشوائية: random
وsecrets
. قد يظن البعض أن كلاهما يؤدي الغرض ذاته، لكنه في الواقع هناك فرق جوهري بينهما مرتبط بالغرض من الاستخدام.
مكتبة random
مصممة للاستخدامات العامة التي لا تتطلب أمانًا عاليًا، مثل الألعاب والاختبارات البسيطة، وتعتمد على مولد أرقام "شبه عشوائي" (Pseudo-Random Number Generator). هذا يعني أن النتائج التي تنتجها يمكن التنبؤ بها إذا عرفت الحالة الأولية (seed) التي بدأ بها التوليد.
أما مكتبة secrets
، فقد ظهرت في بايثون لتلبية حاجة حقيقية في التطبيقات الأمنية. فهي تولد أرقامًا عشوائية يصعب - بل يستحيل عمليًا - التنبؤ بها، وتُستخدم في توليد كلمات مرور، رموز تحقق، مفاتيح سرية، وكل ما يرتبط بالأمان الرقمي.
في هذا المقال، سنتعمق في الفرق بين random
وsecrets
، ونوضح متى تستخدم كل واحدة، ولماذا الاختيار الخاطئ بينهما قد يكون له تبعات أمنية خطيرة.
الحاسوب بطبيعته جهاز حتمي، أي أنه ينفذ التعليمات بنفس الطريقة كل مرة. لهذا، لا يستطيع أن يولّد "عشوائية حقيقية" مثل ما يحدث في الطبيعة. بدلاً من ذلك، يستخدم خوارزميات رياضية تُنتج أرقامًا تبدو عشوائية، لكنها في الواقع ناتجة عن عمليات حسابية تبدأ من قيمة ابتدائية تُعرف باسم seed
. هذا ما يُسمى "العشوائية شبه الحقيقية" (Pseudo-Randomness)، وهي ما تستخدمه مكتبة random
.
أما للحصول على عشوائية حقيقية أو قريبة جدًا منها، كما تفعل مكتبة secrets
، فإن بايثون تعتمد على مصادر عشوائية على مستوى النظام مثل os.urandom
، التي تسحب بيانات غير متوقعة من البيئة الفعلية للجهاز (مثل حركة الماوس، توقيتات الشبكة، إلخ)، مما يجعل التنبؤ بها صعبًا أو مستحيلاً.
مكتبة random
هي الأداة الافتراضية في بايثون لتوليد أرقام أو قيم عشوائية. وهي مصممة لتكون سريعة وسهلة الاستخدام في البرامج التي لا تتطلب أمانًا عاليًا. تعتمد random
على خوارزمية تولد أرقامًا "شبه عشوائية"، أي أنها قد تبدو عشوائية للمستخدم، لكنها في الحقيقة ناتجة عن سلسلة حسابات تبدأ من نقطة معينة (seed). هذا يعني أنك إذا استخدمت نفس seed
مرتين، ستحصل على نفس التسلسل العشوائي في كل مرة.
وهذا السلوك مفيد في بعض الحالات مثل الاختبارات البرمجية أو المحاكاة، حيث تريد أن تعيد نفس النتائج كل مرة لأغراض التصحيح أو التجربة.
random.random()
: يولّد عدد عشري بين 0 و1.
random.randint(a, b)
: يولد عددًا صحيحًا بين a
وb
.
random.choice(seq)
: يختار عنصرًا عشوائيًا من قائمة أو سلسلة.
random.shuffle(seq)
: يعيد ترتيب العناصر في القائمة عشوائيًا.
random.seed(value)
: يضبط نقطة البداية لتوليد العشوائية.
import random
names = ['Ali', 'Sara', 'John', 'Lina']
winner = random.choice(names)
print("The winner is:", winner)
في هذا المثال، يتم اختيار اسم عشوائي من القائمة. النتيجة ستتغير في كل تشغيل للبرنامج، ما لم تستخدم random.seed()
.
لكن رغم سهولة استخدام random
، يجب أن تتجنب استخدامها في أي تطبيق يتعامل مع الأمن أو الخصوصية، لأنها ليست مقاومة للهجمات التي تحاول التنبؤ بالقيم الناتجة.
مكتبة secrets
جاءت لتسد فجوة خطيرة في عالم التوليد العشوائي في بايثون، وهي الحاجة إلى "عشوائية آمنة تشفيريًا" (Cryptographically Secure Randomness). هذه العشوائية مطلوبة في التطبيقات التي تعتمد على أمان البيانات، مثل إنشاء كلمات مرور، رموز تحقق (OTP)، رموز الدخول المؤقتة (tokens)، أو مفاتيح المصادقة.
على عكس مكتبة random
، التي يمكن التنبؤ بقيمها إذا عرف المهاجم قيمة seed
أو تسلسل القيم السابقة، فإن secrets
تعتمد على مصادر عشوائية حقيقية من نظام التشغيل، مثل os.urandom()
، والتي توفر بيانات يصعب أو يستحيل توقعها.
secrets.choice(seq)
: يختار عنصرًا عشوائيًا من تسلسل بطريقة آمنة.
secrets.randbelow(n)
: يُولد رقمًا عشوائيًا بين 0 وn-1 بأمان.
secrets.token_hex(nbytes=...)
: يولد سلسلة عشوائية من أحرف hex.
secrets.token_urlsafe(nbytes=...)
: يولد سلسلة آمنة للاستخدام في URLs أو التوثيق.
import secrets
alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'
password = ''.join(secrets.choice(alphabet) for _ in range(12))
print("Generated secure password:", password)
في هذا المثال، يتم توليد كلمة مرور مكونة من 12 حرفًا باستخدام secrets.choice
. كل اختيار يتم بطريقة عشوائية لا يمكن التنبؤ بها، حتى لو أعيد تشغيل البرنامج مئات المرات.
مكتبة secrets
ضرورية في أي مشروع يتعامل مع بيانات حساسة أو مستخدمين حقيقيين. استخدام random
بدلًا منها في هذه الحالات يعتبر خللاً أمنيًا قد يؤدي إلى اختراق النظام أو تجاوز التحقق.
من السهل الوقوع في خطأ استخدام مكتبة random
في سيناريو يتطلب أمانًا عاليًا، خصوصًا أن random.choice
وsecrets.choice
يقدمان نفس الوظيفة من حيث المظهر. لكن عند النظر إلى الفرق العميق بين المكتبتين، يتضح أن كل واحدة صُممت لغرض محدد، ولا يجوز الخلط بينهما.
فيما يلي مقارنة تفصيلية توضح الفروقات الجوهرية بين random
وsecrets
:
الخاصية | random | secrets |
---|---|---|
مستوى الأمان | غير آمن للتشفير | آمن تشفيريًا |
إمكانية إعادة النتائج (seed) | نعم، عبر random.seed() | لا، لا توجد إمكانية للتحكم في البداية |
التنبؤ بالقيم | ممكن، خاصة إذا عرف المهاجم الـ seed | مستحيل تقريبًا |
سرعة التنفيذ | أسرع | أبطأ قليلًا بسبب استخدام مصادر نظامية |
مناسبة للألعاب والمحاكاة | نعم | لا |
مناسبة لكلمات المرور/الرموز | لا | نعم |
تعتمد على | خوارزمية حسابية داخلية | مصدر عشوائية من النظام (os.urandom ) |
random
ممتازة للعمليات غير الأمنية: ألعاب، نماذج، اختبارات.
secrets
ضرورية عندما يكون هناك تعامل مع بيانات حساسة أو توثيق أو تشفير.
الاختيار الخاطئ قد يؤدي إلى ثغرات أمنية حقيقية.
الفهم الصحيح لهذه الفروقات ليس مجرد مسألة كفاءة برمجية، بل أحيانًا يكون الفاصل بين تطبيق آمن وآخر يمكن كسره بسهولة.
تُستخدم مكتبة random
عندما يكون التوليد العشوائي مطلوبًا لأغراض غير أمنية، أي عندما لا يهم إذا استطاع شخص ما التنبؤ بالقيم الناتجة. هذا النوع من الاستخدام شائع جدًا في البرمجة اليومية، خاصة في مجالات مثل:
تطوير الألعاب: مثل اختيار حركة عشوائية للخصم، أو توزيع عناصر على الخريطة.
المحاكاة: توليد بيانات شبه واقعية لاختبار نظام أو خوارزمية.
اختبارات الأداء: إدخال بيانات عشوائية إلى البرنامج لتجربته تحت ظروف مختلفة.
النماذج الإحصائية: اختيار عينات عشوائية من بيانات كبيرة.
خلط ترتيب العناصر: كأن تعيد ترتيب قائمة من الأسئلة في اختبار.
import random
questions = ['Q1', 'Q2', 'Q3', 'Q4']
random.shuffle(questions)
print("Shuffled questions:", questions)
في المثال أعلاه، يتم خلط ترتيب الأسئلة عشوائيًا. لا يهم إن كانت النتائج قابلة للتكرار أو يمكن التنبؤ بها، لأن الاستخدام غير حساس أمنيًا.
تُستخدم مكتبة secrets
في كل حالة يكون فيها الأمان مطلبًا أساسيًا. أي تطبيق أو نظام يعتمد على التشفير أو حماية المستخدمين أو التحكم في الوصول يجب أن يتجنب تمامًا استخدام random
، ويعتمد بدلاً منها على secrets
.
توليد كلمات مرور للمستخدمين: يجب أن تكون غير قابلة للتنبؤ بأي شكل.
إنشاء رموز تحقق (OTP): تُستخدم في التحقق بخطوتين أو استعادة الحسابات.
توليد رموز الدخول (access tokens): التي تُرسل في الروابط أو رؤوس الطلبات (HTTP headers).
بناء معرفات آمنة للجلسات (session IDs): التي تُستخدم لتحديد هوية المستخدم عند تصفحه للموقع.
توقيع الطلبات أو التوثيق الداخلي: أي حالة تعتمد على "سر" يجب ألا يكون قابلًا للتخمين.
import secrets
token = secrets.token_urlsafe(16)
print("Secure token:", token)
في هذا المثال، يتم توليد رمز دخول آمن يمكن إرساله للمستخدم كجزء من رابط تحقق عبر البريد الإلكتروني. هذا الرمز لا يمكن التنبؤ به حتى لو حاول المهاجم توليد ملايين القيم.
لأن أي رمز تحقق أو كلمة مرور يمكن التنبؤ بها – حتى لو بنسبة ضئيلة – هي ثغرة حقيقية. المهاجم يمكنه كتابة سكربت يجرب القيم الممكنة حتى ينجح، وإذا كانت العشوائية ضعيفة فسيكفيه وقت قصير.
استخدام مكتبة random
في تطبيقات تتعلق بالأمان هو خطأ برمجي جسيم قد يؤدي إلى كارثة أمنية حقيقية. السبب في ذلك أن random
تعتمد على خوارزميات يمكن التنبؤ بها إذا عرف المهاجم أو خمّن القيمة الأولية (seed
). هذه القابلية للتنبؤ تجعل من السهل تنفيذ هجمات مثل:
تخمين كلمات المرور: إذا تم توليدها باستخدام random
، يمكن للمهاجم إعادة توليد نفس التسلسل.
تزوير رموز التحقق أو الدخول: إذا عرف المستخدم نمط القيم الناتجة، قد يتمكن من توليد رموز صالحة بنفسه.
اختراق الجلسات (Session Hijacking): إذا تم إنشاء معرفات الجلسة عبر random
، يمكن التنبؤ بها والوصول إلى حسابات المستخدمين.
افترض أنك كتبت الكود التالي:
import random
def generate_token():
return ''.join(random.choice('abcdef0123456789') for _ in range(16))
في البداية، قد يبدو أن الكود يولد رمزًا عشوائيًا، لكن لو قام المهاجم باختبار عدد كبير من الرموز بناءً على معرفته بطريقة عمل random
، فهناك احتمال كبير أن ينجح في الوصول إلى رمز مستخدم حقيقي، خصوصًا إذا تم استخدام random.seed()
في مكان ما من الكود (ولو حتى غير مقصود).
استخدم مكتبة secrets
كما في المثال الآمن التالي:
import secrets
def generate_token():
return secrets.token_hex(16)
بهذا الشكل، تضمن أن الرمز غير قابل للتنبؤ أو التكرار، حتى من قبل مطورين آخرين أو مستخدمين خبيثين.
القاعدة الذهبية: إذا كان يمكن استغلال العشوائية في اختراق نظامك، لا تستخدم random
.
مكتبة secrets
في بايثون ليست "سحرية"، بل هي مجرد واجهة سهلة الاستخدام تُبسط التعامل مع مصادر العشوائية الآمنة المتوفرة في نظام التشغيل. في خلفيتها، تعتمد secrets
غالبًا على دالة os.urandom()
، والتي بدورها تطلب من نظام التشغيل توليد بايتات عشوائية باستخدام مصادر فيزيائية أو شبه فيزيائية يصعب التنبؤ بها.
os.urandom(n)
هي دالة تُرجع n
بايت من البيانات العشوائية التي تأتي من مصدر موثوق مثل:
/dev/urandom
في أنظمة Linux وUnix.
Crypto API في Windows.
SecureRandom في أنظمة أخرى.
هذه البيانات تُستخدم في تطبيقات التشفير لأنها لا تعتمد على خوارزميات حسابية فقط، بل على مصادر خارجية مثل التوقيتات الدقيقة، حرارة المعالج، تردد الشبكة، وغيرها من المتغيرات غير المتوقعة.
import os
token = os.urandom(16).hex()
print("Secure token:", token)
لكن os.urandom
ترجع بايتات خام، وهو ما يجعل استخدامها غير مريح في معظم السيناريوهات. لذلك جاءت مكتبة secrets
لتغلف هذه العملية وتوفر وظائف مثل:
secrets.token_hex(n)
← تعتمد على os.urandom(n)
secrets.token_urlsafe(n)
← تعتمد على base64
لتمثيل نتيجة os.urandom(n)
secrets.randbelow(n)
← تعتمد على تحويل بايتات os.urandom()
إلى أرقام.
بالتالي، يمكن القول إن مكتبة secrets
هي مجرد واجهة موثوقة وسهلة لاستغلال قوة os.urandom
دون الحاجة للتعامل مع التفاصيل المنخفضة المستوى.
استخدام secrets
يضمن لك أفضل ممارسات الأمان، دون الحاجة لفهم البنية العميقة لأنظمة التشغيل أو كيفية توليد العشوائية فيها.
الفهم الصحيح للفروقات بين مكتبة random
ومكتبة secrets
في بايثون ليس مجرد تمييز تقني، بل هو قرار أمني قد يحمي مشروعك من اختراق محتمل أو كارثة أمنية.
مكتبة random
ممتازة وسريعة وتؤدي الغرض في كل ما هو غير أمني: ألعاب، اختبارات، محاكاة، ترتيب عشوائي… لكنها غير مناسبة إطلاقًا في أي سياق يحتوي على كلمات مرور أو رموز تحقق.
مكتبة secrets
أبطأ قليلًا لكنها توفر عشوائية آمنة لا يمكن التنبؤ بها، وهي الخيار الصحيح لتوليد الرموز، المفاتيح، كلمات المرور، وكل ما له علاقة بحماية البيانات أو هوية المستخدم.
أي خلط بين المكتبتين قد يؤدي إلى عواقب خطيرة، ليس فقط على مستوى الأمان بل على مصداقية مشروعك ككل.
القاعدة البسيطة:
– استخدم random
إذا كنت لا تخشى أن يخمن أحد القيم الناتجة.
– استخدم secrets
إذا كنت لا تريد أن يتمكن أحد من التنبؤ بما ولّدته، حتى لو حاول آلاف أو ملايين المرات.
التشفير لا يُبنى على "يبدو جيدًا"، بل على رياضيات صارمة ومصادر عشوائية موثوقة. ومكتبة secrets
هي السبيل لذلك في بايثون.
تعرف على الفرق الجوهري بين مكتبة random ومكتبة secrets في بايثون، واكتشف متى تستخدم كل واحدة، ولماذا قد يؤدي الاستخدام الخاطئ إلى ثغرات أمنية خطيرة. المقال يشمل أمثلة عملية ومقارنة مباشرة.
مساحة اعلانية
المكتبة في لغة البرمجة هي مجموعة من الأوامر البرمجية المجهزة مسبقا لتنفيذ مهام محددة، تمكنك هذه المكاتب من التعامل معها ضمن مشروعك.
numpy, requests, re
المكتبات في بايثون هي مجموعات من الوحدات والحزم التي توفر أكواد مكتوبة مسبقًا لتنفيذ مهام مختلفة. تساعد في تبسيط عملية البرمجة من خلال توفير دوال وفئات قابلة لإعادة الاستخدام لوظائف محددة، مثل تحليل البيانات، تعلم الآلة، تطوير الويب، والمزيد.
لدى بايثون عدد هائل من المكتبات، مع أكثر من 500,000 حزمة متاحة في فهرس حزم بايثون (PyPI). يستمر هذا العدد في النمو مع تطوير مجتمع بايثون لمكتبات جديدة لتطبيقات متنوعة.