पासवर्ड के अनुसार स्ट्रिंग को एन्कोड करने का सरल तरीका?


123

क्या पाइथन में पासवर्ड का उपयोग करके एन्कोडिंग / डिकोडिंग स्ट्रिंग्स का एक अंतर्निहित, सरल तरीका है?

कुछ इस तरह:

>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'

तो स्ट्रिंग "जॉन डो" को 'sjkl28cn2sx0' के रूप में एन्क्रिप्ट किया गया है। मूल स्ट्रिंग प्राप्त करने के लिए, मैं उस स्ट्रिंग को कुंजी 'मायपास' के साथ "अनलॉक" करूंगा, जो मेरे स्रोत कोड में एक पासवर्ड है। मुझे यह पसंद है कि मैं पासवर्ड के साथ वर्ड डॉक्यूमेंट को एन्क्रिप्ट / डिक्रिप्ट कर सकता हूं।

मैं इन एन्क्रिप्टेड स्ट्रिंग्स को URL पैरामीटर के रूप में उपयोग करना चाहूंगा। मेरा लक्ष्य अतिक्रमण है, मजबूत सुरक्षा नहीं; कुछ भी महत्वपूर्ण मिशन को एनकोड नहीं किया जा रहा है। मुझे एहसास है कि मैं कुंजी और मूल्यों को संग्रहीत करने के लिए एक डेटाबेस तालिका का उपयोग कर सकता हूं, लेकिन मैं न्यूनतम होने की कोशिश कर रहा हूं।


28
यहां "पासवर्ड" शब्द अनुचित है। आप इसे एक क्रिप्टोग्राफ़िक कुंजी के रूप में उपयोग कर रहे हैं और आपको उस शब्दावली का उपयोग अपने प्रश्नों में भ्रम से बचने के लिए और साथ ही किसी भी डॉक्स, टिप्पणियां, चश्मा, परीक्षण योजना, आदि के लिए करना चाहिए
जिम डेनिस

2
"मुझे यह पसंद है कि मैं एक पासवर्ड के साथ एक वर्ड डॉक्यूमेंट को एन्क्रिप्ट / डिक्रिप्ट कर सकता हूं।", वर्ड में पहले से ही आपके डॉक्यूमेंट को एन्क्रिप्ट करने के लिए एक बिल्ट इन ऑप्शन होता है, अगर आपको सिर्फ वर्ड डॉक्युमेंट्स को एन्क्रिप्ट करना है।
बायरन फिल्मर

2
दिलचस्प बात यह है कि इस तरह के पासवर्ड स्टोरेज नुकसान पर इस शोध पत्र के अनुसार , स्टैक ओवरफ्लो का उपयोग करने वाले डेवलपर्स कम सुरक्षित कोड का उत्पादन करते हैं। जी, मुझे आश्चर्य है कि क्यों?
वन

इसके अलावा, किसी को सुरक्षा
ईएस

एक बस एन्कोडिंग / डिकोडिंग को केवल लागू नहीं करता है
लार्जिंग

जवाबों:


70

मान लें कि आप केवल साधारण ओब्यूशन की तलाश कर रहे हैं जो बहुत ही आकस्मिक पर्यवेक्षक से चीजों को अस्पष्ट करेगा , और आप तीसरे पक्ष के पुस्तकालयों का उपयोग नहीं कर रहे हैं। मैं विगेनर सिफर जैसा कुछ सुझाऊंगा। यह सरल प्राचीन सिपहसालारों में से एक सबसे मजबूत है।

विगेनेयर सिफर

इसे लागू करना त्वरित और आसान है। कुछ इस तरह:

import base64

def encode(key, string):
    encoded_chars = []
    for i in xrange(len(string)):
        key_c = key[i % len(key)]
        encoded_c = chr(ord(string[i]) + ord(key_c) % 256)
        encoded_chars.append(encoded_c)
    encoded_string = "".join(encoded_chars)
    return base64.urlsafe_b64encode(encoded_string)

डिकोड बहुत अधिक समान है, इसके अलावा आप कुंजी को घटाते हैं।

यदि आप एन्कोडिंग कर रहे हैं, तो यह टूटना बहुत कठिन है, और / या यदि उपयोग किए गए पासफ़्रेज़ की लंबाई का अनुमान लगाना कठिन है।

यदि आप कुछ क्रिप्टोग्राफिक की तलाश में हैं, तो PyCrypto शायद आपकी सबसे अच्छी शर्त है, हालांकि पिछले उत्तर कुछ विवरणों को अनदेखा करते हैं: PyCrypto में ECB मोड के लिए आपके संदेश की लंबाई 16 अक्षरों की एक बहु होनी चाहिए। तो, आपको पैड करना चाहिए। इसके अलावा, यदि आप उन्हें base64.urlsafe_b64_encode()मानक के बजाय URL पैरामीटर के रूप में उपयोग करना चाहते हैं, तो उपयोग करें । यह बेस -64 वर्णमाला के कुछ अक्षरों को URL-सुरक्षित वर्णों के साथ बदल देता है (जैसा कि नाम से पता चलता है)।

हालाँकि, आपको ABSOLUTELY होना चाहिए कि यह उपयोग करने से पहले आपकी आवश्यकताओं के लिए मोटापे की बहुत पतली परत पर्याप्त है। विकिपीडिया लेख मैंने सिफर को तोड़ने के लिए विस्तृत निर्देश प्रदान करने के लिए जुड़ा हुआ है, इसलिए मध्यम मात्रा में दृढ़ संकल्प वाले कोई भी इसे आसानी से तोड़ सकता है।


6
मैंने स्मेहूद की स्क्रिप्ट तय की, और डिकोडिंग फंक्शन को जोड़ा। gith.github.com/ilogik/6f9431e4588015ecb194
एड्रियन मेस्टर

3
ध्यान! smehmood का कोड और एड्रियन Mester का फिक्स दोनों ही लोअर अस्की रेंज के पात्रों के साथ स्ट्रिंग्स के लिए काम करते हैं! % ऑपरेटर, यूनिकोड इनपुट आदि की पूर्वता देखें। कार्यशील कोड के लिए क्वाइल का उत्तर देखें
le_m

2
@smehmood मुझे निम्न त्रुटि हो रही है'str' object cannot be interpreted as an integer
रोहित खत्री

3
"फॉर मैं इन अरेंज (स्ट्रिंग)" को चेंज करने की जरूरत हो सकती है "आई फॉर एक्सरे (लेन (स्ट्रिंग))"
user3113626

2
अजगर 2 और 3 के लिए एनकोडर और डिकोडर: gist.github.com/gowhari/fea9c559f08a310e5cfd62978bc86a1a
iman

71

जैसा कि आप स्पष्ट रूप से कहते हैं कि आप अस्पष्टता को सुरक्षा नहीं चाहते हैं, हम आपको जो सुझाव देते हैं उसकी कमजोरी के लिए आपको फटकार लगाने से बचेंगे :)

तो, PyCrypto का उपयोग कर:

import base64
from Crypto.Cipher import AES

msg_text = b'test some plain text here'.rjust(32)
secret_key = b'1234567890123456'

cipher = AES.new(secret_key,AES.MODE_ECB) # never use ECB in strong systems obviously
encoded = base64.b64encode(cipher.encrypt(msg_text))
print(encoded)
decoded = cipher.decrypt(base64.b64decode(encoded))
print(decoded)

यदि किसी को आपके डेटाबेस और आपके कोड आधार की पकड़ मिलती है, तो वे एन्क्रिप्ट किए गए डेटा को डिकोड कर पाएंगे। अपनी secret_keyसुरक्षित रखें !


3
मुझे नहीं लगता कि यह तब तक काम करेगा जब तक msg_text की लंबाई 16 बाइट्स की एक से अधिक न हो, क्योंकि AES एन्क्रिप्शन के लिए उन ब्लॉकों की आवश्यकता होती है जो लंबाई में 16 के गुणक हैं। Msg_text की मनमानी लंबाई के लिए एक कार्यान्‍वयन कार्य को लंबाई में 16 की बहुतायत में लाने के लिए स्ट्रिंग में पैडिंग जोड़ना होगा।
टॉस्टर

6
पैडिंग के साथ एक उदाहरण: paste.ubuntu.com/11024555 यह मनमाना पासवर्ड और संदेश की लंबाई के साथ काम करता है।
iman

3
@ ईथन नं, यह विशेष encryptसमारोह स्टेटफुल dlitz.net/software/pycrypto/api/current/… है, इसलिए आपको इसे पुन: उपयोग नहीं करना चाहिए।
विल

1
@Will +1 जानकारी और लिंक के लिए धन्यवाद। मुझे भविष्य में एक बहुत ही महंगे बग फिक्स से बचाया।
एथन

3
फिर से "स्पष्ट रूप से मजबूत प्रणालियों में ईसीबी का उपयोग कभी न करें": मैं सिर्फ अपनी मस्ती के लिए इस पर प्रयोग कर रहा हूं। लेकिन मैंने आपके कोड में उपरोक्त टिप्पणी देखी। बहुत कम सुरक्षा / एन्क्रिप्शन / सूचना-सिद्धांत पृष्ठभूमि वाले हममें से उन लोगों के लिए, जो "कभी उपयोग नहीं करते" क्यों? शायद एक और सवाल की जरूरत है ... या शायद इस पर एक लिंक है।
ट्रेवर बोयड स्मिथ

69

पायथन में कोई अंतर्निहित एन्क्रिप्शन योजनाएं नहीं हैं। आपको एन्क्रिप्टेड डेटा स्टोरेज को भी गंभीर रखना चाहिए; तुच्छ एन्क्रिप्शन योजनाएं जो एक डेवलपर असुरक्षित समझती हैं और एक खिलौना योजना को एक कम अनुभवी डेवलपर द्वारा सुरक्षित योजना के लिए गलत माना जा सकता है। यदि आप एन्क्रिप्ट करते हैं, तो ठीक से एन्क्रिप्ट करें।

हालाँकि, एक उचित एन्क्रिप्शन योजना को लागू करने के लिए आपको बहुत अधिक काम करने की आवश्यकता नहीं है। सबसे पहले, क्रिप्टोग्राफी व्हील का फिर से आविष्कार न करें, आपके लिए इसे संभालने के लिए एक विश्वसनीय क्रिप्टोग्राफी लाइब्रेरी का उपयोग करें। पायथन 3 के लिए, वह विश्वसनीय पुस्तकालय है cryptography

मैं यह भी सलाह देता हूं कि एन्क्रिप्शन और डिक्रिप्शन बाइट्स पर लागू होता है ; पहले बाइट्स के लिए पाठ संदेश सांकेतिक शब्दों में बदलना; stringvalue.encode()UTF8 के लिए एन्कोड, आसानी से फिर से उपयोग करके वापस bytesvalue.decode()

अंतिम लेकिन कम से कम, जब एन्क्रिप्ट और डिक्रिप्टिंग नहीं है, तो हम कुंजी के बारे में बात करते हैं , पासवर्ड नहीं। एक कुंजी मानव यादगार नहीं होनी चाहिए, यह कुछ ऐसा है जिसे आप गुप्त स्थान पर स्टोर करते हैं लेकिन मशीन पठनीय है, जबकि एक पासवर्ड अक्सर मानव-पठनीय और यादगार हो सकता है। आप पासवर्ड से एक कुंजी प्राप्त कर सकते हैं, थोड़ी देखभाल के साथ।

लेकिन एक वेब अनुप्रयोग या प्रक्रिया के लिए एक क्लस्टर में चल रहे मानव ध्यान के बिना इसे चलाने के लिए, आप एक कुंजी का उपयोग करना चाहते हैं। पासवर्ड तब होते हैं जब केवल अंतिम उपयोगकर्ता को विशिष्ट जानकारी तक पहुंचने की आवश्यकता होती है। फिर भी, आप आमतौर पर पासवर्ड के साथ एप्लिकेशन को सुरक्षित करते हैं, फिर एक कुंजी का उपयोग करके एन्क्रिप्टेड जानकारी का आदान-प्रदान करते हैं, शायद उपयोगकर्ता खाते से जुड़ा हुआ है।

सममित कुंजी एन्क्रिप्शन

फर्नेट - एईएस सीबीसी + एचएमएसी, दृढ़ता से अनुशंसित

cryptographyपुस्तकालय भी शामिल है Fernet नुस्खा , क्रिप्टोग्राफी का उपयोग कर के लिए एक सर्वोत्तम प्रथाओं नुस्खा। फर्नेट एक खुला मानक है , जिसमें प्रोग्रामिंग भाषाओं की एक विस्तृत श्रृंखला में तैयार कार्यान्वयन है और यह आपके लिए संस्करण सूचना, टाइमस्टैम्प और संदेश छेड़छाड़ को रोकने के लिए एक एचएमएसी हस्ताक्षर के साथ एईएस सीबीसी एन्क्रिप्शन पैकेज करता है।

फर्नेट संदेशों को एन्क्रिप्ट और डिक्रिप्ट करना और आपको सुरक्षित रखना बहुत आसान बनाता है । यह एक गुप्त के साथ डेटा एन्क्रिप्ट करने के लिए आदर्श विधि है।

मैं आपको Fernet.generate_key()एक सुरक्षित कुंजी उत्पन्न करने के लिए उपयोग करने की सलाह देता हूं । आप एक पासवर्ड (अगले भाग) का भी उपयोग कर सकते हैं, लेकिन एक पूर्ण 32-बाइट गुप्त कुंजी (16 बाइट्स के साथ एन्क्रिप्ट करने के लिए, और हस्ताक्षर के लिए एक और 16) सबसे पासवर्ड से अधिक सुरक्षित होने जा रहा है जिसके बारे में आप सोच सकते थे।

फ़र्नेट उत्पन्न करने वाली कुंजी bytesURL के साथ एक ऑब्जेक्ट है और सुरक्षित बेस 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ऑब्जेक्ट हैं।

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'

पासवर्ड के साथ फर्नेट - पासवर्ड से ली गई कुंजी, सुरक्षा को कुछ हद तक कमजोर करती है

आप एक गुप्त कुंजी के बजाय एक पासवर्ड का उपयोग कर सकते हैं, बशर्ते आप एक मजबूत कुंजी व्युत्पत्ति विधि का उपयोग करें । आपको संदेश में नमक और HMAC पुनरावृत्ति गणना को शामिल करना है, इसलिए पहले अलग किए गए नमक, गिनती और फर्नेट टोकन के बिना एन्क्रिप्ट किया गया मान फर्नेट-संगत नहीं है:

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'

आउटपुट में नमक को शामिल करना एक यादृच्छिक नमक मूल्य का उपयोग करना संभव बनाता है, जो बदले में एन्क्रिप्टेड आउटपुट को पासवर्ड पुन: उपयोग या संदेश पुनरावृत्ति की परवाह किए बिना पूरी तरह से यादृच्छिक होने की गारंटी देता है। पुनरावृत्ति गिनती सहित यह सुनिश्चित करता है कि आप पुराने संदेशों को डिक्रिप्ट करने की क्षमता खोए बिना समय के साथ सीपीयू के प्रदर्शन में वृद्धि के लिए समायोजित कर सकते हैं।

एक पासवर्ड अकेले एक फ़र्नेट 32-बाइट रैंडम की के रूप में सुरक्षित हो सकता है, बशर्ते आप एक समान आकार के पूल से एक ठीक से रैंडम पासवर्ड उत्पन्न करें। 32 बाइट्स आपको 256 ^ 32 नंबर की चाबियाँ प्रदान करते हैं, इसलिए यदि आप 74 वर्णों (26 ऊपरी, 26 निचले, 10 अंक और 12 संभावित प्रतीकों) की वर्णमाला का उपयोग करते हैं, तो आपका पासवर्ड कम से कम math.ceil(math.log(256 ** 32, 74))== 42 वर्ण लंबा होना चाहिए । हालांकि, एचएमएसी पुनरावृत्तियों की एक अच्छी तरह से चुनी गई बड़ी संख्या कुछ हद तक एन्ट्रापी की कमी को कम कर सकती है क्योंकि यह हमलावर के लिए अपने तरीके से बल देने के लिए बहुत अधिक महंगा बनाता है।

बस पता है कि एक छोटा लेकिन अभी भी सुरक्षित रूप से सुरक्षित पासवर्ड चुनने से इस योजना को अपंग नहीं किया जाएगा, यह सिर्फ संभावित मूल्यों की संख्या को कम करता है जो एक क्रूर-बल हमलावर के माध्यम से खोजना होगा; अपनी सुरक्षा आवश्यकताओं के लिए एक मजबूत पर्याप्त पासवर्ड चुनना सुनिश्चित करें ।

वैकल्पिक

obscuring

एक विकल्प एन्क्रिप्ट करने के लिए नहीं है । Vignere कहते हैं, बस एक कम सुरक्षा सिफर का उपयोग करने के लिए, या एक घर का का उपयोग नहीं करने के लिए परीक्षा हो। इन दृष्टिकोणों में कोई सुरक्षा नहीं है, लेकिन एक अनुभवहीन डेवलपर दे सकता है जिसे भविष्य में आपके कोड को सुरक्षा का भ्रम बनाए रखने का काम दिया जाता है, जो किसी भी सुरक्षा से बदतर नहीं है।

यदि आप सभी की जरूरत अस्पष्टता है, तो बस डेटा 6464; URL- सुरक्षित आवश्यकताओं के लिए, 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लाइब्रेरी का उपयोग कर सकते हैं (फिर भी 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लाइब्रेरी को देखना चाहते हैं , जो विभिन्न स्वरूपों में क्रमबद्धता और डी-सीरियलाइजेशन के साथ इसे तैयार करता है।

एन्क्रिप्शन और अखंडता प्रदान करने के लिए एईएस-जीसीएम एन्क्रिप्शन का उपयोग करना

फर्नेट एन्क्रिप्टेड डेटा की अखंडता सुनिश्चित करने के लिए एचएमएसी हस्ताक्षर के साथ एईसी-सीबीसी पर बनाता है; दुर्भावनापूर्ण हमलावर आपके सिस्टम को खराब इनपुट के साथ हलकों में व्यस्त रखने के लिए आपके सिस्टम को बकवास डेटा नहीं खिला सकता है, क्योंकि सिफरटेक्स्ट पर हस्ताक्षर किए गए हैं।

गाल्वा / काउंटर मोड ब्लॉक सिफर सिफर है और एक का उत्पादन टैग इसी उद्देश्य को पूरा करने के लिए है, तो एक ही प्रयोजनों की सेवा करने के लिए इस्तेमाल किया जा सकता। नकारात्मक पक्ष यह है कि फर्नेट के विपरीत अन्य प्लेटफार्मों पर पुन: उपयोग करने के लिए एक आसान-से-उपयोग-एक-फिट-सभी नुस्खा नहीं है। एईएस-जीसीएम भी पैडिंग का उपयोग नहीं करता है, इसलिए यह एन्क्रिप्शन सिफरटेक्स्ट इनपुट संदेश की लंबाई से मेल खाता है (जबकि फ़र्नेट / एईएस-सीबीसी संदेशों को निश्चित लंबाई के ब्लॉकों को एन्क्रिप्ट करता है, संदेश की लंबाई को कुछ हद तक अस्पष्ट करता है)।

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संस्करण है, लेकिन ध्यान दें कि मैं IV को सिफरटेक्स्ट में शामिल करता हूं , इसे वैश्विक के रूप में संग्रहीत नहीं किया जाना चाहिए (IV का पुन: उपयोग करने से कुंजी की सुरक्षा कमजोर हो जाती है, और इसे मॉड्यूल वैश्विक के रूप में संग्रहीत करने का मतलब है कि यह फिर से उत्पन्न होगा। अगले पायथन के आह्वान पर, सभी सिफरटेक्स्ट अविवेकी को प्रस्तुत करते हुए):

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()

इसमें एचएमएसी हस्ताक्षर के अतिरिक्त कवच का अभाव है और टाइमस्टैम्प नहीं है; आपको स्वयं को जोड़ना होगा।

उपरोक्त यह भी दर्शाता है कि बुनियादी क्रिप्टोग्राफी बिल्डिंग ब्लॉकों को गलत तरीके से संयोजित करना कितना आसान है; IV मूल्य के सभी the Vаиітy के गलत हैंडलिंग से डेटा ब्रीच हो सकता है या सभी एन्क्रिप्टेड संदेश बिना पढ़े जा सकते हैं क्योंकि IV खो गया है। इसके बजाय फर्नेट का उपयोग करना आपको ऐसी गलतियों से बचाता है।

एईएस ईसीबी - सुरक्षित नहीं है

यदि आपने पहले एईएस ईसीबी एन्क्रिप्शन को लागू किया था और अभी भी पायथन 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आम क्रिप्टोग्राफिक बिल्डिंग ब्लॉकों को संभाल सकते हैं, यहां तक ​​कि उन लोगों को भी जिन्हें आपको वास्तव में उपयोग नहीं करना चाहिए।


51

@ Smehmood's Vigenere सिफर उत्तर में उल्लिखित "एन्कोडेड_सी" को "की_सी" होना चाहिए।

यहाँ काम कर रहे हैं सांकेतिक शब्दों में बदलना / डिकोड।

import base64
def encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc))

def decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc)
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

डिस्क्लेमर: जैसा कि टिप्पणियों से निहित है, इसका उपयोग किसी वास्तविक एप्लिकेशन में डेटा की सुरक्षा के लिए नहीं किया जाना चाहिए , जब तक कि आप इसे नहीं पढ़ते हैं और इसके बारे में ध्यान नहीं देते हैं:

XOR एन्क्रिप्शन में क्या गलत है?


2
बहुत उपयोगी है, धन्यवाद। मैंने नीचे पायथन 3 संस्करण पोस्ट किया है (यह टिप्पणियों में बदसूरत लग रहा था)
रयान बैरेट

1
"श्नाइयर लॉ" : कोई भी, सबसे क्लूलेस शौकिया से लेकर सर्वश्रेष्ठ क्रिप्टोग्राफर तक, एक एल्गोरिथ्म बना सकता है जिसे वह खुद नहीं तोड़ सकता। इसका उपयोग न करें, यह सुरक्षित होने के करीब भी नहीं है।
ज़ाफ़

