ساخت مدیر پسورد امن پایتون؛ رمزنگاری محلی و آفلاین

ساخت یک مدیر رمز عبور امن، سبک و آفلاین شخصی با پایتون. یاد بگیرید چگونه پسوردها را با الگوریتم AES و کتابخانه cryptography محافظت کنید.

🎧 خلاصه صوتی مقاله (پادکست ۲ دقیقه‌ای):

فرصت مطالعه ندارید؟ چکیده این مطلب را همین‌جا گوش دهید:

مدیریت و به خاطر سپردن ده‌ها کلمه عبور مختلف برای وب‌سایت‌ها و سرویس‌های گوناگون، یکی از چالش‌های روزمره کاربران فضای دیجیتال است. بسیاری از افراد برای حل این مشکل به سرویس‌های ابری آنلاین متکی می‌شوند، اما نگرانی درباره حریم خصوصی و امنیت سرورهای شخص ثالث همواره وجود دارد. اگر به دنبال یک راهکار کاملاً مستقل، امن، آفلاین و شخصی هستید، ساخت یک ابزار اختصاصی با زبان برنامه‌نویسی پایتون بهترین گزینه است. در این مقاله یاد می‌گیرید چگونه یک مدیر رمز عبور امن و سبک بسازید که اطلاعات حساس شما را درون یک فایل محلی با الگوریتم‌های استاندارد رمزنگاری محافظت کند؛ به‌طوری‌که بدون داشتن کلمه عبور اصلی (Master Password)، هیچ‌كس حتی با دسترسی به فایل پایگاه داده قادر به خواندن محتوای آن نباشد.

ویژگیمقدار
زبان برنامه‌نویسیپایتون (Python 3.x)
کتابخانه اصلی رمزنگاریcryptography
نوع رمزنگاریمتقارن AES-256 و کلید مشتق‌شده از پسورد (PBKDF2HMAC)
محیط ذخیره‌سازیمحلی و آفلاین (فایل JSON رمزنگاری شده)
هزینه۱۰۰٪ رایگان و متن‌باز
وضعیت دسترسی ایرانبدون محدودیت

مسئله: چرا مدیریت دستی پسوردها خطرناک است؟

یکی از بزرگ‌ترین اشتباهات رایج کاربران، استفاده از یک کلمه عبور ساده و تکراری برای تمامی حساب‌های کاربری است. هنگامی که یک سایت کوچک هک شود، هکرها می‌توانند با تست کردن همان پسورد در ایمیل، شبکه‌های اجتماعی و حساب‌های بانکی شما، به راحتی به اطلاعاتتان دسترسی پیدا کنند. از طرف دیگر، یادداشت کردن پسوردها روی کاغذ یا فایل‌های متنی ساده (Text File) روی دسکتاپ، دعوتنامه‌ای آشکار برای هر فردی است که به سیستم شما نگاه می‌کند.

در پروژه‌های نرم‌افزاری و بررسی ساختارهای داده امن، همان‌طور که در بررسی ابزارهای تحلیلی مثل معرفی ابزار WordCounter؛ تحلیلگر حرفه‌ای متن و چگالی کلمات کلیدی دیده‌ایم، پردازش و ساختاردهی دقیق داده‌ها اهمیت بالایی دارد. در حوزه امنیت نیز باید داده‌ها پیش از ذخیره‌سازی کاملاً مبدل و غیرقابل خواندن شوند. راهکار ما ساخت یک اسکریپت پایتون است که داده‌ها را پیش از نوشتن روی دیسک رمزگذاری کند.

نصب کتابخانه‌های مورد نیاز

برای پیاده‌سازی این سیستم رمزنگاری قدرتمند، به کتابخانه استاندارد و امن cryptography در پایتون نیاز داریم. این کتابخانه استانداردهای صنعتی رمزنگاری را پیاده‌سازی می‌کند. برای نصب آن، ترمینال یا خط فرمان سیستم خود را باز کرده و دستور زیر را اجرا کنید:

