0

Given below is the code(not complete yet) I have written to encrypt and decrypt files using python with the pycrypto module.

from Crypto.Hash import SHA256 
from Crypto.Cipher import AES 
import getpass

class ED(object):   
  def getfromuser(self,choice):
    if choice=='key':
        key=getpass.getpass('Enter AES Key (minimum 16 characters): ')
        if len(key)<16:
            print 'Key entered too short. Please try again.'
            self.getfromuser(choice)
        key=key+str(8-len(key)%8)*(8-len(key)%8)
        return key
    if choice=='IV':
        IV_seed=raw_input('Enter a seed for the IV: ')
        IV=SHA256.new()
        IV.update(IV_seed)
        IV.digest()
        return str(IV)[0:16]

  def AESEncrypt(self,key,IV,source,dest):

    f=open(source,"r")
    fstream=f.read()
    f.close()

    AES_stream=AES.new(key,AES.MODE_CBC,IV)
    AES_encrypted=AES_stream.encrypt(fstream)

    with open(dest,"w") as write_file:
        write_file.write(AES_encrypted)

  def AESDecrypt(self,key,IV,source,dest):
    f=open(source,"r")
    fstream=f.read()
    f.close()
    AES_stream=AES.new(key,AES.MODE_CBC,IV)
    AES_decrypted=AES_stream.decrypt(fstream)
    with open(dest,"w") as write_file:
        write_file.write(AES_decrypted)

When I tried to encrypt a JPG file using this I got the following error:

    AES_encrypted=AES_stream.encrypt(fstream)
    ValueError: Input strings must be a multiple of 16 in length

I tried it on an mp4 file and it worked fine: the encryption and the decryption too.

What is the cause of this error and how do I fix it?

ritratt
  • 1,703
  • 4
  • 25
  • 45
  • 2
    Did the mp4 file happen to have a file size that is a multiple of 16? Remember, AES is a *block* cipher. It sounds like if your last block isn't complete, you'll need to pad it. – FatalError Jul 08 '12 at 16:17
  • 1
    Why do you ask the user to enter the IV instead of generating a random one? And why do you stuff a plaintext password into the key instead of using a KDF, such as PBKDF2? – CodesInChaos Jul 08 '12 at 16:19
  • #FatalError: You are right. So then how do I go about padding the jpg file without corrupting it? @CodeInChaos: I am well aware of cryptographic protocols. However, my question does not pertain to that. I appreciate your suggestion but let's stick to my question. Thanks! – ritratt Jul 08 '12 at 16:23
  • 1
    The program told you that your ciphertext doesn't have a length that's a multiple of 16 bytes. Did you check its length? How long is it, how long is the plaintext? It's likely a padding related issue. – CodesInChaos Jul 08 '12 at 16:26
  • Yes I checked it. The JPG file size is not a multiple of 16. Looking for ways to pad a jpg file now...and then remove the padding at the time of decryption to prevent corruption. – ritratt Jul 08 '12 at 16:28
  • I'm sure you can tell the AES class that it should take care of padding. btw your indention looks really weird. Is that valid python? – CodesInChaos Jul 08 '12 at 16:30
  • it is python. fixed the indent. Will check pycrypto docs to see if padding can be handled. – ritratt Jul 08 '12 at 19:46

1 Answers1

3

I found the solution. If one does not want the hassle of padding, one can use the CFB (Cipher feedback) mode as follows:

AES_stream=AES.new(key,AES.MODE_CFB,IV)

ritratt
  • 1,703
  • 4
  • 25
  • 45