Cyril N. Cyril N. - 1 year ago 242
Python Question

Encrypt & Decrypt using PyCrypto AES 256

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 the web to help me out, but each one of them has flaws:

This one at codekoala uses os.urandom, which is discouraged by PyCrypto.

Moreover, the key I give to the function is not guaranteed to have the exact length expected. What can I do to make that happen ?

Also, there are several modes, which one is recommended? I don't know what to use :/

Finally, what exactly is the IV? Can I provide a different IV for encrypting and decrypting, or will this return in a different result?

Here's what I've done so far:

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


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

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

Answer Source

You may need the following two functions to pad(when do encryption) and unpad(when do decryption) when the length of input is not a multiple of 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:])]

So you're asking the length of key? You can use the md5sum of the key rather than use it directly.

More, according to my little experience of using PyCrypto, the IV is used to mix up the output of a encryption when input is same, so the IV is chosen as a random string, and use it as part of the encryption output, and then use it to decrypt the message.

And here's my implementation, hope it will be useful for you:

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 = AES.block_size )
        cipher = 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.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))