pip install cryptography

پس از اتمام نصب، پایتون آماده اجرای کدهای رمزنگاری پیشرفته خواهد بود. این کتابخانه نیازی به ابزارهای جانبی پیچیده ندارد و کاملاً مستقل کار می‌کند.

کد کامل و اجرایی مدیر پسورد محلی

اسکریپت زیر یک برنامه کامل و کاربردی است که به شما اجازه می‌دهد یک پایگاه داده محلی بسازید، کلمه عبور اصلی تعیین کنید، اطلاعات حساب‌های جدید را اضافه کنید و با وارد کردن کلمه عبور اصلی، آن‌ها را بازیابی نمایید. این کد را در یک فایل با نام pass_manager.py ذخیره کنید:

import os
import json
import base64
from getpass import getpass
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.fernet import Fernet

DB_FILE = "secure_vault.json"
SALT_FILE = "salt.bin"

def generate_key(master_password: str, salt: bytes) -> bytes:
    """تولید کلید رمزنگاری امن بر اساس پسورد اصلی و نمک (Salt)"""
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=480000,
    )
    key = base64.urlsafe_b64encode(kdf.derive(master_password.encode()))
    return key

def initialize_vault():
    """راه‌اندازی اولیه پایگاه داده و دریافت پسورد اصلی"""
    if not os.path.exists(SALT_FILE):
        print("--- راه‌اندازی اولیه مدیر پسورد ---")
        master_pass = getpass("یک کلمه عبور اصلی (Master Password) قوی وارد کنید: ")
        confirm_pass = getpass("تکرار کلمه عبور اصلی: ")
        
        if master_pass != confirm_pass:
            print("خطا: کلمه‌های عبور مطابقت ندارند.")
            exit(1)
            
        salt = os.urandom(16)
        with open(SALT_FILE, "wb") as f:
            f.write(salt)
            
        empty_data = {}
        key = generate_key(master_pass, salt)
        f = Fernet(key)
        encrypted_data = f.encrypt(json.dumps(empty_data).encode())
        
        with open(DB_FILE, "wb") as f:
            f.write(encrypted_data)
            
        print("پایگاه داده با موفقیت ایجاد و امن‌سازی شد!")
    else:
        print("پایگاه داده از قبل موجود است.")

def load_vault(master_password: str) -> dict:
    """بارگذاری و رمزگشایی پایگاه داده با پسورد اصلی"""
    if not os.path.exists(SALT_FILE) or not os.path.exists(DB_FILE):
        print("خطا: پایگاه داده یافت نشد. ابتدا برنامه را راه‌اندازی کنید.")
        exit(1)
        
    with open(SALT_FILE, "rb") as f:
        salt = f.read()
        
    key = generate_key(master_password, salt)
    f = Fernet(key)
    
    with open(DB_FILE, "rb") as db:
        encrypted_data = db.read()
        
    try:
        decrypted_data = f.decrypt(encrypted_data)
        return json.loads(decrypted_data.decode())
    except Exception:
        print("خطا: کلمه عبور اصلی اشتباه است یا فایل آسیب دیده است.")
        exit(1)

def save_vault(data: dict, master_password: str):
    """ذخیره و رمزگذاری مجدد داده‌ها در فایل محلی"""
    with open(SALT_FILE, "rb") as f:
        salt = f.read()
        
    key = generate_key(master_password, salt)
    f = Fernet(key)
    
    encrypted_data = f.encrypt(json.dumps(data).encode())
    with open(DB_FILE, "wb") as db:
        db.write(encrypted_data)

def add_password(master_password: str):
    """افزودن حساب کاربری و پسورد جدید"""
    data = load_vault(master_password)
    service = input("نام سرویس یا وب‌سایت (مثلا github.com): ").strip()
    username = input("نام کاربری یا ایمیل: ").strip()
    password = getpass("کلمه عبور آن حساب: ")
    
    data[service] = {
        "username": username,
        "password": password
    }
    
    save_vault(data, master_password)
    print(f"اطلاعات مربوط به {service} با موفقیت ذخیره شد.")

