Encrypt & Decrypt using PyCrypto AES 256

后端 未结 12 902
夕颜
夕颜 2020-11-22 13:07

I\'m trying to build two functions using PyCrypto that accept two parameters: the message and the key, and then encrypt/decrypt the message.

I found several links on

相关标签:
12条回答
  • 2020-11-22 13:08

    It's little late but i think this will be very helpful. No one mention about use scheme like PKCS#7 padding. You can use it instead the previous functions to pad(when do encryption) and unpad(when do decryption).i will provide the full Source Code below.

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

    0 讨论(0)
  • 2020-11-22 13:08
    from Crypto import Random
    from Crypto.Cipher import AES
    import base64
    
    BLOCK_SIZE=16
    def trans(key):
         return md5.new(key).digest()
    
    def encrypt(message, passphrase):
        passphrase = trans(passphrase)
        IV = Random.new().read(BLOCK_SIZE)
        aes = AES.new(passphrase, AES.MODE_CFB, IV)
        return base64.b64encode(IV + aes.encrypt(message))
    
    def decrypt(encrypted, passphrase):
        passphrase = trans(passphrase)
        encrypted = base64.b64decode(encrypted)
        IV = encrypted[:BLOCK_SIZE]
        aes = AES.new(passphrase, AES.MODE_CFB, IV)
        return aes.decrypt(encrypted[BLOCK_SIZE:])
    
    0 讨论(0)
  • 2020-11-22 13:09

    Here is my implementation and works for me with some fixes and enhances the alignment of the key and secret phrase with 32 bytes and iv to 16 bytes:

    import base64
    import hashlib
    from Crypto import Random
    from Crypto.Cipher import AES
    
    class AESCipher(object):
    
        def __init__(self, key): 
            self.bs = AES.block_size
            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.encode()))
    
        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:])]
    
    0 讨论(0)
  • 2020-11-22 13:11

    Another take on this (heavily derived from solutions above) but

    • uses null for padding
    • does not use lambda (never been a fan)
    • tested with python 2.7 and 3.6.5

      #!/usr/bin/python2.7
      # you'll have to adjust for your setup, e.g., #!/usr/bin/python3
      
      
      import base64, re
      from Crypto.Cipher import AES
      from Crypto import Random
      from django.conf import settings
      
      class AESCipher:
          """
            Usage:
            aes = AESCipher( settings.SECRET_KEY[:16], 32)
            encryp_msg = aes.encrypt( 'ppppppppppppppppppppppppppppppppppppppppppppppppppppppp' )
            msg = aes.decrypt( encryp_msg )
            print("'{}'".format(msg))
          """
          def __init__(self, key, blk_sz):
              self.key = key
              self.blk_sz = blk_sz
      
          def encrypt( self, raw ):
              if raw is None or len(raw) == 0:
                  raise NameError("No value given to encrypt")
              raw = raw + '\0' * (self.blk_sz - len(raw) % self.blk_sz)
              raw = raw.encode('utf-8')
              iv = Random.new().read( AES.block_size )
              cipher = AES.new( self.key.encode('utf-8'), AES.MODE_CBC, iv )
              return base64.b64encode( iv + cipher.encrypt( raw ) ).decode('utf-8')
      
          def decrypt( self, enc ):
              if enc is None or len(enc) == 0:
                  raise NameError("No value given to decrypt")
              enc = base64.b64decode(enc)
              iv = enc[:16]
              cipher = AES.new(self.key.encode('utf-8'), AES.MODE_CBC, iv )
              return re.sub(b'\x00*$', b'', cipher.decrypt( enc[16:])).decode('utf-8')
      
    0 讨论(0)
  • 2020-11-22 13:12

    For someone who would like to use urlsafe_b64encode and urlsafe_b64decode, here are the version that're working for me (after spending some time with the unicode issue)

    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:]))
    
    0 讨论(0)
  • 2020-11-22 13:13

    Grateful for the other answers which inspired but didn't work for me.

    After spending hours trying to figure out how it works, I came up with the implementation below with the newest PyCryptodomex library (it is another story how I managed to set it up behind proxy, on Windows, in a virtualenv.. phew)

    Working on your implementation, remember to write down padding, encoding, encrypting steps (and vice versa). You have to pack and unpack keeping in mind the order.

    import base64
    import hashlib
    from Cryptodome.Cipher import AES
    from Cryptodome.Random import get_random_bytes
    
    __key__ = hashlib.sha256(b'16-character key').digest()
    
    def encrypt(raw):
        BS = AES.block_size
        pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
    
        raw = base64.b64encode(pad(raw).encode('utf8'))
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key= __key__, mode= AES.MODE_CFB,iv= iv)
        return base64.b64encode(iv + cipher.encrypt(raw))
    
    def decrypt(enc):
        unpad = lambda s: s[:-ord(s[-1:])]
    
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(__key__, AES.MODE_CFB, iv)
        return unpad(base64.b64decode(cipher.decrypt(enc[AES.block_size:])).decode('utf8'))
    
    0 讨论(0)
提交回复
热议问题