পাইথনের কোনও বিল্ট-ইন এনক্রিপশন স্কিম নেই, নেই। আপনার এনক্রিপ্ট করা ডেটা স্টোরেজটিকে গুরুতরভাবে নেওয়া উচিত; একটি বিকাশকারী অনিরাপদ হতে বুঝতে টিউভিয়াল এনক্রিপশন স্কিমগুলি এবং একটি খেলনা স্কিম কম অভিজ্ঞ বিকাশকারী দ্বারা একটি সুরক্ষিত স্কিমের জন্য ভালই ভুল হতে পারে। আপনি যদি এনক্রিপ্ট করেন তবে সঠিকভাবে এনক্রিপ্ট করুন।
সঠিক এনক্রিপশন স্কিমটি প্রয়োগ করতে আপনার খুব বেশি কাজ করার দরকার নেই। প্রথমত, ক্রিপ্টোগ্রাফি হুইলটি পুনরায় উদ্ভাবন করবেন না , এটি আপনার জন্য পরিচালনা করতে একটি বিশ্বস্ত ক্রিপ্টোগ্রাফি লাইব্রেরি ব্যবহার করুন। পাইথন 3 এর জন্য, এটি নির্ভরযোগ্য লাইব্রেরিcryptography
।
আমি এও প্রস্তাব দিচ্ছি যে এনক্রিপশন এবং ডিক্রিপশন বাইটগুলিতে প্রযোজ্য ; প্রথমে বাইটগুলিতে পাঠ্য বার্তাগুলি এনকোড করুন; stringvalue.encode()
ইউটিএফ 8 এ এনকোডগুলি ব্যবহার করে সহজেই আবার ফিরানো হয়েছে bytesvalue.decode()
।
সর্বশেষে তবে অন্তত নয়, এনক্রিপ্ট করা এবং ডিক্রিপ্ট করার সময়, আমরা পাসওয়ার্ড নয়, কীগুলির বিষয়ে কথা বলি । একটি কী মানুষের স্মরণীয় হওয়া উচিত নয়, এটি এমন একটি জিনিস যা আপনি কোনও গোপন স্থানে সংরক্ষণ করেন তবে মেশিনটি পাঠযোগ্য, আপনি পারেন একটু যত্ন নিয়ে পাসওয়ার্ড থেকে একটি কী অর্জন ।
তবে কোনও ওয়েব অ্যাপ্লিকেশন বা কোনও ক্লাস্টারে চলছে এমন প্রক্রিয়া যাতে মানুষের মনোযোগ ছাড়াই এটি চালিয়ে যায়, আপনি একটি কী ব্যবহার করতে চান। পাসওয়ার্ডগুলি তখনই যখন কোনও শেষ-ব্যবহারকারীর নির্দিষ্ট তথ্যে অ্যাক্সেসের প্রয়োজন হয়। তারপরেও আপনি সাধারণত পাসওয়ার্ড দিয়ে অ্যাপ্লিকেশনটি সুরক্ষিত করেন, তারপরে কোনও কী ব্যবহার করে এনক্রিপ্ট করা তথ্যের বিনিময় করুন, সম্ভবত এটি ব্যবহারকারীর অ্যাকাউন্টে সংযুক্ত একটি one
প্রতিসম কী কী এনক্রিপশন
ফার্নেট - এইএস সিবিসি + এইচএমএসি, দৃ strongly়ভাবে প্রস্তাবিত
cryptography
গ্রন্থাগার রয়েছে Fernet রেসিপি , ক্রিপ্টোগ্রাফি ব্যবহার করার জন্য বেস্ট চর্চা রেসিপি। ফার্নেট একটি ওপেন স্ট্যান্ডার্ড , বিস্তৃত প্রোগ্রামিং ভাষাগুলিতে প্রস্তুত বাস্তবায়ন রয়েছে এবং এটি আপনার জন্য সংস্করণ তথ্য, একটি টাইমস্ট্যাম্প এবং একটি এইচএমএসি স্বাক্ষর সহ বার্তাপ্রাপ্তি রোধে AES সিবিসি এনক্রিপশন প্যাকেজ করে।
ফার্নেট বার্তা এবং এনক্রিপ্ট এবং ডিক্রিপ্ট করা খুব সহজ করে তোলে আপনাকে সুরক্ষিত রাখা । এটি একটি গোপনের সাথে ডেটা এনক্রিপ্ট করার জন্য আদর্শ পদ্ধতি।
আমি আপনাকে Fernet.generate_key()
একটি নিরাপদ কী উত্পন্ন করতে ব্যবহার করার পরামর্শ দিচ্ছি । আপনি একটি পাসওয়ার্ডও (পরবর্তী বিভাগ) ব্যবহার করতে পারেন, তবে একটি সম্পূর্ণ 32-বাইট গোপন কী (স্বাক্ষর করার জন্য 16 বাইটস, আরও একটি স্বাক্ষর জন্য 16 টি) আপনার মনে হতে পারে এমন বেশিরভাগ পাসওয়ার্ডের চেয়ে আরও সুরক্ষিত হতে চলেছে।
ফার্নেট যে কী উত্পন্ন করে তা হ'ল bytes
ইউআরএল এবং ফাইল নিরাপদ বেস 64 অক্ষর যুক্ত একটি বস্তু, তাই মুদ্রণযোগ্য:
from cryptography.fernet import Fernet
key = Fernet.generate_key() # store in a secure location
print("Key:", key.decode())
বার্তাগুলি এনক্রিপ্ট বা ডিক্রিপ্ট করতে, Fernet()
প্রদত্ত কীটি দিয়ে একটি উদাহরণ তৈরি করুন এবং কল করুন Fernet.encrypt()
বা Fernet.decrypt()
, উভয়কে এনক্রিপ্ট করার জন্য সরলখর বার্তা এবং এনক্রিপ্ট করা টোকেন bytes
অবজেক্ট are
encrypt()
এবং decrypt()
ফাংশনগুলি দেখতে হবে:
from cryptography.fernet import Fernet
def encrypt(message: bytes, key: bytes) -> bytes:
return Fernet(key).encrypt(message)
def decrypt(token: bytes, key: bytes) -> bytes:
return Fernet(key).decrypt(token)
ডেমো:
>>> key = Fernet.generate_key()
>>> print(key.decode())
GZWKEhHGNopxRdOHS4H4IyKhLQ8lwnyU7vRLrM3sebY=
>>> message = 'John Doe'
>>> encrypt(message.encode(), key)
'gAAAAABciT3pFbbSihD_HZBZ8kqfAj94UhknamBuirZWKivWOukgKQ03qE2mcuvpuwCSuZ-X_Xkud0uWQLZ5e-aOwLC0Ccnepg=='
>>> token = _
>>> decrypt(token, key).decode()
'John Doe'
পাসওয়ার্ড সহ ফার্নেট - পাসওয়ার্ড থেকে প্রাপ্ত কী, সুরক্ষা কিছুটা দুর্বল করে
আপনি যদি কোনও শক্তিশালী কী ডেরাইভেশন পদ্ধতি ব্যবহার করেন তবে গোপন কী পরিবর্তে আপনি একটি পাসওয়ার্ড ব্যবহার করতে পারেন । তারপরে আপনাকে বার্তায় লবণ এবং এইচএমএসি পুনরাবৃত্তি গণনাটি অন্তর্ভুক্ত করতে হবে, সুতরাং এনক্রিপ্ট করা মান প্রথমে লবণ, গণনা এবং ফার্নেট টোকেনকে আলাদা না করে ফার্নেটের সাথে সামঞ্জস্যপূর্ণ নয়:
import secrets
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
backend = default_backend()
iterations = 100_000
def _derive_key(password: bytes, salt: bytes, iterations: int = iterations) -> bytes:
"""Derive a secret key from a given password and salt"""
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(), length=32, salt=salt,
iterations=iterations, backend=backend)
return b64e(kdf.derive(password))
def password_encrypt(message: bytes, password: str, iterations: int = iterations) -> bytes:
salt = secrets.token_bytes(16)
key = _derive_key(password.encode(), salt, iterations)
return b64e(
b'%b%b%b' % (
salt,
iterations.to_bytes(4, 'big'),
b64d(Fernet(key).encrypt(message)),
)
)
def password_decrypt(token: bytes, password: str) -> bytes:
decoded = b64d(token)
salt, iter, token = decoded[:16], decoded[16:20], b64e(decoded[20:])
iterations = int.from_bytes(iter, 'big')
key = _derive_key(password.encode(), salt, iterations)
return Fernet(key).decrypt(token)
ডেমো:
>>> message = 'John Doe'
>>> password = 'mypass'
>>> password_encrypt(message.encode(), password)
b'9Ljs-w8IRM3XT1NDBbSBuQABhqCAAAAAAFyJdhiCPXms2vQHO7o81xZJn5r8_PAtro8Qpw48kdKrq4vt-551BCUbcErb_GyYRz8SVsu8hxTXvvKOn9QdewRGDfwx'
>>> token = _
>>> password_decrypt(token, password).decode()
'John Doe'
আউটপুটে নুনকে অন্তর্ভুক্ত করা এলোমেলো লবণের মান ব্যবহার করা সম্ভব করে, যার ফলে পাসওয়ার্ড পুনরায় ব্যবহার বা বার্তা পুনরাবৃত্তি নির্বিশেষে এনক্রিপ্ট করা আউটপুট সম্পূর্ণরূপে এলোমেলোভাবে নিশ্চিত হওয়া নিশ্চিত করে। পুনরাবৃত্তি গণনা অন্তর্ভুক্ত করা নিশ্চিত করে যে আপনি পুরানো বার্তাগুলি ডিক্রিপ্ট করার ক্ষমতা না হারিয়ে সময়ের সাথে সাথে সিপিইউ কর্মক্ষমতা বৃদ্ধির জন্য সামঞ্জস্য করতে পারেন।
একা একটি পাসওয়ার্ড পারেন প্রদান আপনি যদি অনুরূপ আকার পুকুর থেকে একটি সঠিকভাবে র্যান্ডম পাসওয়ার্ড জেনারেট, একটি Fernet 32-বাইট র্যান্ডম কী-এর মত নিরাপদ হতে। 32 বাইটস আপনাকে 256 keys 32 সংখ্যক কী দেয়, সুতরাং আপনি যদি 74 টি বর্ণের বর্ণমালা ব্যবহার করেন (26 টি উচ্চতর, 26 নিম্ন, 10 সংখ্যা এবং 12 সম্ভাব্য চিহ্ন), তবে আপনার পাসওয়ার্ডটি কমপক্ষে math.ceil(math.log(256 ** 32, 74))
== 42 অক্ষরের দীর্ঘ হওয়া উচিত । তবে, এইচএমএসি পুনরাবৃত্তির একটি ভালভাবে নির্বাচিত সংখ্যক এনট্রপির অভাব কিছুটা কমিয়ে আনতে পারে কারণ এটি আক্রমণকারীর পক্ষে তাদের জোর করে প্রবেশ করা আরও বেশি ব্যয়বহুল করে তোলে।
কেবলমাত্র জেনে থাকুন যে একটি সংক্ষিপ্ততর তবে এখনও যুক্তিসঙ্গতভাবে সুরক্ষিত পাসওয়ার্ড এই স্কিমটিকে পঙ্গু করে দেবে না, এটি কেবল একটি কার্যকর শক্তি আক্রমণকারীকে অনুসন্ধান করতে হবে এমন সম্ভাব্য মানের সংখ্যা হ্রাস করে; আপনার সুরক্ষা প্রয়োজনীয়তার জন্য যথেষ্ট শক্তিশালী পাসওয়ার্ড বেছে নেওয়ার বিষয়টি নিশ্চিত করুন ।
বিকল্প
অস্পষ্ট
একটি বিকল্প এনক্রিপ্ট করা হয় না । ভিগনেরে বলুন, কেবলমাত্র একটি স্বল্প-সুরক্ষার সাইফার বা একটি হোম-স্প্যান বাস্তবায়নের প্রলোভন করবেন না। এই পদ্ধতির কোনও সুরক্ষা নেই, তবে ভবিষ্যতে আপনার কোডটি সুরক্ষার মায়া বজায় রাখার জন্য দেওয়া একটি অনভিজ্ঞ বিকাশকারীকে দিতে পারেন, যা মোটেই সুরক্ষার চেয়ে খারাপ নয়।
আপনার যা যা দরকার তা হ'ল অস্পষ্টতা, কেবলমাত্র ডেটা বেস 64; ইউআরএল-নিরাপদ প্রয়োজনীয়তার জন্য, base64.urlsafe_b64encode()
ফাংশনটি ভাল। এখানে কোনও পাসওয়ার্ড ব্যবহার করবেন না, কেবল এনকোড করুন এবং আপনার কাজ শেষ। সর্বাধিক, কিছু সংক্ষেপণ যুক্ত করুন (যেমন zlib
):
import zlib
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
def obscure(data: bytes) -> bytes:
return b64e(zlib.compress(data, 9))
def unobscure(obscured: bytes) -> bytes:
return zlib.decompress(b64d(obscured))
এটি পরিণত b'Hello world!'
হয় b'eNrzSM3JyVcozy_KSVEEAB0JBF4='
।
কেবলমাত্র আন্তরিকতা
অবিশ্বস্ত ক্লায়েন্টের কাছে পাঠানো এবং ফিরে পাওয়ার পরে ডেটা আনলটারে ভরসা করা যেতে পারে তা নিশ্চিত করার একটি উপায় যদি আপনার প্রয়োজন হয় তবে আপনি ডেটাতে স্বাক্ষর করতে চান, আপনি SHA1 এর সাথে hmac
লাইব্রেরিটি ব্যবহার করতে পারেন (এখনও এইচএমএসি সাইন ইন করার জন্য নিরাপদ হিসাবে বিবেচিত ) বা আরও ভাল:
import hmac
import hashlib
def sign(data: bytes, key: bytes, algorithm=hashlib.sha256) -> bytes:
assert len(key) >= algorithm().digest_size, (
"Key must be at least as long as the digest size of the "
"hashing algorithm"
)
return hmac.new(key, data, algorithm).digest()
def verify(signature: bytes, data: bytes, key: bytes, algorithm=hashlib.sha256) -> bytes:
expected = sign(data, key, algorithm)
return hmac.compare_digest(expected, signature)
ডেটাতে স্বাক্ষর করতে এটি ব্যবহার করুন, তারপরে ডেটা সহ স্বাক্ষরটি সংযুক্ত করুন এবং ক্লায়েন্টকে প্রেরণ করুন। আপনি যখন ডেটা ফিরে পান, ডেটা এবং স্বাক্ষর বিভক্ত করুন এবং যাচাই করুন। আমি SHA256 এ ডিফল্ট অ্যালগরিদম সেট করেছি, সুতরাং আপনার একটি 32-বাইট কী প্রয়োজন:
key = secrets.token_bytes(32)
আপনি itsdangerous
গ্রন্থাগারটি দেখতে চাইতে পারেন , যা বিভিন্ন ফর্ম্যাটে সিরিয়ালাইজেশন এবং ডি-সিরিয়ালাইজেশনের সাথে এটি প্যাকেজ করে।
এনক্রিপশন এবং সততা সরবরাহ করতে AES-GCM এনক্রিপশন ব্যবহার করা Using
ফার্নেট এনক্রিপ্ট হওয়া ডেটার অখণ্ডতা নিশ্চিত করতে এইচএমএসি স্বাক্ষর সহ এইসি-সিবিসি তৈরি করে; দূষিত আক্রমণকারী আপনার সার্ভিসটিকে খারাপ ইনপুট সহ চেনাশোনাগুলিতে ব্যস্ত রাখতে আপনার সিস্টেমে বাজে ডেটা খাওয়াতে পারে না, কারণ সিফেরেক্সটেক্স সই হয়েছে।
গ্যালোয়া / কাউন্টার মোড ব্লক সাইফার ciphertext এবং উৎপন্ন ট্যাগ একই উদ্দেশ্য পরিবেশন, তাই একই উদ্দেশ্যে পরিবেশন করা ব্যবহার করা যাবে। অবক্ষয়টি হ'ল ফার্নেটের বিপরীতে অন্য প্ল্যাটফর্মগুলিতে পুনরায় ব্যবহারের জন্য সহজে ব্যবহারের এক-আকারের ফিট-সমস্ত রেসিপি নেই। এইএস-জিসিএমও প্যাডিং ব্যবহার করে না, সুতরাং এই এনক্রিপশন সিফারেক্সটেক্সটি ইনপুট বার্তার দৈর্ঘ্যের সাথে মেলে (যেখানে ফার্নেট / এইএস-সিবিসি বার্তাগুলিকে নির্দিষ্ট দৈর্ঘ্যের ব্লকের সাথে এনক্রিপ্ট করে, বার্তার দৈর্ঘ্যটিকে কিছুটা অস্পষ্ট করে)।
AES256-GCM সাধারণত 32 বাইট সিক্রেটটি কী হিসাবে গ্রহণ করে:
key = secrets.token_bytes(32)
তারপরে ব্যবহার করুন
import binascii, time
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.exceptions import InvalidTag
backend = default_backend()
def aes_gcm_encrypt(message: bytes, key: bytes) -> bytes:
current_time = int(time.time()).to_bytes(8, 'big')
algorithm = algorithms.AES(key)
iv = secrets.token_bytes(algorithm.block_size // 8)
cipher = Cipher(algorithm, modes.GCM(iv), backend=backend)
encryptor = cipher.encryptor()
encryptor.authenticate_additional_data(current_time)
ciphertext = encryptor.update(message) + encryptor.finalize()
return b64e(current_time + iv + ciphertext + encryptor.tag)
def aes_gcm_decrypt(token: bytes, key: bytes, ttl=None) -> bytes:
algorithm = algorithms.AES(key)
try:
data = b64d(token)
except (TypeError, binascii.Error):
raise InvalidToken
timestamp, iv, tag = data[:8], data[8:algorithm.block_size // 8 + 8], data[-16:]
if ttl is not None:
current_time = int(time.time())
time_encrypted, = int.from_bytes(data[:8], 'big')
if time_encrypted + ttl < current_time or current_time + 60 < time_encrypted:
# too old or created well before our current time + 1 h to account for clock skew
raise InvalidToken
cipher = Cipher(algorithm, modes.GCM(iv, tag), backend=backend)
decryptor = cipher.decryptor()
decryptor.authenticate_additional_data(timestamp)
ciphertext = data[8 + len(iv):-16]
return decryptor.update(ciphertext) + decryptor.finalize()
ফার্নেট সমর্থন করে এমন একই সময়ে-লাইভ-ব্যবহারের ক্ষেত্রে সমর্থন করার জন্য আমি একটি টাইমস্ট্যাম্প অন্তর্ভুক্ত করেছি।
পাইথন 3 এ এই পৃষ্ঠাতে অন্যান্য পন্থা
এইএস সিএফবি - সিবিসির মতো তবে প্যাডের প্রয়োজন ছাড়াই
এই পদ্ধতির যে সকল Іѕ Vаиітy অনুসরণ করে, ভুল যদ্যপি। এটি cryptography
সংস্করণ, তবে নোট করুন যে আমি আইফিকে সিফারেক্সটেক্সে অন্তর্ভুক্ত করেছি , এটি বিশ্বব্যাপী হিসাবে সংরক্ষণ করা উচিত নয় (আইভি পুনরায় ব্যবহার করা কীটির সুরক্ষাকে দুর্বল করে এবং মডিউলটিকে বিশ্বব্যাপী সংরক্ষণ করে এটি পুনরায় উত্পন্ন হবে পরবর্তী পাইথন অনুরোধ, সমস্ত সাইফারেক্সট অনির্ক্রিয়াযোগ্য রেন্ডারিং):
import secrets
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
def aes_cfb_encrypt(message, key):
algorithm = algorithms.AES(key)
iv = secrets.token_bytes(algorithm.block_size // 8)
cipher = Cipher(algorithm, modes.CFB(iv), backend=backend)
encryptor = cipher.encryptor()
ciphertext = encryptor.update(message) + encryptor.finalize()
return b64e(iv + ciphertext)
def aes_cfb_decrypt(ciphertext, key):
iv_ciphertext = b64d(ciphertext)
algorithm = algorithms.AES(key)
size = algorithm.block_size // 8
iv, encrypted = iv_ciphertext[:size], iv_ciphertext[size:]
cipher = Cipher(algorithm, modes.CFB(iv), backend=backend)
decryptor = cipher.decryptor()
return decryptor.update(encrypted) + decryptor.finalize()
এটিতে এইচএমএসি স্বাক্ষর যুক্ত আর্মারিংয়ের অভাব রয়েছে এবং কোনও টাইমস্ট্যাম্প নেই; আপনাকে সেগুলি নিজেরাই যুক্ত করতে হবে।
উপরেরটিও ব্যাখ্যা করে যে বেসিক ক্রিপ্টোগ্রাফি বিল্ডিং ব্লকগুলি ভুলভাবে একত্রিত করা কতটা সহজ; আইভি ভ্যালুতে সমস্ত ভাইয়ের ভুল পরিচালনা থেকে ডেটা লঙ্ঘন বা সমস্ত এনক্রিপ্ট হওয়া বার্তাগুলি অপঠনযোগ্য হতে পারে কারণ আইভি হারিয়ে গেছে lost পরিবর্তে ফার্নেট ব্যবহার আপনাকে এ জাতীয় ভুল থেকে রক্ষা করে।
AES ইসিবি - নিরাপদ নয়
আপনি যদি আগে এইএস ইসিবি এনক্রিপশন প্রয়োগ করেছেন এবং পাইথন 3 এ এখনও এটি সমর্থন করার প্রয়োজন হয় তবে আপনি এখনও এটি দিয়ে cryptography
করতে পারেন। একই ক্যাভ্যাটস প্রয়োগ হয়, ইসিবি বাস্তব জীবনের অ্যাপ্লিকেশনগুলির জন্য যথেষ্ট নিরাপদ নয় । পাইথন 3 এর উত্তরটি পুনরায় বাস্তবায়ন করুন, প্যাডিংয়ের স্বয়ংক্রিয় হ্যান্ডলিং যুক্ত করুন:
from base64 import urlsafe_b64encode as b64e, urlsafe_b64decode as b64d
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
backend = default_backend()
def aes_ecb_encrypt(message, key):
cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
encryptor = cipher.encryptor()
padder = padding.PKCS7(cipher.algorithm.block_size).padder()
padded = padder.update(msg_text.encode()) + padder.finalize()
return b64e(encryptor.update(padded) + encryptor.finalize())
def aes_ecb_decrypt(ciphertext, key):
cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
unpadder = padding.PKCS7(cipher.algorithm.block_size).unpadder()
padded = decryptor.update(b64d(ciphertext)) + decryptor.finalize()
return unpadder.update(padded) + unpadder.finalize()
আবার এটির মধ্যে এইচএমএসি স্বাক্ষর নেই এবং আপনার কোনওভাবে ইসিবি ব্যবহার করা উচিত নয়। উপরেরটি কেবল চিত্রিত করার জন্য রয়েছে cryptography
যা সাধারণ ক্রিপ্টোগ্রাফিক বিল্ডিং ব্লকগুলি পরিচালনা করতে পারে, এমনকি আপনার প্রকৃত ব্যবহার করা উচিত নয়।