منبع اصلی نوشتار زیر در این لینک قرار دارد

رمزنگاری و رمزگشایی به شیوه نامتقارن در Python

در این مطلب آموزشی قصد داریم تا با استفاده از کتابخانه cryptography ، شیوه رمزنگاری نامتقارن بر اساس RSA را به شما آموزش دهیم.

 

همانند آموزش قبلی با عنوان “رمزنگاری و رمزگشایی متقارن در زبان پایتون” ، در این مطلب هم از ماژول cryptography استفاده خواهیم کرد و ساخت کلیدهای نامتقارن و ذخیره و بازیابی آنها را یاد می گیریم. در نهایت هم از این شیوه برای رمزنگاری پیام ها و متون استفاده خواهیم کرد.

نصب کتابخانه cryptography

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

برای نصب کتابخانه cryptography دستور زیر را اجرا کنید:

python -m pip install cryptography

برای اطمینان از نصب صحیح این کتابخانه دستور زیر را در IDLE اجرا کنید:

import cryptography

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

رمزنگاری نامتقارن چیست؟

اگر از وبسایت ما مطلب “رمزنگاری و رمزگشایی متقارن در زبان پایتون” را خوانده باشید، دیده اید که در رمزنگاری مقارن فقط و فقط یک کلید برای هر دو عمل رمزنگاری و رمزگشایی استفاده می شود.

اما در روش رمزنگاری نامتقارن دو کلید خواهیم داشت، یکی با نام کلید خصوصی و دیگری با نام کلید عمومی.

کلیدهای عمومی برای استفاده همه منتشر و آزاد می شوند. هر کسی با داشتن کلید عمومی، می تواند اطلاعات را رمزنگاری کند و بفرستد؛ اما تنهایی کسانی که کلید خصوصی را داشته باشند، می تواند عمل رمزگشایی آن اطلاعات را انجام دهند و داده اصلی را مشاهده کنند.

تا به اینجای کار ایده اصلی رمزنگاری نامتقارن را متوجه شده اید و حتماً به ذهنتان خطور کرده که لازمه امنیت این رمزنگاری آن است که کلید خصوصی را به صورت امن و خصوصی نگهداری کنید.

به دست آوردن کلید رمز نامتقارن

برای تولید دو کلید عمومی و خصوصی رمزنگاری نامتقارن، ما از ماژول rsa که در cryptography.hazmat.primitives.asymmetric تعریف شده است استفاده می کنیم و تابع generate_private_key آن را صدا می زنیم؛ پس از ساخت کلید خصوصی، کلید عمومی را هم از همان کلید خصوصی استخراج می کنیم.

به کد زیر دقت کنید تا تولید کلید برای شما روشن شود:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)
public_key = private_key.public_key()

 

ذخیره کلید رمز

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

به کد زیر که یک نمونه کلید خصوصی از قبل ساخته شده را در فایل باینری ذخیره می کند، دقت کنید:

from cryptography.hazmat.primitives import serialization
private_key = ... # Placeholder - you generated this before

pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)

with open('private_key.pem', 'wb') as f:
    f.write(pem)

برای مطالعه درباره امنیت بیشتر این فایل و تخصیص رمز عبور برای آن، به مثال موجود در این لینک مراجعه کنید.

 

ذخیره کردن کلید عمومی هم با اندکی تغییر در فرمت، به شکل زیر انجام می شود:

from cryptography.hazmat.primitives import serialization
public_key = ... # Placeholder - you generated this before

pem = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)

with open('public_key.pem', 'wb') as f:
    f.write(pem)

خواندن و بارگذاری کلید

برای بارگذاری کلیدها از روی فایل ها جداگانه، طبیعتاً لازم است تا هر فایل را به شیوه مخصوص خودش بخوانید.

برای خواندن کلیدها از ماژول serialization که در cryptography.hazmat.primitives تعریف شده استفاده می کنیم و از درون این ماژول، توابع load_pem_private_key و load_pem_public_key را صدا می زنیم.