def get_password(master_password: str):
    """بازیابی و نمایش پسورد یک سرویس خاص"""
    data = load_vault(master_password)
    service = input("نام سرویس مورد نظر برای جستجو: ").strip()
    
    if service in data:
        print(f"\n--- اطلاعات حساب {service} ---")
        print(f"نام کاربری: {data[service]['username']}")
        print(f"کلمه عبور: {data[service]['password']}")
        print("-" * 30)
    else:
        print("خطا: این سرویس در پایگاه داده ثبت نشده است.")

def main():
    initialize_vault()
    
    while True:
        print("\nمنوی اصلی:")
        print("1. افزودن پسورد جدید")
        print("2. بازیابی پسورد")
        print("3. خروج")
        
        choice = input("انتخاب شما (1 تا 3): ").strip()
        
        if choice == '1':
            master_pass = getpass("کلمه عبور اصلی را وارد کنید: ")
            add_password(master_pass)
        elif choice == '2':
            master_pass = getpass("کلمه عبور اصلی را وارد کنید: ")
            get_password(master_pass)
        elif choice == '3':
            print("خروج از برنامه. روز خوش!")
            break
        else:
            print("گزینه نامعتبر. لطفاً دوباره تلاش کنید.")

if __name__ == "__main__":
    main()

توضیح بخش‌به‌بخش کد و نحوه عملکرد

این اسکریپت بر پایه چند مفهوم کلیدی امنیتی طراحی شده است که در ادامه هر بخش را بررسی می‌کنیم:

  • تولید کلید امن (PBKDF2HMAC): ما کلمه عبور متنی ساده‌ای که شما وارد می‌کنید را مستقیماً به عنوان کلید رمزنگاری استفاده نمی‌کنیم. بلکه با استفاده از تابع مشتق‌ساز کلید و یک مقدار تصادفی به نام Salt که در فایل جداگانه‌ای ذخیره می‌شود، کلید رمزنگاری ۲۵۶ بیتی منحصربه‌فردی می‌سازیم. این کار مانع از حملات دیکشنری می‌شود.
  • رمزنگاری متقارن Fernet: کتابخانه cryptography.fernet از استاندارد رمزنگاری AES در حالت CBC با کلید HMAC استفاده می‌کند. این یعنی امنیت داده‌ها تضمین شده است و هیچ‌کس بدون کلید نمی‌تواند فایل secure_vault.json را بخواند.
  • مدیریت فایل‌ها: ساختار داده‌ها در قالب یک دیکشنری پایتون ذخیره شده و سپس به فرمت JSON تبدیل و رمزگذاری می‌شود. فایل خروجی فقط شامل بایت‌های درهم‌ریخته خواهد بود.

نحوه اجرا و سناریوی استفاده

برای اجرای این اسکریپت، کافی است مراحل زیر را دنبال کنید:

  1. کد بالا را در فایلی به نام pass_manager.py ذخیره کنید.
  2. ترمینال را در پوشه حاوی فایل باز کرده و دستور زیر را بنویسید:
    python pass_manager.py
  3. در اولین اجرا، برنامه از شما می‌خواهد یک کلمه عبور اصلی قدرتمند تعیین کنید. این پسورد را هرگز نباید فراموش کنید، چون راهی برای بازیابی آن وجود ندارد.
  4. پس از تعیین پسورد، منوی تعاملی باز می‌شود که می‌توانید با انتخاب گزینه ۱، اطلاعات ورود سایت‌های خود را اضافه کنید و با گزینه ۲ در هر زمان آن‌ها را استخراج کنید.

ایده‌های توسعه و شخصی‌سازی پیشرفته