3
महान! यह संस्करण लहजे के साथ तार के लिए भी काम करता है, जबकि @ smehmood का संस्करण नहीं है। उपयोग उदाहरण: encodedmsg = encode('mypassword', 'this is the message éçàèç"') print encodedmsg print decode('mypassword', encodedmsg)यह ठीक काम करता है।
बसज

2
यहाँ इस कोड पर आधारित एक उदात्त पाठ प्लगइन है , जो CTRL + SHIFT + P के साथ पाठ के आसान एन्कोडिंग / डिकोडिंग की अनुमति देता है फिर "Eeencode" या "Dddecode"।
बसज

2
@basj उदाहरण के लिए धन्यवाद
sk03

49

यहाँ @qneill के उत्तर से कार्यों का एक पायथन 3 संस्करण है :

import base64
def encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc).encode()).decode()

def decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc).decode()
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

अतिरिक्त सांकेतिक शब्दों में बदलना / व्याख्या करना आवश्यक है क्योंकि पायथन 3 ने स्ट्रिंग्स / बाइट सरणियों को दो अलग-अलग अवधारणाओं में विभाजित किया है, और यह दर्शाने के लिए अपने एपीआई को अपडेट किया है कि ।।


4
धन्यवाद रयान, fwiw आप typo'd @qniell
qneill

3
सोच रहे लोगों के लिए, मतभेद हैं .encode()).decode()। की वापसी में encode(), और .decode()दूसरी पंक्ति में decode()
रॉल्फबली

2
हम्म, एन्कोडेड कोड वास्तव में अद्वितीय नहीं है, मैंने एक परीक्षण चलाया और यह 11,22,33,44, ..., 88,99,111,222 की हर कोड कुंजी दिखाता है, ... हमेशा पहले जैसा ही एक और कोड है। लेकिन मैं इसकी सराहना करता हूं
हज्जीक्स

1
@ रयान बैरेट, क्या डिकोडिंग के समय पासवर्ड की शुद्धता की जांच करना संभव है। मान लें कि मैं एक एन्कोडेड स्ट्रिंग भेजता हूं जो कुंजी को जानता है, अगर वह टाइपो के साथ कुंजी दर्ज करता है तो क्या होगा? डिकोड अभी भी उसे "डिकोडेड" स्ट्रिंग देता है, लेकिन यह सही नहीं है, वह कैसे बता सकता है?
हेनज

26

डिस्क्लेमर: जैसा कि टिप्पणियों में बताया गया है, इसका उपयोग वास्तविक एप्लिकेशन में डेटा की सुरक्षा के लिए नहीं किया जाना चाहिए

XOR एन्क्रिप्शन में क्या गलत है?

/crypto/56281/breaking-a-xor-cipher-of-known-key-length

https://github.com/hellman/xortool


जैसा कि उल्लेख किया गया है कि PyCrypto लाइब्रेरी में सिफर्स का एक सूट है। XOR "सिफर" का उपयोग गंदे काम करने के लिए किया जा सकता है यदि आप इसे स्वयं नहीं करना चाहते हैं:

from Crypto.Cipher import XOR
import base64

def encrypt(key, plaintext):
  cipher = XOR.new(key)
  return base64.b64encode(cipher.encrypt(plaintext))

def decrypt(key, ciphertext):
  cipher = XOR.new(key)
  return cipher.decrypt(base64.b64decode(ciphertext))

साइडर प्लेटेक्स्ट को पैड किए बिना निम्नानुसार काम करता है:

>>> encrypt('notsosecretkey', 'Attack at dawn!')
'LxsAEgwYRQIGRRAKEhdP'

>>> decrypt('notsosecretkey', encrypt('notsosecretkey', 'Attack at dawn!'))
'Attack at dawn!'

बेस 64 एनकोड / डिकोड फ़ंक्शंस के लिए https://stackoverflow.com/a/2490376/241294 पर क्रेडिट (मैं एक अजगर नौसिखिया हूँ)।


ध्यान दें: क्रिप्टो मॉड्यूल को pyron3 में स्थापित किया गया है जो कि क्रिप्टो है, न कि क्रिप्टो। sudo pip3 install pycrypto
निखिल वीजे

2
नोट: pycrypto मेरे अंत में हरकुप्प पर स्थापित करने में विफल रहा। मुझे यह पोस्टिंग मिली .. ऐसा लगता है कि pycrypto package को pycryptodome insteal नामक एक अन्य के साथ बदल दिया गया है, और XOR विधि को पदावनत कर दिया गया है: github.com/digitalocean/netbox/issues/1527
Nikhil VJ

2
इस पद्धति का उपयोग कभी न करें , इस 'सिफर' के विवरण को दस्तावेज़ीकरण में नोट करें: XOR खिलौना सिफर, XOR सबसे सरल धारा सिफर है। एन्क्रिप्शन और डिक्रिप्शन XOR-ing डेटा द्वारा कुंजी को contatenating द्वारा किए गए कीस्ट्रीम के साथ किया जाता है। वास्तविक अनुप्रयोगों के लिए इसका उपयोग न करें!
मार्टिन पीटर्स

@MartijnPieters आप सही हैं। उम्मीद है कि मेरे संपादन ने उस बिंदु को स्पष्ट कर दिया है।
पोइदा

12

यहां AES (PyCrypto) और base64 का उपयोग करके URL सुरक्षित एन्क्रिप्शन और डिक्रिप्शन का कार्यान्वयन है।

import base64
from Crypto import Random
from Crypto.Cipher import AES

AKEY = b'mysixteenbytekey' # AES key must be either 16, 24, or 32 bytes long

iv = Random.new().read(AES.block_size)

def encode(message):
    obj = AES.new(AKEY, AES.MODE_CFB, iv)
    return base64.urlsafe_b64encode(obj.encrypt(message))

def decode(cipher):
    obj2 = AES.new(AKEY, AES.MODE_CFB, iv)
    return obj2.decrypt(base64.urlsafe_b64decode(cipher))

अगर आपको इस तरह की कुछ समस्या का सामना करना पड़ रहा है तो https://bugs.python.org/issue4329 ( TypeError: character mapping must return integer, None or unicode) str(cipher)निम्नानुसार डिकोडिंग करते समय उपयोग करें :

return obj2.decrypt(base64.urlsafe_b64decode(str(cipher)))

परीक्षा:

In [13]: encode(b"Hello World")
Out[13]: b'67jjg-8_RyaJ-28='

In [14]: %timeit encode("Hello World")
100000 loops, best of 3: 13.9 µs per loop

In [15]: decode(b'67jjg-8_RyaJ-28=')
Out[15]: b'Hello World'

In [16]: %timeit decode(b'67jjg-8_RyaJ-28=')
100000 loops, best of 3: 15.2 µs per loop

Windows x64 + Python 3.6 + PyCryptodome (pycrypto के रूप में पदावनत) के साथ बग TypeError: Object type <class 'str'> cannot be passed to C code:।
बसज

@Basj खेद है .. मैं विंडोज़ का उपयोग नहीं करता, इसलिए मैं एक तय नहीं कर सकता।
All All Vаиітy

IV उत्पन्न न करें और इसे मॉड्यूल स्तर पर संग्रहीत करें, आपको IV को दिए गए सिफरटेक्स्ट संदेश में शामिल करना होगा! आपने अब दो समस्याएं पेश कीं: पायथन प्रक्रिया को फिर से शुरू करने से आपको एक नया IV प्राप्त होता है, जिससे पहले से एन्क्रिप्ट किए गए संदेशों को डिक्रिप्ट करना असंभव हो जाता है, और इस बीच आप कई संदेशों के लिए IV का फिर से उपयोग कर रहे हैं, जो प्रभावी रूप से ईसीबी स्तर तक सुरक्षा को कम कर देता है।
मार्टिन पीटर्स

1
@ All @Vаиітy के साथ हल किया b'...', मैंने भविष्य के संदर्भ के लिए उत्तर को संपादित किया!
बसज

8

पायथन 3 में काम करना सांकेतिक शब्दों में बदलना / डिकोड करना (कनील के उत्तर से बहुत कम अनुकूलित):

def encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = (ord(clear[i]) + ord(key_c)) % 256
        enc.append(enc_c)
    return base64.urlsafe_b64encode(bytes(enc))

def decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc)
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + enc[i] - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

8

कुछ बेहतरीन जवाब के लिए धन्यवाद। जोड़ने के लिए कुछ भी मूल नहीं है, लेकिन यहाँ कुछ उपयोगी पायथन सुविधाओं का उपयोग करके क्वाइल के उत्तर के कुछ प्रगतिशील पुनर्लेखन हैं। मुझे आशा है कि आप सहमत हैं कि वे कोड को सरल और स्पष्ट करेंगे।

import base64


def qneill_encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc))


def qneill_decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc)
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

enumerate()- सूची में आइटमों को उनके सूचकांक के साथ जोड़ दें

एक स्ट्रिंग में वर्णों पर पुनरावृति

def encode_enumerate(key, clear):
    enc = []
    for i, ch in enumerate(clear):
        key_c = key[i % len(key)]
        enc_c = chr((ord(ch) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc))


def decode_enumerate(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc)
    for i, ch in enumerate(enc):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(ch) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)

एक सूची समझ का उपयोग कर सूची बनाएँ

def encode_comprehension(key, clear):
    enc = [chr((ord(clear_char) + ord(key[i % len(key)])) % 256)
                for i, clear_char in enumerate(clear)]
    return base64.urlsafe_b64encode("".join(enc))


def decode_comprehension(key, enc):
    enc = base64.urlsafe_b64decode(enc)
    dec = [chr((256 + ord(ch) - ord(key[i % len(key)])) % 256)
           for i, ch in enumerate(enc)]
    return "".join(dec)

अक्सर पायथन में लिस्ट इंडेक्स की कोई आवश्यकता नहीं होती है। पूरी तरह से ज़िप और चक्र का उपयोग करके लूप इंडेक्स चर को हटा दें:

from itertools import cycle


def encode_zip_cycle(key, clear):
    enc = [chr((ord(clear_char) + ord(key_char)) % 256)
                for clear_char, key_char in zip(clear, cycle(key))]
    return base64.urlsafe_b64encode("".join(enc))


def decode_zip_cycle(key, enc):
    enc = base64.urlsafe_b64decode(enc)
    dec = [chr((256 + ord(enc_char) - ord(key_char)) % 256)
                for enc_char, key_char in zip(enc, cycle(key))]
    return "".join(dec)

और कुछ परीक्षण ...

msg = 'The quick brown fox jumps over the lazy dog.'
key = 'jMG6JV3QdtRh3EhCHWUi'
print('cleartext: {0}'.format(msg))
print('ciphertext: {0}'.format(encode_zip_cycle(key, msg)))

encoders = [qneill_encode, encode_enumerate, encode_comprehension, encode_zip_cycle]
decoders = [qneill_decode, decode_enumerate, decode_comprehension, decode_zip_cycle]

# round-trip check for each pair of implementations
matched_pairs = zip(encoders, decoders)
assert all([decode(key, encode(key, msg)) == msg for encode, decode in matched_pairs])
print('Round-trips for encoder-decoder pairs: all tests passed')

# round-trip applying each kind of decode to each kind of encode to prove equivalent
from itertools import product
all_combinations = product(encoders, decoders)
assert all(decode(key, encode(key, msg)) == msg for encode, decode in all_combinations)
print('Each encoder and decoder can be swapped with any other: all tests passed')

>>> python crypt.py
cleartext: The quick brown fox jumps over the lazy dog.
ciphertext: vrWsVrvLnLTPlLTaorzWY67GzYnUwrSmvXaix8nmctybqoivqdHOic68rmQ=
Round-trips for encoder-decoder pairs: all tests passed
Each encoder and decoder can be swapped with any other: all tests passed

बहुत अच्छा @ निक, अजगर की अच्छी प्रगति, और परीक्षण भी बूट। उचित श्रेय देने के लिए मैं सिर्फ Smehmood के मूल उत्तर stackoverflow.com/a/2490718/468252 में एक बग को ठीक कर रहा था ।
११:४२ बजे क्नील

4

यदि आप सुरक्षित रहना चाहते हैं, तो आप फर्नेट का उपयोग कर सकते हैं, जो क्रिप्टोग्राफिक रूप से ध्वनि है। आप एक स्थिर "नमक" का उपयोग कर सकते हैं यदि आप इसे अलग से संग्रहीत नहीं करना चाहते हैं - तो आप केवल शब्दकोश और इंद्रधनुष हमले की रोकथाम खो देंगे। मैंने इसे चुना क्योंकि मैं लंबे या छोटे पासवर्ड चुन सकता हूं, जो एईएस के साथ इतना आसान नहीं है।

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
import base64

#set password
password = "mysecretpassword"
#set message
message = "secretmessage"

kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt="staticsalt", iterations=100000, backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)

#encrypt
encrypted = f.encrypt(message)
print encrypted

#decrypt
decrypted = f.decrypt(encrypted)
print decrypted

यदि यह बहुत जटिल है, तो किसी ने सरलता से सुझाव दिया

from simplecrypt import encrypt, decrypt
ciphertext = encrypt('password', plaintext)
plaintext = decrypt('password', ciphertext)

बस एक नमक उत्पन्न करें और इसे एन्क्रिप्शन परिणाम में शामिल करें ताकि बार-बार पासवर्ड और संदेश अभी भी यादृच्छिक आउटपुट में परिणाम हो। एल्गोरिथ्म को भविष्य के सबूत के लिए पुनरावृत्तियों के मूल्य को भी शामिल करें लेकिन फिर भी एक अलग पुनरावृत्ति गणना का उपयोग करके संदेशों को डिक्रिप्ट करने में सक्षम हो।
मार्टिन पीटर्स

3

जो कोई भी यहां आया (और बाउंटी) एक सेटअप के साथ एक लग रहा था, जिसमें बहुत सारे सेटअप नहीं थे, जो अन्य उत्तर प्रदान नहीं करते हैं। इसलिए मैं आगे बेस 64 लगा रहा हूं।

अब, यह ध्यान रखें कि यह केवल मूल अपभ्रंश है, और ** ** ** के लिए NO NOAY OK में है , लेकिन यहां कुछ एक-लाइनर हैं:

from base64 import urlsafe_b64encode, urlsafe_b64decode

def encode(data, key):
    return urlsafe_b64encode(bytes(key+data, 'utf-8'))

def decode(enc, key):
    return urlsafe_b64decode(enc)[len(key):].decode('utf-8')

print(encode('hi', 'there')) # b'dGhlcmVoaQ=='
print(decode(encode('hi', 'there'), 'there')) # 'hi'