کد زیر برای خواندن کلید خصوصی از فایل باینری “private_key.pem” نوشته شده است. دقت کنید که فرض بر این بوده که فایل کلید رمز عبور جداگانه ای نداشته است.

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

with open("private_key.pem", "rb") as key_file:
    private_key = serialization.load_pem_private_key(
        key_file.read(),
        password=None,
        backend=default_backend()
    )

اگر برای محافظت بیشتر از فایل، رمز عبوری برای آن تنظیم کرده اید، مقدار رمز را جلوی آرگومان password وارد کنید.

 

بازیابی کلید عمومی هم به صورت زیر انجام می شود:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

with open("public_key.pem", "rb") as key_file:
    public_key = serialization.load_pem_public_key(
        key_file.read(),
        backend=default_backend()
    )

 

رمزگذاری اطلاعات

جالب است بدانید که به دلیل تعریف عملکرد رمزنگاری RSA ، شما می توانید داده ها را با هر کدام از کلید هایی که می خواهید رمز کنید و با کلید دیگر آن را رمزگشایی کنید. با همین ایده و با استفاده از رمزنگاری نامتقارن، می توان کاربردهایی مانند امضای دیجیتال و تایید هویت را به وجود آورد.

برای کد زیر، فرض می کنیم که برنامه شما عملکرد روی شبکه ندارد و به صورت local کار می کنید و هر دو کلید را به طور امن نگهداری می کنید و آنها منتشر نخواهند شد.

پس اگر کلیدها نزد خودتان محفوظ باشید می توانید با هر کدام که خواسنید رمزنگاری کنید و با دیگری هم رمزگشایی کنید. اما در این کد رمزنگاری با کلید عمومی انجام می شود (و رمزگشایی با کلید خصوصی باید انجام شود که در بخش بعدی می بینید):

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

message = b'encrypt me!'
public_key = ... # Use one of the methods above to get your public key

encrypted = public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

 

رمزگشایی

طبق کد بخش قبل، با فرض انجام عملیات رمزنگاری با استفاده از کلید عمومی، در ادامه کدی نوشته ایم که رمزگشایی را با کمک کلید خصوصی انجام می دهد:

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

encrypted = ... # From before (could have been stored then read back here)
private_key = ... # Use one of the methods above to get your public key (matches the public_key)

original_message = private_key.decrypt(
    encrypted,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

 

یک نمونه کامل از رمزنگاری و رمزگشایی نامتقارن

برای سر هم کردن همه مواردی که از قبل دیده اید، به مثال کامل زیر دقت کنید. در این مثال توجه به خروجی دستورات به شما کمک می کند تا عملکرد رمزنگاری در پایتون با کتابخانه های معرفی شده را بهتر درک کنید.

# Generating a key
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
>>> public_key = private_key.public_key()

# Storing the keys
>>> from cryptography.hazmat.primitives import serialization
>>> pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption()
    )
>>> with open('private_key.pem', 'wb') as f:
    f.write(pem)
>>>
>>> pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
>>> with open('public_key.pem', 'wb') as f:
    f.write(pem)

# Reading the keys back in (for demonstration purposes)
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import serialization
>>> with open("private_key.pem", "rb") as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
>>> with open("public_key.pem", "rb") as key_file:
        public_key = serialization.load_pem_public_key(
            key_file.read(),
            backend=default_backend()
        )

# Encrypting and decrypting
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import padding
>>>
>>> message = b'encrypt me!'
>>> encrypted = public_key.encrypt(
        message,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
>>> original_message = private_key.decrypt(
        encrypted,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )

# Checking the results
>>> original_message
b'encrypt me!'
>>> message == original_message
True

 

 

منبع : Asymmetric Encryption and Decryption in Python

نوشته رمزنگاری و رمزگشایی به شیوه نامتقارن در Python اولین بار در اوپن مایند. پدیدار شد.



برچسب ها :