دليل شامل لـ sha2 / bcrypt في Rust مع أمثلة عملية

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

sha2 / bcrypt في Rust: دليل شامل مع أمثلة

في تطوير البرمجيات الحديث، تُعد أمان البيانات جانبًا حاسمًا في أي تطبيق. توفر مكتبتا sha2 و bcrypt للغة Rust أدوات قوية وآمنة للتجزئة التشفيرية (Cryptographic Hashing). sha2 تنفذ عائلة خوارزميات SHA-2 (خوارزمية التجزئة الآمنة 2)، بما في ذلك SHA-224 و SHA-256 و SHA-384 و SHA-512، بالإضافة إلى متغيراتها المقتطعة (SHA-512/224 و SHA-512/256). bcrypt هي دالة تجزئة تشفيرية تكيفية، مصممة خصيصًا لتخزين كلمات المرور بشكل آمن. تستخدم "ملحًا" (Salt) وعددًا قابلاً للتعديل من الجولات (Cost Factor)، مما يجعلها مقاومة لهجمات جداول قوس قزح (Rainbow Tables) وهجمات القوة العمياء (Brute Force).

لماذا تحتاج هذا؟ تُستخدم SHA-2 للتحقق من سلامة البيانات، وإنشاء التوقيعات الرقمية، وفي أنظمة التحكم في الإصدارات (Git)، وسلسلة الكتل (Blockchain)، والعديد من المجالات الأخرى التي تتطلب تجزئة سريعة وموثوقة. أما Bcrypt، فهي المعيار الفعلي (De Facto) لتجزئة كلمات المرور في تطبيقات الويب، وقواعد البيانات، وأنظمة المصادقة. ميزتها الرئيسية هي "البطء" القابل للتعديل: يمكنك زيادة عدد الجولات لتعويض الزيادة في القوة الحاسوبية للمهاجمين.

في هذه المقالة، سنستعرض بالتفصيل كلتا المكتبتين: التثبيت، والطرق الأساسية، وأمثلة استخدام عملية، والأخطاء الشائعة. ستتعلم كيفية تجزئة البيانات بشكل صحيح، والتحقق من كلمات المرور، ودمج هذه الوظائف في مشاريع Rust الخاصة بك.

التثبيت

لاستخدام sha2 و bcrypt في Rust، يجب إضافتهما إلى ملف Cargo.toml الخاص بمشروعك. افتح الطرفية (Terminal) في الدليل الجذر للمشروع ونفّذ الأمر التالي:

cargo add sha2 bcrypt

سيضيف هذا الأمر أحدث إصدارات المكتبات إلى قسم [dependencies]. بدلاً من ذلك، يمكنك تحرير ملف Cargo.toml يدويًا:

[dependencies]
sha2 = "0.10"
bcrypt = "0.15"

بعد ذلك، نفّذ الأمر cargo build لتحميل التبعيات والتأكد من أن كل شيء مثبت بشكل صحيح.

بداية سريعة: مثال عملي مصغر

لنبدأ بمثال بسيط: تجزئة نص باستخدام SHA-256 والتحقق من كلمة مرور باستخدام bcrypt.

use sha2::{Sha256, Digest};
use bcrypt::{hash, verify, DEFAULT_COST};

fn main() {
    // تجزئة SHA-256
    let data = b"Hello, world!";
    let mut hasher = Sha256::new();
    hasher.update(data);
    let result = hasher.finalize();
    println!("SHA-256 هاش: {:x}", result);

    // تجزئة كلمة مرور باستخدام Bcrypt
    let password = "my_secure_password";
    let hashed = hash(password, DEFAULT_COST).unwrap();
    println!("Bcrypt هاش: {}", hashed);

    // التحقق من كلمة المرور
    let is_valid = verify(password, &hashed).unwrap();
    println!("كلمة المرور صحيحة: {}", is_valid);
}

يوضح هذا الكود الإمكانيات الأساسية لكلتا المكتبتين. ستحتوي المخرجات على هاش SHA-256 سداسي عشري (Hex) مكون من 64 حرفًا وسلسلة طويلة من bcrypt (تبدأ بـ $2b$).

الطرق والوظائف الأساسية

دعنا نستعرض الوظائف والطرق الرئيسية من sha2 و bcrypt. لكل منها، سنقدم التوقيع (Signature)، والوصف، ومثال عملي.

1. sha2::Sha256::new()

التوقيع: pub fn new() -> Sha256

الوصف: ينشئ مثيلًا جديدًا من هاش SHA-256. هذه هي نقطة البداية لتجزئة البيانات.

use sha2::{Sha256, Digest};

let mut hasher = Sha256::new();
hasher.update(b"test data");
let hash = hasher.finalize();
println!("{:x}", hash);

2. sha2::Sha256::update()

التوقيع: pub fn update(&mut self, data: impl AsRef<[u8]>)

