python - पीईक्रिप्टो एईएस 256 का उपयोग करके एन्क्रिप्ट और डिक्रिप्ट करें




encryption padding (6)

मैं PyCrypto का उपयोग करके दो फ़ंक्शंस बनाने की कोशिश कर रहा हूं जो दो पैरामीटर स्वीकार करते हैं: संदेश और कुंजी, और फिर संदेश को एन्क्रिप्ट / डिक्रिप्ट करें।

मुझे मदद करने के लिए वेब पर कई लिंक मिले, लेकिन उनमें से प्रत्येक में त्रुटियां हैं:

कोडेकोला में यह एक os.urandom का उपयोग करता है, जो PyCrypto द्वारा निराश है।

इसके अलावा, मैं जिस कुंजी को फ़ंक्शन को देता हूं उसे सटीक लंबाई की अपेक्षा रखने की गारंटी नहीं है। ऐसा करने के लिए मैं क्या कर सकता हूं?

इसके अलावा, कई तरीके हैं, जिनकी सिफारिश की जाती है? मुझे नहीं पता कि क्या उपयोग करना है: /

अंत में, चतुर्थ क्या है? क्या मैं एन्क्रिप्टिंग और डिक्रिप्टिंग के लिए एक अलग IV प्रदान कर सकता हूं, या यह एक अलग परिणाम में वापस आ जाएगा?

यहां तक ​​कि मैंने अभी तक क्या किया है:

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

BLOCK_SIZE=32

def encrypt(message, passphrase):
    # passphrase MUST be 16, 24 or 32 bytes long, how can I do that ?
    IV = Random.new().read(BLOCK_SIZE)
    aes = AES.new(passphrase, AES.MODE_CFB, IV)
    return base64.b64encode(aes.encrypt(message))

def decrypt(encrypted, passphrase):
    IV = Random.new().read(BLOCK_SIZE)
    aes = AES.new(passphrase, AES.MODE_CFB, IV)
    return aes.decrypt(base64.b64decode(encrypted))

आप क्रिप्टोग्राफिक हैश फ़ंक्शन (पायथन के बिल्टिन hash ) जैसे SHA-1 या SHA-256 का उपयोग करके मनमाने ढंग से पासवर्ड से पासफ्रेज प्राप्त कर सकते हैं। पायथन में मानक पुस्तकालय दोनों के लिए समर्थन शामिल है:

import hashlib

hashlib.sha1("this is my awesome password").digest() # => a 20 byte string
hashlib.sha256("another awesome password").digest() # => a 32 byte string

आप केवल [:16] या [:24] का उपयोग कर क्रिप्टोग्राफ़िक हैश मान को छोटा कर सकते हैं और यह आपके द्वारा निर्दिष्ट लंबाई तक इसकी सुरक्षा बनाए रखेगा।


इनपुट की लंबाई BLOCK_SIZE के एकाधिक नहीं होने पर आपको पैड के लिए निम्न दो फ़ंक्शंस (एन्क्रिप्शन कब करें) और अनपैड (डिक्रिप्शन करते समय) की आवश्यकता हो सकती है।

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
unpad = lambda s : s[:-ord(s[len(s)-1:])]

तो आप कुंजी की लंबाई पूछ रहे हैं? आप सीधे इसका उपयोग करने के बजाय कुंजी के md5sum का उपयोग कर सकते हैं।

अधिक, PyCrypto का उपयोग करने के अपने छोटे अनुभव के अनुसार, IV का उपयोग इनपुट के समान होने पर एन्क्रिप्शन के आउटपुट को मिश्रित करने के लिए किया जाता है, इसलिए IV को यादृच्छिक स्ट्रिंग के रूप में चुना जाता है, और फिर इसे एन्क्रिप्शन आउटपुट के हिस्से के रूप में उपयोग किया जाता है, और फिर संदेश को डिक्रिप्ट करने के लिए इसका इस्तेमाल करें।

और यहां मेरा कार्यान्वयन है, उम्मीद है कि यह आपके लिए उपयोगी होगा:

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

class AESCipher:
    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) ) 

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

किसी ऐसे व्यक्ति के लिए जो urlsafe_b64encode और urlsafe_b64decode का उपयोग करना चाहेगा, यहां वह संस्करण है जो मेरे लिए काम कर रहा है (यूनिकोड समस्या के साथ कुछ समय बिताने के बाद)

BS = 16
key = hashlib.md5(settings.SECRET_KEY).hexdigest()[:BS]
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[:-ord(s[len(s)-1:])]

class AESCipher:
    def __init__(self, key):
        self.key = key

    def encrypt(self, raw):
        raw = pad(raw)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.urlsafe_b64encode(iv + cipher.encrypt(raw)) 

    def decrypt(self, enc):
        enc = base64.urlsafe_b64decode(enc.encode('utf-8'))
        iv = enc[:BS]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return unpad(cipher.decrypt(enc[BS:]))

दूसरों के लाभ के लिए, यहां मेरा डिक्रिप्शन कार्यान्वयन है जो मुझे @ कैरिल और @ मर्कस के उत्तरों के संयोजन से मिला है। यह मानता है कि यह HTTP अनुरोध के माध्यम से एन्क्रिप्टेड टेक्स्ट उद्धृत और बेस 64 एन्कोडेड के साथ आ रहा है।

import base64
import urllib2
from Crypto.Cipher import AES


def decrypt(quotedEncodedEncrypted):
    key = 'SecretKey'

    encodedEncrypted = urllib2.unquote(quotedEncodedEncrypted)

    cipher = AES.new(key)
    decrypted = cipher.decrypt(base64.b64decode(encodedEncrypted))[:16]

    for i in range(1, len(base64.b64decode(encodedEncrypted))/16):
        cipher = AES.new(key, AES.MODE_CBC, base64.b64decode(encodedEncrypted)[(i-1)*16:i*16])
        decrypted += cipher.decrypt(base64.b64decode(encodedEncrypted)[i*16:])[:16]

    return decrypted.strip()

यह बहुत देर हो चुकी है लेकिन मुझे लगता है कि यह बहुत उपयोगी होगा। पीकेसीएस # 7 पैडिंग जैसी उपयोग योजना के बारे में कोई भी उल्लेख नहीं करता है। आप इसके बजाय पिछले कार्यों को पैड (जब एन्क्रिप्शन करते हैं) और अनपैड (डिक्रिप्शन करते समय) का उपयोग कर सकते हैं। मैं नीचे पूर्ण स्रोत कोड प्रदान करूंगा।

import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
import pkcs7
class Encryption:

    def __init__(self):
        pass

    def Encrypt(self, PlainText, SecurePassword):
        pw_encode = SecurePassword.encode('utf-8')
        text_encode = PlainText.encode('utf-8')

        key = hashlib.sha256(pw_encode).digest()
        iv = Random.new().read(AES.block_size)

        cipher = AES.new(key, AES.MODE_CBC, iv)
        pad_text = pkcs7.encode(text_encode)
        msg = iv + cipher.encrypt(pad_text)

        EncodeMsg = base64.b64encode(msg)
        return EncodeMsg

    def Decrypt(self, Encrypted, SecurePassword):
        decodbase64 = base64.b64decode(Encrypted.decode("utf-8"))
        pw_encode = SecurePassword.decode('utf-8')

        iv = decodbase64[:AES.block_size]
        key = hashlib.sha256(pw_encode).digest()

        cipher = AES.new(key, AES.MODE_CBC, iv)
        msg = cipher.decrypt(decodbase64[AES.block_size:])
        pad_text = pkcs7.decode(msg)

        decryptedString = pad_text.decode('utf-8')
        return decryptedString

import StringIO
import binascii


def decode(text, k=16):
    nl = len(text)
    val = int(binascii.hexlify(text[-1]), 16)
    if val > k:
        raise ValueError('Input is not padded or padding is corrupt')

    l = nl - val
    return text[:l]


def encode(text, k=16):
    l = len(text)
    output = StringIO.StringIO()
    val = k - (l % k)
    for _ in xrange(val):
        output.write('%02x' % val)
    return text + binascii.unhexlify(output.getvalue())


यहां मेरे कार्यान्वयन और कुछ फिक्स के साथ मेरे लिए काम करता है और 32 बाइट्स और iv से 16 बाइट्स के साथ कुंजी और गुप्त वाक्यांश के संरेखण को बढ़ाता है:

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

class AESCipher(object):

    def __init__(self, key): 
        self.bs = 32
        self.key = hashlib.sha256(key.encode()).digest()

    def encrypt(self, raw):
        raw = self._pad(raw)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw))

    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)

    @staticmethod
    def _unpad(s):
        return s[:-ord(s[len(s)-1:])]




initialization-vector