شما می‌توانید این اسکریپت ساده را برای کاربردهای حرفه‌ای‌تر گسترش دهید:

  • افزودن قابلیت تولید پسورد تصادفی: تابعی بنویسید که کلمات عبور بسیار پیچیده شامل حروف بزرگ، کوچک، اعداد و نمادها تولید کند.
  • خروجی گرفتن پشتیبان امن: امکان کپی گرفتن خودکار یا فشرده‌سازی فایل‌های secure_vault.json و salt.bin را به اسکریپت اضافه کنید.
  • رابط گرافیکی یا تحت وب: با استفاده از کتابخانه‌های سبک مانند Tkinter یا فریم‌ورک‌های وب کوچک، یک محیط کاربری بصری برای آن بسازید.

خطاهای رایج و راه‌حل آن‌ها

هنگام کار با ابزارهای رمزنگاری محلی، ممکن است با چند خطای پرتکرار مواجه شوید:

  • خطای اشتباه بودن کلمه عبور اصلی: اگر پسورد اصلی را فراموش کنید، تابع decrypt در کتابخانه Fernet با استثنای InvalidToken مواجه می‌شود. در کد ما این خطا مدیریت شده و پیام هشدار چاپ می‌شود. راهکار: دقت در ورود پسورد؛ در صورت گم شدن پسورد، فایل‌های پایگاه داده و نمک باید پاک شوند و از نو شروع کنید.
  • حذف تصادفی فایل Salt: فایل salt.bin کلیدِ ارتباطی بین پسورد شما و فایل رمزنگاری شده است. اگر این فایل پاک شود، حتی با داشتن پسورد اصلی نیز قادر به باز کردن داده‌های خود نخواهید بود. حتماً از این دو فایل کنار هم پشتیبان تهیه کنید.

پرسش‌های متداول

اگر فایل‌های دیتابیس یا نمک پاک شوند چه اتفاقی می‌افتد؟

تمام اطلاعات ذخیره‌شده غیرقابل بازیابی خواهند بود. فلسفه امنیت این ابزار دقیقاً همین است؛ هیچ درب پشتی (Backdoor) یا سرور مرکزی وجود ندارد که اطلاعات شما را بازیابی کند.

آیا این اسکریپت روی سیستم‌عامل‌های مختلف کار می‌کند؟

بله، چون به زبان پایتون نوشته شده و از کتابخانه استاندارد cryptography استفاده می‌کند، روی ویندوز، لینوکس و مک‌بوک بدون هیچ مشکلی اجرا می‌شود.

چرا پسوردها به صورت متن ساده در دیکشنری پایتون ذخیره می‌شوند؟

پسوردها فقط در حافظه موقت (RAM) سیستم شما و هنگامی که برنامه باز است و پسورد اصلی را وارد کرده‌اید به صورت متن ساده در دسترس هستند. اما روی دیسک سخت و درون فایل، کل داده‌ها به طور کامل رمزنگاری شده‌اند.

تعداد تکرار تابع PBKDF2 چیست و چرا ۴۸۰۰۰۰ انتخاب شده است؟

تعداد تکرارها (Iterations) مشخص می‌کند که الگوریتم مشتق‌سازی چقدر باید زمان صرف کند تا از پسورد شما کلید بسازد. مقدار بالا باعث می‌شود حملاتِ حدس پسورد (Brute-force) بسیار کند و عملاً غیرممکن شوند.

جمع‌بندی

ساخت یک مدیر رمز عبور محلی با پایتون نه تنها تسلط شما را بر مفاهیم کلیدی رمزنگاری و امنیت داده‌ها افزایش می‌دهد، بلکه کنترل کامل حریم خصوصیتان را در اختیارتان می‌گذارد. با استفاده از کتابخانه cryptography و الگوریتم AES، داده‌های حساس شما در برابر دسترسی‌های غیرمجاز کاملاً ایمن خواهند بود. این اسکریپت سبک، سریع و بدون نیاز به اینترنت، همراهی مطمئن برای مدیریت حساب‌های کاربری شماست.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *