Search code examples
pythonencryptionpycryptoin-memory

Encrypt/Decrypt an animated gif in Python without storing the final copy to HD


Okay, let's try this again.

I'm trying to encrypt an animated gif with PyCrypto to be sent to someone. After the receiver gets it, they should be able to run my pycrypto script and view the animated image- WITHOUT storing the unencrypted file to the hard drive. Essentially I'm trying to save the unencrypted file in-memory so that it can be accessed by another library without saving it to the disk.

For encryption I've been using

import os, random, struct
from Crypto.Cipher import AES

def encrypt_file(key='8c57d066796428d5a8f4b012155dad90', in_filename='tile.png', out_filename=None, chunksize=8192):
    """ Encrypts a file using AES (CBC mode) with the
        given key.

        key:
            The encryption key - a string that must be
            either 16, 24 or 32 bytes long. Longer keys
            are more secure.

        in_filename:
            Name of the input file

        out_filename:
            If None, '<in_filename>.enc' will be used.

        chunksize:
            Sets the size of the chunk which the function
            uses to read and encrypt the file. Larger chunk
            sizes can be faster for some files and machines.
            chunksize must be divisible by 16.
    """
    if not out_filename:
        out_filename = in_filename + '.enc'

    iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    filesize = os.path.getsize(in_filename)

    with open(in_filename, 'r') as infile:
        with open(out_filename, 'w') as outfile:
            outfile.write(struct.pack('<Q', filesize))
            outfile.write(iv)

            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += ' ' * (16 - len(chunk) % 16)

                outfile.write(encryptor.encrypt(chunk))

, but that doesn't seem to be doing anything at all. I don't even know where to begin on the decryption part because again, I need to be able to access the decrypted file without storing it to the hard drive.

Thanks guys.


Solution

  • How about using StringIO instead of an actual disc file called out_filename?

    Just use a virtual disc with the same structure.

    Example:

    import StringIO
    
    f=StringIO.StringIO()
    
    for line in ['line {}\n'.format(i) for i in range(25)]:
        f.write(line)
    
    f.seek(0)
    
    for line in f:
        print line.strip() 
    

    So you would need to replace with open(out_filename, 'w') as outfile: ... with a call to outfile=StringIO.StringIO() and the rest should be the same.

    Like so:

    with open(in_filename, 'r') as infile:
        outfile=StringIO.StringIO()
        outfile.write(struct.pack('<Q', filesize))
        outfile.write(iv)
    
        while True:
            chunk = infile.read(chunksize)
            if len(chunk) == 0:
                break
            elif len(chunk) % 16 != 0:
                chunk += ' ' * (16 - len(chunk) % 16)
    
            outfile.write(encryptor.encrypt(chunk))