الوصف: يُغذي الهاش بالبيانات المراد تجزئتها. يمكن استدعاؤه عدة مرات لتجزئة بيانات متدفقة.

use sha2::{Sha256, Digest};

let mut hasher = Sha256::new();
hasher.update(b"part1");
hasher.update(b"part2");
let hash = hasher.finalize();
println!("{:x}", hash);

3. sha2::Sha256::finalize()

التوقيع: pub fn finalize(self) -> GenericArray<u8, U32>

الوصف: يُنهي عملية التجزئة ويعيد قيمة الهاش النهائية كمصفوفة بايتات. بعد الاستدعاء، لا يمكن استخدام الهاشر مرة أخرى.

use sha2::{Sha256, Digest};

let mut hasher = Sha256::new();
hasher.update(b"data");
let hash = hasher.finalize();
println!("{:x}", hash);

4. bcrypt::hash()

التوقيع: pub fn hash<S: AsRef<str>>(password: S, cost: u32) -> Result<String, BcryptError>

الوصف: يُجزئ كلمة المرور باستخدام bcrypt مع عدد محدد من الجولات (Cost). كلما زاد العدد، زاد الأمان ولكن أيضًا زاد وقت المعالجة. القيمة الافتراضية هي DEFAULT_COST (12).

use bcrypt::{hash, DEFAULT_COST};

let hashed = hash("my_password", DEFAULT_COST).unwrap();
println!("{}", hashed);

5. bcrypt::verify()

التوقيع: pub fn verify<S: AsRef<str>>(password: S, hash: S) -> Result<bool, BcryptError>

الوصف: يتحقق مما إذا كانت كلمة المرور تتطابق مع الهاش المخزن. تُعيد true إذا تطابقت، و false إذا لم تتطابق.

use bcrypt::{hash, verify, DEFAULT_COST};

let hashed = hash("my_password", DEFAULT_COST).unwrap();
let is_valid = verify("my_password", &hashed).unwrap();
println!("صحيح: {}", is_valid);

أمثلة عملية متقدمة

فيما يلي مثال أكثر تقدمًا يوضح كيفية استخدام المكتبتين معًا في تطبيق حقيقي، مثل نظام تسجيل دخول بسيط:

use sha2::{Sha256, Digest};
use bcrypt::{hash, verify, DEFAULT_COST};
use std::collections::HashMap;

fn main() {
    // محاكاة قاعدة بيانات المستخدمين
    let mut users: HashMap<String, String> = HashMap::new();

    // تسجيل مستخدم جديد
    let username = "user1";
    let password = "secure_password_123";
    let hashed_password = hash(password, DEFAULT_COST).unwrap();
    users.insert(username.to_string(), hashed_password);

    // التحقق من تسجيل الدخول
    let login_username = "user1";
    let login_password = "secure_password_123";
    if let Some(stored_hash) = users.get(login_username) {
        if verify(login_password, stored_hash).unwrap() {
            println!("تم تسجيل الدخول بنجاح!");
        } else {
            println!("كلمة المرور غير صحيحة.");
        }
    } else {
        println!("المستخدم غير موجود.");
    }

    // استخدام SHA-256 للتحقق من سلامة البيانات
    let file_data = b"important file content";
    let mut hasher = Sha256::new();
    hasher.update(file_data);
    let file_hash = hasher.finalize();
    println!("هاش الملف: {:x}", file_hash);
}

الأخطاء الشائعة ونصائح الأداء

  • نسيان استيراد Digest trait: تأكد من استيراد use sha2::Digest; لاستخدام طرق update() و finalize().
  • استخدام cost عالية جدًا: القيمة الافتراضية DEFAULT_COST (12) مناسبة لمعظم التطبيقات. تجنب استخدام قيم أعلى من 15 إلا إذا كنت تعرف ما تفعله، لأنها قد تبطئ التطبيق بشكل كبير.
  • عدم تخزين كلمات المرور كنص عادي: استخدم دائمًا bcrypt أو Argon2 لتجزئة كلمات المرور. لا تستخدم SHA-2 لتخزين كلمات المرور لأنه سريع جدًا وسهل الاختراق.
  • إعادة استخدام مثيل الهاشر: بعد استدعاء finalize()، لا يمكن إعادة استخدام مثيل Sha256. أنشئ مثيلًا جديدًا لكل عملية تجزئة.

الخلاصة

في هذا الدليل، تعلمت كيفية استخدام مكتبتي sha2 و bcrypt في Rust. sha2 مثالية للتحقق من سلامة البيانات والتوقيعات الرقمية، بينما bcrypt هي الخيار الأمثل لتخزين كلمات المرور بأمان. تذكر دائمًا استخدام bcrypt لكلمات المرور، واختيار عدد جولات مناسب، وتحديث التبعيات بانتظام للحصول على أحدث التحسينات الأمنية. ابدأ الآن في تطبيق هذه المفاهيم في مشاريع Rust الخاصة بك!

توصيات