ध्यान देने योग्य कुछ बातें:

  • आप अपने I / O के आधार पर अपने आप अधिक / कम बाइट-से-स्ट्रिंग एन्कोडिंग / डिकोडिंग से निपटना चाहेंगे। में bytes()और देखोbytes::decode()
  • base64 आसानी से पहचाने जाने वाले वर्णों के प्रकारों से पहचाना जाता है, और अक्सर =वर्णों के साथ समाप्त होता है। मेरे जैसे लोग जब हम वेबसाइटों पर देखते हैं तो उन्हें जावास्क्रिप्ट कंसोल में डिकोड करते हुए घूमते हैं। यह btoa(string)(जेएस) जितना आसान है
  • यह आदेश कुंजी + डेटा है, जैसा कि b64 में, अंत में क्या वर्ण दिखाई देते हैं, यह इस बात पर निर्भर करता है कि शुरुआत में कौन से वर्ण हैं (बाइट ऑफ़सेट के कारण। विकिपीडिया में कुछ अच्छे स्पष्टीकरण हैं)। इस परिदृश्य में, एन्कोडेड स्ट्रिंग की शुरुआत उस कुंजी के साथ एन्कोडेड सब कुछ के लिए समान होगी। प्लस यह है कि डेटा अधिक बाधित हो जाएगा। इसे दूसरे तरीके से करने से डेटा भाग पर परिणाम सभी के लिए समान होगा, चाहे कोई भी कुंजी हो।

अब, अगर आप चाहते थे कि आपको किसी भी प्रकार की चाबी की आवश्यकता न हो, लेकिन बस कुछ आपत्ति हो, तो आप अभी भी बस फिर से आधार का उपयोग कर सकते हैं, बिना किसी प्रकार की कुंजी के:

from base64 import urlsafe_b64encode, urlsafe_b64decode

def encode(data):
    return urlsafe_b64encode(bytes(data, 'utf-8'))

def decode(enc):
    return urlsafe_b64decode(enc).decode()

print(encode('hi')) # b'aGk='
print(decode(encode('hi'))) # 'hi'

2
हां, यदि आप सुरक्षा के बारे में उपद्रव नहीं कर रहे हैं, तो base64 एन्क्रिप्ट करने की तुलना में बेहतर है।
मार्टिन पीटर्स

एक-लाइनर नहीं होने के अन्य उत्तरों के बारे में: यह सवाल का बिंदु नहीं है। वे कॉल करने के लिए दो कार्यों के लिए पूछते हैं। और Fernet(key).encrypt(message)आपके बेस 64 कॉल की तरह सिर्फ एक अभिव्यक्ति है।
मार्टिन पीटर्स

और तुम चाहिए हटानेkey पूरी तरह। डेवलपर्स का भार ध्यान दे बिना कॉपी और स्टैक ओवरफ़्लो से चिपकाने के लिए जा रहे हैं और करेंगे कुंजी मान गुप्त किया जाना है। यदि आपको इसे शामिल करना चाहिए, तो बहुत कम से कम इसका उपयोग न करें और किसी भी तरह से उपयोग किए जाने पर चेतावनी दें या अपवाद बढ़ाएं। प्रतिलिपि कार्यों को देने के लिए कॉपी-एंड-पेस्ट संस्कृति और अपनी जिम्मेदारियों की मूर्खता को कम मत समझो।
मार्टिन पीटर्स

3

मैं 4 समाधान दूंगा:

1) cryptographyलाइब्रेरी के साथ फर्नेट एन्क्रिप्शन का उपयोग करना

यहां पैकेज का उपयोग करके एक समाधान है cryptography, जिसे आप हमेशा की तरह स्थापित कर सकते हैं pip install cryptography:

import base64
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

def cipherFernet(password):
    key = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=b'abcd', iterations=1000, backend=default_backend()).derive(password)
    return Fernet(base64.urlsafe_b64encode(key))

def encrypt1(plaintext, password):
    return cipherFernet(password).encrypt(plaintext)

def decrypt1(ciphertext, password):
    return cipherFernet(password).decrypt(ciphertext)

# Example:

print(encrypt1(b'John Doe', b'mypass'))  
# b'gAAAAABd53tHaISVxFO3MyUexUFBmE50DUV5AnIvc3LIgk5Qem1b3g_Y_hlI43DxH6CiK4YjYHCMNZ0V0ExdF10JvoDw8ejGjg=='
print(decrypt1(b'gAAAAABd53tHaISVxFO3MyUexUFBmE50DUV5AnIvc3LIgk5Qem1b3g_Y_hlI43DxH6CiK4YjYHCMNZ0V0ExdF10JvoDw8ejGjg==', b'mypass')) 
# b'John Doe'
try:  # test with a wrong password
    print(decrypt1(b'gAAAAABd53tHaISVxFO3MyUexUFBmE50DUV5AnIvc3LIgk5Qem1b3g_Y_hlI43DxH6CiK4YjYHCMNZ0V0ExdF10JvoDw8ejGjg==', b'wrongpass')) 
except InvalidToken:
    print('Wrong password')

आप अपने स्वयं के नमक, पुनरावृत्ति गणना आदि के साथ अनुकूलित कर सकते हैं। यह कोड @ HCLivess के उत्तर से बहुत दूर नहीं है, लेकिन लक्ष्य यहां तैयार-से-उपयोग encryptऔर decryptकार्यों के लिए है। स्रोत: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet

नोट: का उपयोग करें .encode()और .decode()हर जगह अगर आप 'John Doe'बाइट्स के बजाय तार चाहते हैं b'John Doe'


2) Cryptoपुस्तकालय के साथ सरल एईएस एन्क्रिप्शन

यह पायथन 3 के साथ काम करता है:

import base64
from Crypto import Random
from Crypto.Hash import SHA256
from Crypto.Cipher import AES

def cipherAES(password, iv):
    key = SHA256.new(password).digest()
    return AES.new(key, AES.MODE_CFB, iv)

def encrypt2(plaintext, password):
    iv = Random.new().read(AES.block_size)
    return base64.b64encode(iv + cipherAES(password, iv).encrypt(plaintext))

def decrypt2(ciphertext, password):
    d = base64.b64decode(ciphertext)
    iv, ciphertext = d[:AES.block_size], d[AES.block_size:]
    return cipherAES(password, iv).decrypt(ciphertext)

# Example:    

print(encrypt2(b'John Doe', b'mypass'))
print(decrypt2(b'B/2dGPZTD8V22cIVKfp2gD2tTJG/UfP/', b'mypass'))
print(decrypt2(b'B/2dGPZTD8V22cIVKfp2gD2tTJG/UfP/', b'wrongpass'))  # wrong password: no error, but garbled output

नोट: आप हटा सकते हैं base64.b64encodeऔर .b64decodeयदि आप पाठ-पठनीय आउटपुट और / या नहीं चाहते हैं, तो आप किसी भी तरह बाइनरी फ़ाइल के रूप में डिस्क पर सिफर को सहेजना चाहते हैं।


3) बेहतर पासवर्ड कुंजी व्युत्पत्ति समारोह और परीक्षण की क्षमता का उपयोग करके एईएस अगर "गलत पासवर्ड दर्ज", Cryptoपुस्तकालय के साथ

एईएस "सीएफबी मोड" के साथ समाधान 2) ठीक है, लेकिन इसमें दो कमियां हैं: तथ्य यह है कि SHA256(password)लुकअप टेबल के साथ आसानी से भंगुर किया जा सकता है, और अगर कोई गलत पासवर्ड दर्ज किया गया है तो परीक्षण का कोई तरीका नहीं है। यह "जीसीएम मोड" में एईएस के उपयोग से यहां हल किया गया है, जैसा कि एईएस में चर्चा की गई है : यह कैसे पता लगाया जाए कि एक खराब पासवर्ड दर्ज किया गया है? और यह कहने का तरीका "आपके द्वारा दर्ज किया गया पासवर्ड गलत है" सुरक्षित है? :

import Crypto.Random, Crypto.Protocol.KDF, Crypto.Cipher.AES

def cipherAES_GCM(pwd, nonce):
    key = Crypto.Protocol.KDF.PBKDF2(pwd, nonce, count=100000)
    return Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_GCM, nonce=nonce, mac_len=16)

def encrypt3(plaintext, password):
    nonce = Crypto.Random.new().read(16)
    return nonce + b''.join(cipherAES_GCM(password, nonce).encrypt_and_digest(plaintext))  # you case base64.b64encode it if needed

def decrypt3(ciphertext, password):
    nonce, ciphertext, tag = ciphertext[:16], ciphertext[16:len(ciphertext)-16], ciphertext[-16:]
    return cipherAES_GCM(password, nonce).decrypt_and_verify(ciphertext, tag)

# Example:

print(encrypt3(b'John Doe', b'mypass'))
print(decrypt3(b'\xbaN_\x90R\xdf\xa9\xc7\xd6\x16/\xbb!\xf5Q\xa9]\xe5\xa5\xaf\x81\xc3\n2e/("I\xb4\xab5\xa6ezu\x8c%\xa50', b'mypass'))
try:
    print(decrypt3(b'\xbaN_\x90R\xdf\xa9\xc7\xd6\x16/\xbb!\xf5Q\xa9]\xe5\xa5\xaf\x81\xc3\n2e/("I\xb4\xab5\xa6ezu\x8c%\xa50', b'wrongpass'))
except ValueError:
    print("Wrong password")

4) RC4 का उपयोग करना (कोई पुस्तकालय की आवश्यकता नहीं)

Https://github.com/bozhu/RC4-Python/blob/master/rc4.py से अनुकूलित ।

def PRGA(S):
    i = 0
    j = 0
    while True:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        yield S[(S[i] + S[j]) % 256]

def encryptRC4(plaintext, key, hexformat=False):
    key, plaintext = bytearray(key), bytearray(plaintext)  # necessary for py2, not for py3
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    keystream = PRGA(S)
    return b''.join(b"%02X" % (c ^ next(keystream)) for c in plaintext) if hexformat else bytearray(c ^ next(keystream) for c in plaintext)

print(encryptRC4(b'John Doe', b'mypass'))                           # b'\x88\xaf\xc1\x04\x8b\x98\x18\x9a'
print(encryptRC4(b'\x88\xaf\xc1\x04\x8b\x98\x18\x9a', b'mypass'))   # b'John Doe'

(नवीनतम संपादनों के बाद से आउट किया गया था, लेकिन भविष्य के संदर्भ के लिए रखा गया): मुझे विंडोज़ + पायथन 3.6 + का उपयोग करने में समस्याएँ थीं ( या विंडोज़ पर pycryptoसक्षम नहीं pip install pycrypto) या pycryptodomeइसमें दिए गए सभी उत्तर, from Crypto.Cipher import XORक्योंकि XORइस pycryptoकांटे का समर्थन नहीं किया गया है ;) समाधान का उपयोग कर ... AESविफल TypeError: Object type <class 'str'> cannot be passed to C code) के साथ भी । इसके अलावा, पुस्तकालय simple-cryptपर pycryptoनिर्भरता होती है, इसलिए यह एक विकल्प नहीं है।


1
आप नमक और पुनरावृत्ति की गिनती को हार्डकोड नहीं करना चाहते हैं; एक यादृच्छिक नमक उत्पन्न करें और एन्क्रिप्शन पर पुनरावृत्ति गणना को कॉन्फ़िगर करें, एन्क्रिप्शन परिणाम में उस जानकारी को शामिल करें, और डिक्रिप्शन के मानों को निकालें और उपयोग करें। नमक आपको किसी दिए गए संदेश पर पुन: उपयोग किए गए पासवर्ड की तुच्छ मान्यता से बचाता है, पुनरावृत्ति एल्गोरिथम को भविष्य के प्रमाणों की गणना करता है।
मार्टिन पीटर्स

हाँ, बेशक @MartijnPieters, लेकिन लक्ष्य यहाँ ओपी के अनुरोध के अनुसार सरल प्रयोजनों के लिए एक सरल कोड है, दो मापदंडों के साथ : सादा पाठ + पासवर्ड। बेशक अधिक जटिल परिदृश्य (यानी एक डेटाबेस) के लिए, आप इन सभी अतिरिक्त मापदंडों का उपयोग करेंगे।
बसज

अतिरिक्त मापदंडों की कोई आवश्यकता नहीं है! मैं उस जानकारी को शामिल करता हूं जो कि अपारदर्शी रिटर्न वैल्यू में एन्कोडेड हैpassword_encrypt()
मार्टिन पीटर्स

@MartijnPieters वास्तव में अच्छा समाधान।
बसज

2

यह काम करता है लेकिन पासवर्ड की लंबाई बिल्कुल होनी चाहिए 8। यह सरल है और pyDes की आवश्यकता है ।

from pyDes import *

def encode(data,password):
    k = des(password, CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
    d = k.encrypt(data)
    return d

def decode(data,password):
    k = des(password, CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
    d = k.decrypt(data)
    return d

x = encode('John Doe', 'mypass12')
y = decode(x,'mypass12')

print x
print y

उत्पादन:

³.\Þ\åS¾+æÅ`;Ê
John Doe

एक निश्चित IV का उपयोग न करें! IV को रैंडमाइज करें और इसके बजाय इसे सिफरटेक्स्ट के साथ शामिल करें। अन्यथा आप ईसीबी मोड का भी उपयोग कर सकते हैं; बार-बार सादे पाठ संदेश पहचानने के लिए अन्यथा तुच्छ हैं।
मार्टिन पीटर्स

इसके अलावा, pyDes परियोजना मृत प्रतीत होती है; मुखपृष्ठ समाप्त हो गया है, और PyPI पर अंतिम रिलीज़ अब 9 साल की है।
मार्टिन पीटर्स

2

@Qneill कोड का एक अन्य कार्यान्वयन जिसमें मूल संदेश के CRC चेकसम शामिल हैं, यह एक अपवाद फेंक देता है यदि चेक विफल हो जाता है:

import hashlib
import struct
import zlib

def vigenere_encode(text, key):
    text = '{}{}'.format(text, struct.pack('i', zlib.crc32(text)))

    enc = []
    for i in range(len(text)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(text[i]) + ord(key_c)) % 256)
        enc.append(enc_c)

    return base64.urlsafe_b64encode("".join(enc))


def vigenere_decode(encoded_text, key):
    dec = []
    encoded_text = base64.urlsafe_b64decode(encoded_text)
    for i in range(len(encoded_text)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(encoded_text[i]) - ord(key_c)) % 256)
        dec.append(dec_c)

    dec = "".join(dec)
    checksum = dec[-4:]
    dec = dec[:-4]

    assert zlib.crc32(dec) == struct.unpack('i', checksum)[0], 'Decode Checksum Error'

    return dec

2

आप अपने स्ट्रिंग को पासवर्ड से एन्क्रिप्ट करने के लिए एईएस का उपयोग कर सकते हैं। हालाँकि, आप एक मजबूत पर्याप्त पासवर्ड चुनना चाहते हैं ताकि लोग आसानी से अनुमान न लगा सकें कि यह क्या है (क्षमा करें, मैं इसकी मदद नहीं कर सकता। मैं एक wannabe सुरक्षा weenie हूं)।

AES एक अच्छे कुंजी आकार के साथ मजबूत है, लेकिन यह PyCrypto के साथ उपयोग करना भी आसान है।


3
धन्यवाद एलन। लेकिन स्पष्टीकरण के लिए, मैं खुद पासवर्ड एन्क्रिप्ट नहीं कर रहा हूं। उपरोक्त उदाहरण में, मैं पासवर्ड "मायपास" के अनुसार स्ट्रिंग "जॉन डो" को एन्क्रिप्ट कर रहा हूं, जो कि एक साधारण पासवर्ड है जो मैं अपने स्रोत कोड में उपयोग करता हूं। उपयोगकर्ता पासवर्ड शामिल नहीं हैं, न ही कोई अन्य बहुत ही संवेदनशील जानकारी है। मैंने इसे स्पष्ट करने के लिए अपने प्रश्न का संपादन किया।
RexE

1
एईएस महान है, अगर सही तरीके से उपयोग किया जाता है। हालांकि इसे गलत तरीके से उपयोग करना आसान है; यहाँ कम से कम एक उत्तर है जो एक असुरक्षित ब्लॉक सिफर मोड का उपयोग करता है, एक और दो जो आईवी मूल्य को संभालने में गड़बड़ी करते हैं। फर्नेट जैसी अच्छी तरह से परिभाषित नुस्खा के साथ एक अच्छी लाइब्रेरी का उपयोग करने के लिए बेहतर है!
मार्टिन पीटर्स

दरअसल, यह एक बहुत ही सूक्ष्म अवलोकन है। मैंने एक बार IV को फंबल किया है।
एलन

0

बाहरी पुस्तकालय गुप्त-कुंजी एन्क्रिप्शन एल्गोरिदम प्रदान करते हैं।

उदाहरण के लिए, CypherPyCrypto में मॉड्यूल कई एन्क्रिप्शन एल्गोरिदम का चयन प्रदान करता है:

  • Crypto.Cipher.AES
  • Crypto.Cipher.ARC2
  • Crypto.Cipher.ARC4
  • Crypto.Cipher.Blowfish
  • Crypto.Cipher.CAST
  • Crypto.Cipher.DES
  • Crypto.Cipher.DES3
  • Crypto.Cipher.IDEA
  • Crypto.Cipher.RC5
  • Crypto.Cipher.XOR

MeTooCrypto OpenSSL केPython लिए एक आवरण है , और एक पूर्ण शक्ति सामान्य उद्देश्य क्रिप्टोग्राफी पुस्तकालय प्रदान करता है। सममित सिफर (एईएस की तरह) शामिल हैं।


0

यदि आप सुरक्षित एन्क्रिप्शन चाहते हैं:

अजगर 2 के लिए, आपको keyczar http://www.keyczar.org/ का उपयोग करना चाहिए

अजगर 3 के लिए, जब तक कि कीकर उपलब्ध न हो, मैंने सरल-क्रिप्ट पर लिखा है http://pypi.python.org/pypi/simple-crypt

ये दोनों प्रमुख मजबूती का उपयोग करेंगे जो उन्हें यहां के अन्य उत्तरों की तुलना में अधिक सुरक्षित बनाता है। और जब से वे उपयोग करने में आसान होते हैं, तब भी आप उनका उपयोग करना चाह सकते हैं, जब सुरक्षा गंभीर न हो ...


से Keyczar भंडार : महत्वपूर्ण नोट: Keyczar मान्य नहीं है। Keyczar डेवलपर्स की सिफारिश Tink , लेकिन वहाँ Tink का कोई अजगर संस्करण है।
मार्टिन पीटर्स

0

इसलिए, जैसा कि कुछ भी नहीं है महत्वपूर्ण मिशन को एनकोड किया जा रहा है , और आप सिर्फ अश्लीलता के लिए एन्क्रिप्ट करना चाहते हैं ।

मुझे कैसर का सिफर प्रस्तुत करने दो

यहां छवि विवरण दर्ज करें

सीज़र की सिफर या सीज़र शिफ्ट, सबसे सरल और सबसे व्यापक रूप से ज्ञात एन्क्रिप्शन तकनीकों में से एक है। यह एक प्रकार का स्थानापन्न सिफर है जिसमें प्लेटेक्स्ट के प्रत्येक अक्षर को वर्ण के नीचे कुछ निश्चित संख्या में अक्षरों द्वारा प्रतिस्थापित किया जाता है। उदाहरण के लिए, 3 की बाईं पारी के साथ, डी को ए से बदल दिया जाएगा, ई बी हो जाएगा, और इसी तरह।

आपके संदर्भ के लिए नमूना कोड:

def encrypt(text,s): 
        result = "" 

        # traverse text 
        for i in range(len(text)): 
            char = text[i] 

            # Encrypt uppercase characters 
            if (char.isupper()): 
                result += chr((ord(char) + s-65) % 26 + 65) 

            # Encrypt lowercase characters 
            else: 
                result += chr((ord(char) + s - 97) % 26 + 97) 

        return result 

    def decrypt(text,s): 
        result = "" 

        # traverse text 
        for i in range(len(text)): 
            char = text[i] 

            # Encrypt uppercase characters 
            if (char.isupper()): 
                result += chr((ord(char) - s-65) % 26 + 65) 

            # Encrypt lowercase characters 
            else: 
                result += chr((ord(char) - s - 97) % 26 + 97) 

        return result 

    #check the above function 
    text = "ATTACKATONCE"
    s = 4
    print("Text  : " + text) 
    print("Shift : " + str(s)) 
    print("Cipher: " + encrypt(text,s))
    print("Original text: " + decrypt(encrypt(text,s),s))

लाभ: यह आपकी आवश्यकताओं को पूरा करता है और सरल है और एन्कोडिंग thing'y 'करता है।

नुकसान: साधारण जानवर बल एल्गोरिदम द्वारा क्रैक किया जा सकता है (अत्यधिक किसी को भी सभी अतिरिक्त परिणामों के माध्यम से जाने का प्रयास नहीं किया जाएगा)।


0

संदर्भ के लिए डीकोड और एनकोड के साथ एक और कोड जोड़ना

import base64

def encode(key, string):
    encoded_chars = []
    for i in range(len(string)):
        key_c = key[i % len(key)]
        encoded_c = chr(ord(string[i]) + ord(key_c) % 128)
        encoded_chars.append(encoded_c)
    encoded_string = "".join(encoded_chars)
    arr2 = bytes(encoded_string, 'utf-8')
    return base64.urlsafe_b64encode(arr2)

def decode(key, string):
    encoded_chars = []
    string = base64.urlsafe_b64decode(string)
    string = string.decode('utf-8')
    for i in range(len(string)):
        key_c = key[i % len(key)]
        encoded_c = chr(ord(string[i]) - ord(key_c) % 128)
        encoded_chars.append(encoded_c)
    encoded_string = "".join(encoded_chars)
    return encoded_string

def main():
    answer = str(input("EorD"))
    if(answer in ['E']):
        #ENCODE
        file = open("D:\enc.txt")
        line = file.read().replace("\n", " NEWLINEHERE ")
        file.close()
        text = encode("4114458",line)
        fnew = open("D:\\new.txt","w+")
        fnew.write(text.decode('utf-8'))
        fnew.close()
    else:
        #DECODE
        file = open("D:\\new.txt",'r+')
        eline = file.read().replace("NEWLINEHERE","\n")
        file.close()
        print(eline)
        eline = eline.encode('utf-8')
        dtext=decode("4114458",eline)
        print(dtext)
        fnew = open("D:\\newde.txt","w+")
        fnew.write(dtext)
        fnew.close

if __name__ == '__main__':
    main()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.